shared code (new strerror stuff)
This commit is contained in:
parent
1ffd54f834
commit
a9ae4de43c
141
src/utils/log.h
141
src/utils/log.h
@ -1,35 +1,18 @@
|
||||
/* Copyright (C) 2014 J.F.Dockes
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
/* Copyright (C) 2014-2019 J.F.Dockes
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Copyright (C) 2006-2016 J.F.Dockes
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
#ifndef _LOG_H_X_INCLUDED_
|
||||
#define _LOG_H_X_INCLUDED_
|
||||
@ -57,7 +40,7 @@
|
||||
class Logger {
|
||||
public:
|
||||
/** Initialize logging to file name. Use "stderr" for stderr
|
||||
output. Creates the singleton logger object */
|
||||
output. Creates the singleton logger object */
|
||||
static Logger *getTheLog(const std::string& fn);
|
||||
|
||||
bool reopen(const std::string& fn);
|
||||
@ -97,7 +80,7 @@ private:
|
||||
#define LOGGER_PRT (Logger::getTheLog("")->getstream())
|
||||
|
||||
#if LOGGER_THREADSAFE
|
||||
#define LOGGER_LOCK \
|
||||
#define LOGGER_LOCK \
|
||||
std::unique_lock<std::recursive_mutex> lock(Logger::getTheLog("")->getmutex())
|
||||
#else
|
||||
#define LOGGER_LOCK
|
||||
@ -107,63 +90,63 @@ private:
|
||||
#define LOGGER_LOCAL_LOGINC 0
|
||||
#endif
|
||||
|
||||
#define LOGGER_LEVEL (Logger::getTheLog("")->getloglevel() + \
|
||||
#define LOGGER_LEVEL (Logger::getTheLog("")->getloglevel() + \
|
||||
LOGGER_LOCAL_LOGINC)
|
||||
|
||||
#define LOGGER_DOLOG(L,X) LOGGER_PRT << ":" << L << ":" << \
|
||||
__FILE__ << ":" << __LINE__ << "::" << X \
|
||||
#define LOGGER_DOLOG(L,X) LOGGER_PRT << ":" << L << ":" << \
|
||||
__FILE__ << ":" << __LINE__ << "::" << X \
|
||||
<< std::flush
|
||||
|
||||
#if LOGGER_STATICVERBOSITY >= 7
|
||||
#define LOGDEB2(X) { \
|
||||
if (LOGGER_LEVEL >= Logger::LLDEB2) { \
|
||||
LOGGER_LOCK; \
|
||||
LOGGER_DOLOG(Logger::LLDEB2, X); \
|
||||
} \
|
||||
#define LOGDEB2(X) { \
|
||||
if (LOGGER_LEVEL >= Logger::LLDEB2) { \
|
||||
LOGGER_LOCK; \
|
||||
LOGGER_DOLOG(Logger::LLDEB2, X); \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define LOGDEB2(X)
|
||||
#endif
|
||||
|
||||
#if LOGGER_STATICVERBOSITY >= 6
|
||||
#define LOGDEB1(X) { \
|
||||
if (LOGGER_LEVEL >= Logger::LLDEB1) { \
|
||||
LOGGER_LOCK; \
|
||||
LOGGER_DOLOG(Logger::LLDEB1, X); \
|
||||
} \
|
||||
#define LOGDEB1(X) { \
|
||||
if (LOGGER_LEVEL >= Logger::LLDEB1) { \
|
||||
LOGGER_LOCK; \
|
||||
LOGGER_DOLOG(Logger::LLDEB1, X); \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define LOGDEB1(X)
|
||||
#endif
|
||||
|
||||
#if LOGGER_STATICVERBOSITY >= 5
|
||||
#define LOGDEB0(X) { \
|
||||
if (LOGGER_LEVEL >= Logger::LLDEB0) { \
|
||||
LOGGER_LOCK; \
|
||||
LOGGER_DOLOG(Logger::LLDEB0, X); \
|
||||
} \
|
||||
#define LOGDEB0(X) { \
|
||||
if (LOGGER_LEVEL >= Logger::LLDEB0) { \
|
||||
LOGGER_LOCK; \
|
||||
LOGGER_DOLOG(Logger::LLDEB0, X); \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define LOGDEB0(X)
|
||||
#endif
|
||||
|
||||
#if LOGGER_STATICVERBOSITY >= 4
|
||||
#define LOGDEB(X) { \
|
||||
if (LOGGER_LEVEL >= Logger::LLDEB) { \
|
||||
LOGGER_LOCK; \
|
||||
LOGGER_DOLOG(Logger::LLDEB, X); \
|
||||
} \
|
||||
#define LOGDEB(X) { \
|
||||
if (LOGGER_LEVEL >= Logger::LLDEB) { \
|
||||
LOGGER_LOCK; \
|
||||
LOGGER_DOLOG(Logger::LLDEB, X); \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define LOGDEB(X)
|
||||
#endif
|
||||
|
||||
#if LOGGER_STATICVERBOSITY >= 3
|
||||
#define LOGINF(X) { \
|
||||
if (LOGGER_LEVEL >= Logger::LLINF) { \
|
||||
LOGGER_LOCK; \
|
||||
LOGGER_DOLOG(Logger::LLINF, X); \
|
||||
} \
|
||||
#define LOGINF(X) { \
|
||||
if (LOGGER_LEVEL >= Logger::LLINF) { \
|
||||
LOGGER_LOCK; \
|
||||
LOGGER_DOLOG(Logger::LLINF, X); \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define LOGINF(X)
|
||||
@ -171,22 +154,22 @@ private:
|
||||
#define LOGINFO LOGINF
|
||||
|
||||
#if LOGGER_STATICVERBOSITY >= 2
|
||||
#define LOGERR(X) { \
|
||||
if (LOGGER_LEVEL >= Logger::LLERR) { \
|
||||
LOGGER_LOCK; \
|
||||
LOGGER_DOLOG(Logger::LLERR, X); \
|
||||
} \
|
||||
#define LOGERR(X) { \
|
||||
if (LOGGER_LEVEL >= Logger::LLERR) { \
|
||||
LOGGER_LOCK; \
|
||||
LOGGER_DOLOG(Logger::LLERR, X); \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define LOGERR(X)
|
||||
#endif
|
||||
|
||||
#if LOGGER_STATICVERBOSITY >= 1
|
||||
#define LOGFAT(X) { \
|
||||
if (LOGGER_LEVEL >= Logger::LLFAT) { \
|
||||
LOGGER_LOCK; \
|
||||
LOGGER_DOLOG(Logger::LLFAT, X); \
|
||||
} \
|
||||
#define LOGFAT(X) { \
|
||||
if (LOGGER_LEVEL >= Logger::LLFAT) { \
|
||||
LOGGER_LOCK; \
|
||||
LOGGER_DOLOG(Logger::LLFAT, X); \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define LOGFAT(X)
|
||||
@ -198,20 +181,18 @@ private:
|
||||
LOGERR(who << ": " << what << "(" << arg << "): errno " << errno << \
|
||||
": " << strerror(errno) << std::endl); \
|
||||
}
|
||||
#else // !WINDOWS->
|
||||
#if (_POSIX_C_SOURCE >= 200112L) && ! _GNU_SOURCE
|
||||
#define LOGSYSERR(who, what, arg) { \
|
||||
char buf[200]; buf[0] = 0; strerror_r(errno, buf, 200); \
|
||||
LOGERR(who << ": " << what << "(" << arg << "): errno " << errno << \
|
||||
": " << buf << std::endl); \
|
||||
}
|
||||
#else
|
||||
#else // not WINDOWS or sun
|
||||
|
||||
inline char *_log_check_strerror_r(int, char *errbuf) {return errbuf;}
|
||||
inline char *_log_check_strerror_r(char *cp, char *){return cp;}
|
||||
|
||||
#define LOGSYSERR(who, what, arg) { \
|
||||
char buf[200]; buf[0] = 0; \
|
||||
LOGERR(who << ": " << what << "(" << arg << "): errno " << errno << \
|
||||
": " << strerror_r(errno, buf, 200) << std::endl); \
|
||||
": " << _log_check_strerror_r( \
|
||||
strerror_r(errno, buf, 200), buf) << std::endl); \
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // not windows
|
||||
|
||||
#endif /* _LOG_H_X_INCLUDED_ */
|
||||
|
||||
@ -115,7 +115,7 @@ string stringtoupper(const string& i)
|
||||
extern int stringisuffcmp(const string& s1, const string& s2)
|
||||
{
|
||||
string::const_reverse_iterator r1 = s1.rbegin(), re1 = s1.rend(),
|
||||
r2 = s2.rbegin(), re2 = s2.rend();
|
||||
r2 = s2.rbegin(), re2 = s2.rend();
|
||||
while (r1 != re1 && r2 != re2) {
|
||||
char c1 = ::toupper(*r1);
|
||||
char c2 = ::toupper(*r2);
|
||||
@ -326,18 +326,18 @@ template <class T> bool stringToStrings(const string& s, T& tokens,
|
||||
}
|
||||
|
||||
template bool stringToStrings<list<string> >(const string&,
|
||||
list<string>&, const string&);
|
||||
list<string>&, const string&);
|
||||
template bool stringToStrings<vector<string> >(const string&,
|
||||
vector<string>&, const string&);
|
||||
vector<string>&, const string&);
|
||||
template bool stringToStrings<set<string> >(const string&,
|
||||
set<string>&, const string&);
|
||||
set<string>&, const string&);
|
||||
template bool stringToStrings<std::unordered_set<string> >
|
||||
(const string&, std::unordered_set<string>&, const string&);
|
||||
|
||||
template <class T> void stringsToString(const T& tokens, string& s)
|
||||
{
|
||||
for (typename T::const_iterator it = tokens.begin();
|
||||
it != tokens.end(); it++) {
|
||||
it != tokens.end(); it++) {
|
||||
bool hasblanks = false;
|
||||
if (it->find_first_of(" \t\n") != string::npos) {
|
||||
hasblanks = true;
|
||||
@ -382,10 +382,10 @@ template <class T> void stringsToCSV(const T& tokens, string& s,
|
||||
{
|
||||
s.erase();
|
||||
for (typename T::const_iterator it = tokens.begin();
|
||||
it != tokens.end(); it++) {
|
||||
it != tokens.end(); it++) {
|
||||
bool needquotes = false;
|
||||
if (it->empty() ||
|
||||
it->find_first_of(string(1, sep) + "\"\n") != string::npos) {
|
||||
it->find_first_of(string(1, sep) + "\"\n") != string::npos) {
|
||||
needquotes = true;
|
||||
}
|
||||
if (it != tokens.begin()) {
|
||||
@ -409,7 +409,7 @@ template <class T> void stringsToCSV(const T& tokens, string& s,
|
||||
}
|
||||
template void stringsToCSV<list<string> >(const list<string>&, string&, char);
|
||||
template void stringsToCSV<vector<string> >(const vector<string>&, string&,
|
||||
char);
|
||||
char);
|
||||
|
||||
void stringToTokens(const string& str, vector<string>& tokens,
|
||||
const string& delims, bool skipinit)
|
||||
@ -418,7 +418,7 @@ void stringToTokens(const string& str, vector<string>& tokens,
|
||||
|
||||
// Skip initial delims, return empty if this eats all.
|
||||
if (skipinit &&
|
||||
(startPos = str.find_first_not_of(delims, 0)) == string::npos) {
|
||||
(startPos = str.find_first_not_of(delims, 0)) == string::npos) {
|
||||
return;
|
||||
}
|
||||
while (startPos < str.size()) {
|
||||
@ -569,13 +569,13 @@ string escapeHtml(const string& in)
|
||||
{
|
||||
string out;
|
||||
for (string::size_type pos = 0; pos < in.length(); pos++) {
|
||||
switch(in.at(pos)) {
|
||||
case '<': out += "<"; break;
|
||||
case '>': out += ">"; break;
|
||||
case '&': out += "&"; break;
|
||||
case '"': out += """; break;
|
||||
default: out += in.at(pos); break;
|
||||
}
|
||||
switch(in.at(pos)) {
|
||||
case '<': out += "<"; break;
|
||||
case '>': out += ">"; break;
|
||||
case '&': out += "&"; break;
|
||||
case '"': out += """; break;
|
||||
default: out += in.at(pos); break;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
@ -850,7 +850,7 @@ static bool parsedate(vector<string>::const_iterator& it,
|
||||
{
|
||||
dip->y1 = dip->m1 = dip->d1 = dip->y2 = dip->m2 = dip->d2 = 0;
|
||||
if (it->length() > 4 || !it->length() ||
|
||||
it->find_first_not_of("0123456789") != string::npos) {
|
||||
it->find_first_not_of("0123456789") != string::npos) {
|
||||
return false;
|
||||
}
|
||||
if (it == end || sscanf(it++->c_str(), "%d", &dip->y1) != 1) {
|
||||
@ -864,7 +864,7 @@ static bool parsedate(vector<string>::const_iterator& it,
|
||||
}
|
||||
|
||||
if (it->length() > 2 || !it->length() ||
|
||||
it->find_first_not_of("0123456789") != string::npos) {
|
||||
it->find_first_not_of("0123456789") != string::npos) {
|
||||
return false;
|
||||
}
|
||||
if (it == end || sscanf(it++->c_str(), "%d", &dip->m1) != 1) {
|
||||
@ -878,7 +878,7 @@ static bool parsedate(vector<string>::const_iterator& it,
|
||||
}
|
||||
|
||||
if (it->length() > 2 || !it->length() ||
|
||||
it->find_first_not_of("0123456789") != string::npos) {
|
||||
it->find_first_not_of("0123456789") != string::npos) {
|
||||
return false;
|
||||
}
|
||||
if (it == end || sscanf(it++->c_str(), "%d", &dip->d1) != 1) {
|
||||
@ -1001,7 +1001,7 @@ static bool addperiod(DateInterval *dp, DateInterval *pp)
|
||||
int monthdays(int mon, int year)
|
||||
{
|
||||
switch (mon) {
|
||||
// We are returning a few too many 29 days februaries, no problem
|
||||
// We are returning a few too many 29 days februaries, no problem
|
||||
case 2:
|
||||
return (year % 4) == 0 ? 29 : 28;
|
||||
case 1:
|
||||
@ -1023,7 +1023,7 @@ bool parsedateinterval(const string& s, DateInterval *dip)
|
||||
DateInterval p1, p2, d1, d2;
|
||||
p1 = p2 = d1 = d2 = *dip;
|
||||
bool hasp1 = false, hasp2 = false, hasd1 = false, hasd2 = false,
|
||||
hasslash = false;
|
||||
hasslash = false;
|
||||
|
||||
if (!stringToStrings(s, vs, "PYMDpymd-/")) {
|
||||
return false;
|
||||
@ -1164,6 +1164,16 @@ secondelt:
|
||||
return true;
|
||||
}
|
||||
|
||||
// We'd like these static, but then, as only one is used, this
|
||||
// triggers a 'defined but not used' warning.
|
||||
char *_check_strerror_r(int, char *errbuf)
|
||||
{
|
||||
return errbuf;
|
||||
}
|
||||
char *_check_strerror_r(char *cp, char *)
|
||||
{
|
||||
return cp;
|
||||
}
|
||||
|
||||
void catstrerror(string *reason, const char *what, int _errno)
|
||||
{
|
||||
@ -1186,8 +1196,6 @@ void catstrerror(string *reason, const char *what, int _errno)
|
||||
// Note: sun strerror is noted mt-safe ??
|
||||
reason->append(strerror(_errno));
|
||||
#else
|
||||
#define ERRBUFSZ 200
|
||||
char errbuf[ERRBUFSZ];
|
||||
// There are 2 versions of strerror_r.
|
||||
// - The GNU one returns a pointer to the message (maybe
|
||||
// static storage or supplied buffer).
|
||||
@ -1198,13 +1206,15 @@ void catstrerror(string *reason, const char *what, int _errno)
|
||||
// were returned a pointer...
|
||||
// Also couldn't find an easy way to disable the gnu version without
|
||||
// changing the cxxflags globally, so forget it. Recent gnu lib versions
|
||||
// normally default to the posix version.
|
||||
// At worse we get no message at all here.
|
||||
// normally default to the posix version. (not !)
|
||||
// The feature defines tests are too complicated and seem unreliable.
|
||||
// In short it's a mess, but thanks to c++ function overloading and smart
|
||||
// people, we have a solution:
|
||||
// https://www.zverovich.net/2015/03/13/reliable-detection-of-strerror-variants.html
|
||||
char errbuf[200];
|
||||
errbuf[0] = 0;
|
||||
// We don't use ret, it's there to silence a cc warning
|
||||
auto ret = strerror_r(_errno, errbuf, ERRBUFSZ);
|
||||
(void)ret;
|
||||
reason->append(errbuf);
|
||||
reason->append(_check_strerror_r(
|
||||
strerror_r(_errno, errbuf, sizeof(errbuf)), errbuf));
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -1232,7 +1242,7 @@ static std::unordered_map<string, string> lang_to_code {
|
||||
{"th", "iso-8859-11"},
|
||||
{"tr", "iso-8859-9"},
|
||||
{"uk", "koi8-u"},
|
||||
};
|
||||
};
|
||||
static const string cstr_cp1252("CP1252");
|
||||
|
||||
string langtocode(const string& lang)
|
||||
@ -1252,7 +1262,7 @@ string localelang()
|
||||
const char *lang = getenv("LANG");
|
||||
|
||||
if (lang == 0 || *lang == 0 || !strcmp(lang, "C") ||
|
||||
!strcmp(lang, "POSIX")) {
|
||||
!strcmp(lang, "POSIX")) {
|
||||
return "en";
|
||||
}
|
||||
string locale(lang);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user