diff options
Diffstat (limited to 'rbutil/rbutilqt/logger/AbstractStringAppender.cpp')
-rw-r--r-- | rbutil/rbutilqt/logger/AbstractStringAppender.cpp | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/rbutil/rbutilqt/logger/AbstractStringAppender.cpp b/rbutil/rbutilqt/logger/AbstractStringAppender.cpp new file mode 100644 index 0000000000..073ecb7782 --- /dev/null +++ b/rbutil/rbutilqt/logger/AbstractStringAppender.cpp | |||
@@ -0,0 +1,161 @@ | |||
1 | /* | ||
2 | Copyright (c) 2010 Boris Moiseev (cyberbobs at gmail dot com) | ||
3 | |||
4 | This program is free software: you can redistribute it and/or modify | ||
5 | it under the terms of the GNU Lesser General Public License version 2.1 | ||
6 | as published by the Free Software Foundation and appearing in the file | ||
7 | LICENSE.LGPL included in the packaging of this file. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU Lesser General Public License for more details. | ||
13 | */ | ||
14 | // Local | ||
15 | #include "AbstractStringAppender.h" | ||
16 | |||
17 | // Qt | ||
18 | #include <QReadLocker> | ||
19 | #include <QWriteLocker> | ||
20 | #include <QDateTime> | ||
21 | #include <QRegExp> | ||
22 | |||
23 | const char formattingMarker = '%'; | ||
24 | |||
25 | AbstractStringAppender::AbstractStringAppender() | ||
26 | : m_format(QLatin1String("%t{yyyy-MM-ddTHH:mm:ss.zzz} [%-7l] <%c> %m\n")) | ||
27 | {} | ||
28 | |||
29 | |||
30 | QString AbstractStringAppender::format() const | ||
31 | { | ||
32 | QReadLocker locker(&m_formatLock); | ||
33 | return m_format; | ||
34 | } | ||
35 | |||
36 | |||
37 | void AbstractStringAppender::setFormat(const QString& format) | ||
38 | { | ||
39 | QWriteLocker locker(&m_formatLock); | ||
40 | m_format = format; | ||
41 | } | ||
42 | |||
43 | |||
44 | QString AbstractStringAppender::stripFunctionName(const char* name) | ||
45 | { | ||
46 | QRegExp rx("^.+\\s((?:[\\w\\d]+::)+)?([\\w\\d\\<\\>~]+)(?:\\(.*\\)).*$"); // XXX: SLOW! | ||
47 | return QString::fromLatin1(name).replace(rx, QString(QLatin1String("\\1\\2"))); | ||
48 | } | ||
49 | |||
50 | |||
51 | QString AbstractStringAppender::formattedString(const QDateTime& timeStamp, Logger::LogLevel logLevel, const char* file, | ||
52 | int line, const char* function, const QString& message) const | ||
53 | { | ||
54 | QString f = format(); | ||
55 | const int size = f.size(); | ||
56 | |||
57 | QString result; | ||
58 | |||
59 | int i = 0; | ||
60 | while (i < f.size()) | ||
61 | { | ||
62 | QChar c = f.at(i); | ||
63 | |||
64 | // We will silently ignore the broken % marker at the end of string | ||
65 | if (c != QLatin1Char(formattingMarker) || (i + 1) == size) | ||
66 | { | ||
67 | result.append(c); | ||
68 | } | ||
69 | else | ||
70 | { | ||
71 | QChar command = f.at(++i); | ||
72 | |||
73 | // Check for the padding instruction | ||
74 | int fieldWidth = 0; | ||
75 | if (command.isDigit() || command.category() == QChar::Punctuation_Dash) | ||
76 | { | ||
77 | int j = 1; | ||
78 | while ((i + j) < size && f.at(i + j).isDigit()) | ||
79 | j++; | ||
80 | fieldWidth = f.mid(i, j).toInt(); | ||
81 | |||
82 | i += j; | ||
83 | command = f.at(i); | ||
84 | } | ||
85 | |||
86 | // Log record chunk to insert instead of formatting instruction | ||
87 | QString chunk; | ||
88 | |||
89 | // Time stamp | ||
90 | if (command == QLatin1Char('t')) | ||
91 | { | ||
92 | if (f.at(i + 1) == QLatin1Char('{')) | ||
93 | { | ||
94 | int j = 1; | ||
95 | while ((i + 2 + j) < size && f.at(i + 2 + j) != QLatin1Char('}')) | ||
96 | j++; | ||
97 | |||
98 | if ((i + 2 + j) < size) | ||
99 | { | ||
100 | chunk = timeStamp.toString(f.mid(i + 2, j)); | ||
101 | |||
102 | i += j; | ||
103 | i += 2; | ||
104 | } | ||
105 | } | ||
106 | |||
107 | if (chunk.isNull()) | ||
108 | chunk = timeStamp.toString(QLatin1String("HH:mm:ss.zzz")); | ||
109 | } | ||
110 | |||
111 | // Log level | ||
112 | else if (command == QLatin1Char('l')) | ||
113 | chunk = Logger::levelToString(logLevel); | ||
114 | |||
115 | // Uppercased log level | ||
116 | else if (command == QLatin1Char('L')) | ||
117 | chunk = Logger::levelToString(logLevel).toUpper(); | ||
118 | |||
119 | // Filename | ||
120 | else if (command == QLatin1Char('F')) | ||
121 | chunk = QLatin1String(file); | ||
122 | |||
123 | // Filename without a path | ||
124 | else if (command == QLatin1Char('f')) | ||
125 | chunk = QString(QLatin1String(file)).section('/', -1); | ||
126 | |||
127 | // Source line number | ||
128 | else if (command == QLatin1Char('i')) | ||
129 | chunk = QString::number(line); | ||
130 | |||
131 | // Function name, as returned by Q_FUNC_INFO | ||
132 | else if (command == QLatin1Char('C')) | ||
133 | chunk = QString::fromLatin1(function); | ||
134 | |||
135 | // Stripped function name | ||
136 | else if (command == QLatin1Char('c')) | ||
137 | chunk = stripFunctionName(function); | ||
138 | |||
139 | // Log message | ||
140 | else if (command == QLatin1Char('m')) | ||
141 | chunk = message; | ||
142 | |||
143 | // We simply replace the double formatting marker (%) with one | ||
144 | else if (command == QLatin1Char(formattingMarker)) | ||
145 | chunk = QLatin1Char(formattingMarker); | ||
146 | |||
147 | // Do not process any unknown commands | ||
148 | else | ||
149 | { | ||
150 | chunk = QLatin1Char(formattingMarker); | ||
151 | chunk.append(command); | ||
152 | } | ||
153 | |||
154 | result.append(QString(QLatin1String("%1")).arg(chunk, fieldWidth)); | ||
155 | } | ||
156 | |||
157 | ++i; | ||
158 | } | ||
159 | |||
160 | return result; | ||
161 | } | ||