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);
+    }
+}