comparison 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
comparison
equal deleted inserted replaced
0:76ccd6ce50c0 1:0b3630a29ad8
1 //////////////////////////////////////////////////////////////////////////////
2 /// \file LogFile.cpp
3 /// \brief Put Log message into a log file.
4 /// \author JD Gascuel.
5 /// \copyright (c) 2011-2016 JD Gascuel. All rights reserved.
6 /// $Id$
7 //////////////////////////////////////////////////////////////////////////////
8 //
9 // BSD 2-Clause License:
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions
13 // are met:
14 //
15 // 1. Redistributions of source code must retain the above copyright notice,
16 // this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright notice,
19 // this list of conditions and the following disclaimer in the documentation
20 // and/or other materials provided with the distribution.
21 //
22 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
26 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
32 // THE POSSIBILITY OF SUCH DAMAGE.
33 //
34 //////////////////////////////////////////////////////////////////////////////
35
36 #include "Utils/LogFile.h"
37
38 #include <QCoreApplication>
39 #include <QDir>
40 #include <QMutex>
41 #include <QSettings>
42 #include <QRegularExpression>
43
44 #ifndef WIN32
45 # include <sys/stat.h> // umask
46 #else
47 # include <io.h> // umask
48 #endif
49
50 static QMutex mutex;
51
52 //////////////////////////////////////////////////////////////////////////////
53
54 LogFile::LogFile(int argc, char *argv[])
55 : LogAppender(argc, argv),
56 _holdFiles(5),
57 _fileNameFormat("%a-%n.txt"),
58 _logFile(NULL)
59 {
60 setMinLevel(defaultMinLevel());
61 for(int i=1; i<argc; ++i)
62 {
63 if( strcmp("-dd", argv[i]) == 0 )
64 setMinLevel(Log::LEVEL_DEBUG);
65 else if( strcmp("-d", argv[i]) == 0 )
66 setMinLevel(Log::LEVEL_TRACE);
67 }
68 }
69
70 LogFile::~LogFile()
71 {
72 if( _logFile )
73 fclose(_logFile);
74 _logFile = NULL;
75 }
76
77 const char *LogFile::type() const
78 {
79 return "File";
80 }
81
82 Log::Level LogFile::defaultMinLevel() const
83 {
84 return Log::LEVEL_TRACE;
85 }
86
87
88 const char* LogFile::defaultFormat() const
89 {
90 return "[%d %t] %o %F:%l: %m";
91 }
92
93 //////////////////////////////////////////////////////////////////////////////
94
95 QString LogFile::filePath(bool pattern) const
96 {
97 QString path =
98 #ifdef Q_OS_MAC
99 QString("/tmp")
100 #else
101 QDir::tempPath()
102 #endif
103 + "/"
104 + _fileNameFormat;
105 path.replace("%n", pattern ? "*" : "001")
106 .replace("%a", Log::applicationName());
107 return path;
108 }
109
110 //////////////////////////////////////////////////////////////////////////////
111
112 void LogFile::cleanup()
113 {
114 QString name = filePath(true);
115 QDir dir(name.section('/', 0, -2));
116 name = name.section('/', -1);
117
118 // ---- Make sure the directory exists, and is writable by everyone.
119 int oldUMask = umask(0);
120 if( ! dir.exists() )
121 QDir::current().mkdir( dir.absolutePath() );
122
123 // ---- Then perform the cleanup, if necessary
124 QFileInfoList list = dir.entryInfoList(QStringList(name), QDir::Files, QDir::Name | QDir::Reversed);
125 // QRegExp parse(name.replace("*", "([0-9]+)"));
126 QRegularExpression parse(name.replace("*", "([0-9]+)"));
127
128 for(int i=0; i<list.count(); ++i)
129 {
130 QString log = list[i].fileName();
131 #if 0
132 if( parse.exactMatch(log) )
133 {
134 int num = parse.cap(1).toInt();
135 if( num >= _holdFiles )
136 dir.remove(log);
137 else
138 {
139 QString newName = _fileNameFormat;
140 newName.replace("%n", QString().sprintf("%03d", num+1))
141 .replace("%a", Log::applicationName());
142 dir.rename(log, newName);
143 }
144 }
145 #endif
146 QRegularExpressionMatch match = parse.match(log); // match erzeugen
147 if (match.hasMatch()) // entspricht exactMatch
148 {
149 int num = match.captured(1).toInt(); // entspricht cap(1)
150
151 if (num >= _holdFiles)
152 dir.remove(log);
153 else
154 {
155 QString newName = _fileNameFormat;
156 // newName.replace("%n", QString().sprintf("%03d", num+1))
157 // .replace("%a", Log::applicationName());
158 QString number = QString::number(num + 1).rightJustified(3, '0');
159 newName.replace("%n", number)
160 .replace("%a", Log::applicationName());
161 dir.rename(log, newName);
162 }
163 }
164 }
165
166 umask(oldUMask);
167 }
168
169 //////////////////////////////////////////////////////////////////////////////
170
171 void LogFile::operator()(const Log &log)
172 {
173 // stdio FILE is not reentrant. So a lock here is mandatory.
174 QMutexLocker locker(&mutex);
175
176 //---- Open the current log file -----------------------------------------
177 if( ! _logFile )
178 {
179 //---- Clean old log files
180 cleanup();
181 //---- Then open the new one.
182 QString name = filePath();
183 _logFile = fopen(name.toLocal8Bit().constData(), "at+");
184 }
185
186 //---- Output log line ---------------------------------------------------
187 if( _logFile ) // File open succeded ?
188 {
189 QString line = format(log);
190 fprintf(_logFile, "%s\n", line.toUtf8().constData());
191 fflush(_logFile);
192 }
193 }