Mercurial > public > ostc_companion
view 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 source
////////////////////////////////////////////////////////////////////////////// /// \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); } }
