Mercurial > public > ostc_companion
diff Utils/LogFile.cpp @ 1:0b3630a29ad8
Initial version based on previous repository.
Project was ported to QT6 and in now cmake based.
| author | Ideenmodellierer <tiefenrauscher@web.de> |
|---|---|
| date | Thu, 27 Nov 2025 18:40:28 +0100 |
| parents | |
| children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Utils/LogFile.cpp Thu Nov 27 18:40:28 2025 +0100 @@ -0,0 +1,193 @@ +////////////////////////////////////////////////////////////////////////////// +/// \file LogFile.cpp +/// \brief Put Log message into a log file. +/// \author JD Gascuel. +/// \copyright (c) 2011-2016 JD Gascuel. All rights reserved. +/// $Id$ +////////////////////////////////////////////////////////////////////////////// +// +// BSD 2-Clause License: +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +// THE POSSIBILITY OF SUCH DAMAGE. +// +////////////////////////////////////////////////////////////////////////////// + +#include "Utils/LogFile.h" + +#include <QCoreApplication> +#include <QDir> +#include <QMutex> +#include <QSettings> +#include <QRegularExpression> + +#ifndef WIN32 +# include <sys/stat.h> // umask +#else +# include <io.h> // umask +#endif + +static QMutex mutex; + +////////////////////////////////////////////////////////////////////////////// + +LogFile::LogFile(int argc, char *argv[]) + : LogAppender(argc, argv), + _holdFiles(5), + _fileNameFormat("%a-%n.txt"), + _logFile(NULL) +{ + setMinLevel(defaultMinLevel()); + for(int i=1; i<argc; ++i) + { + if( strcmp("-dd", argv[i]) == 0 ) + setMinLevel(Log::LEVEL_DEBUG); + else if( strcmp("-d", argv[i]) == 0 ) + setMinLevel(Log::LEVEL_TRACE); + } +} + +LogFile::~LogFile() +{ + if( _logFile ) + fclose(_logFile); + _logFile = NULL; +} + +const char *LogFile::type() const +{ + return "File"; +} + +Log::Level LogFile::defaultMinLevel() const +{ + return Log::LEVEL_TRACE; +} + + +const char* LogFile::defaultFormat() const +{ + return "[%d %t] %o %F:%l: %m"; +} + +////////////////////////////////////////////////////////////////////////////// + +QString LogFile::filePath(bool pattern) const +{ + QString path = +#ifdef Q_OS_MAC + QString("/tmp") +#else + QDir::tempPath() +#endif + + "/" + + _fileNameFormat; + path.replace("%n", pattern ? "*" : "001") + .replace("%a", Log::applicationName()); + return path; +} + +////////////////////////////////////////////////////////////////////////////// + +void LogFile::cleanup() +{ + QString name = filePath(true); + QDir dir(name.section('/', 0, -2)); + name = name.section('/', -1); + + // ---- Make sure the directory exists, and is writable by everyone. + int oldUMask = umask(0); + if( ! dir.exists() ) + QDir::current().mkdir( dir.absolutePath() ); + + // ---- Then perform the cleanup, if necessary + QFileInfoList list = dir.entryInfoList(QStringList(name), QDir::Files, QDir::Name | QDir::Reversed); + // QRegExp parse(name.replace("*", "([0-9]+)")); + QRegularExpression parse(name.replace("*", "([0-9]+)")); + + for(int i=0; i<list.count(); ++i) + { + QString log = list[i].fileName(); +#if 0 + if( parse.exactMatch(log) ) + { + int num = parse.cap(1).toInt(); + if( num >= _holdFiles ) + dir.remove(log); + else + { + QString newName = _fileNameFormat; + newName.replace("%n", QString().sprintf("%03d", num+1)) + .replace("%a", Log::applicationName()); + dir.rename(log, newName); + } + } +#endif + QRegularExpressionMatch match = parse.match(log); // match erzeugen + if (match.hasMatch()) // entspricht exactMatch + { + int num = match.captured(1).toInt(); // entspricht cap(1) + + if (num >= _holdFiles) + dir.remove(log); + else + { + QString newName = _fileNameFormat; + // newName.replace("%n", QString().sprintf("%03d", num+1)) + // .replace("%a", Log::applicationName()); + QString number = QString::number(num + 1).rightJustified(3, '0'); + newName.replace("%n", number) + .replace("%a", Log::applicationName()); + dir.rename(log, newName); + } + } + } + + umask(oldUMask); +} + +////////////////////////////////////////////////////////////////////////////// + +void LogFile::operator()(const Log &log) +{ + // stdio FILE is not reentrant. So a lock here is mandatory. + QMutexLocker locker(&mutex); + + //---- Open the current log file ----------------------------------------- + if( ! _logFile ) + { + //---- Clean old log files + cleanup(); + //---- Then open the new one. + QString name = filePath(); + _logFile = fopen(name.toLocal8Bit().constData(), "at+"); + } + + //---- Output log line --------------------------------------------------- + if( _logFile ) // File open succeded ? + { + QString line = format(log); + fprintf(_logFile, "%s\n", line.toUtf8().constData()); + fflush(_logFile); + } +}
