TreeFrogFramework 2.10
Loading...
Searching...
No Matches
tglobal.h
Go to the documentation of this file.
1#pragma once
2constexpr auto TF_VERSION_STR = "2.10.0";
3constexpr auto TF_VERSION_NUMBER = 0x020a00;
4constexpr auto TF_SRC_REVISION = 2956;
5
6#include <QMetaType>
7#include <QIODevice>
8#include <QtGlobal>
9#include <version>
10
11
12#if (!defined(Q_OS_WIN) && (defined(__cpp_lib_format) || __has_include(<format>))) || (defined(_MSC_VER) && _MSC_VER >= 1930) // std::format
13#define TF_HAVE_STD_FORMAT
14#endif
15
16#define T_DEFINE_CONTROLLER(TYPE) T_DEFINE_TYPE(TYPE)
17#define T_DEFINE_VIEW(TYPE) T_DEFINE_TYPE(TYPE)
18#define T_DEFINE_TYPE(TYPE) \
19 class Static##TYPE##Definition { \
20 public: \
21 Static##TYPE##Definition() noexcept \
22 { \
23 Tf::objectFactories()->insert(QByteArray(#TYPE).toLower(), []() { return new TYPE(); }); \
24 } \
25 }; \
26 static Static##TYPE##Definition _static##TYPE##Definition;
27
28// do no longer exist in qt6, qRegisterMetaTypeStreamOperators().
29#define T_REGISTER_STREAM_OPERATORS(TYPE)
30
31#define T_DEFINE_PROPERTY(TYPE, PROPERTY) \
32 inline void set##PROPERTY(const TYPE &v__) noexcept { PROPERTY = v__; } \
33 inline TYPE get##PROPERTY() const noexcept { return PROPERTY; }
34
35
36#if defined(Q_CC_GNU) && !defined(__INSURE__)
37#if defined(Q_CC_MINGW) && !defined(Q_CC_CLANG)
38#define T_ATTRIBUTE_FORMAT(A, B) __attribute__((format(gnu_printf, (A), (B))))
39#else
40#define T_ATTRIBUTE_FORMAT(A, B) __attribute__((format(printf, (A), (B))))
41#endif
42#else
43#define T_ATTRIBUTE_FORMAT(A, B)
44#endif
45
46
47#define T_EXPORT(VAR) \
48 do { \
49 QVariant ___##VAR##_; \
50 ___##VAR##_.setValue(VAR); \
51 Tf::currentController()->exportVariant(QLatin1String(#VAR), (___##VAR##_), true); \
52 } while (0)
53#define texport(VAR) T_EXPORT(VAR)
54
55#define T_EXPORT_UNLESS(VAR) \
56 do { \
57 QVariant ___##VAR##_; \
58 ___##VAR##_.setValue(VAR); \
59 Tf::currentController()->exportVariant(QLatin1String(#VAR), (___##VAR##_), false); \
60 } while (0)
61#define texportUnless(VAR) T_EXPORT_UNLESS(VAR)
62
63#define T_FETCH(TYPE, VAR) TYPE VAR = variant(QLatin1String(#VAR)).value<TYPE>()
64#define tfetch(TYPE, VAR) T_FETCH(TYPE, VAR)
65
66#define T_FETCH_V(TYPE, VAR, DEFAULT) TYPE VAR = (hasVariant(QLatin1String(#VAR))) ? (variant(QLatin1String(#VAR)).value<TYPE>()) : (DEFAULT)
67#define tfetchv(TYPE, VAR, DEFAULT) T_FETCH_V(TYPE, VAR, DEFAULT)
68
69#define T_EHEX(VAR) \
70 do { \
71 auto ___##VAR##_ = variant(QLatin1String(#VAR)); \
72 int ___##VAR##_type = (___##VAR##_).typeId(); \
73 switch (___##VAR##_type) { \
74 case QMetaType::QJsonValue: \
75 eh((___##VAR##_).toJsonValue()); \
76 break; \
77 case QMetaType::QJsonObject: \
78 eh((___##VAR##_).toJsonObject()); \
79 break; \
80 case QMetaType::QJsonArray: \
81 eh((___##VAR##_).toJsonArray()); \
82 break; \
83 case QMetaType::QJsonDocument: \
84 eh((___##VAR##_).toJsonDocument()); \
85 break; \
86 case QMetaType::QVariantMap: \
87 eh((___##VAR##_).toMap()); \
88 break; \
89 default: \
90 eh(___##VAR##_); \
91 } \
92 } while (0)
93
94#define tehex(VAR) T_EHEX(VAR)
95
96#define T_EHEX_V(VAR, DEFAULT) \
97 do { \
98 auto ___##VAR##_ = variant(QLatin1String(#VAR)); \
99 if ((___##VAR##_).isNull()) { \
100 eh(DEFAULT); \
101 } else { \
102 T_EHEX(VAR); \
103 } \
104 } while (0)
105
106#define tehexv(VAR, DEFAULT) T_EHEX_V(VAR, DEFAULT)
107
108// alias of tehexv
109#define T_EHEX2(VAR, DEFAULT) T_EHEX_V(VAR, DEFAULT)
110#define tehex2(VAR, DEFAULT) T_EHEX2(VAR, DEFAULT)
111
112#define T_ECHOEX(VAR) \
113 do { \
114 auto ___##VAR##_ = variant(QLatin1String(#VAR)); \
115 int ___##VAR##_type = (___##VAR##_).typeId(); \
116 switch (___##VAR##_type) { \
117 case QMetaType::QJsonValue: \
118 echo((___##VAR##_).toJsonValue()); \
119 break; \
120 case QMetaType::QJsonObject: \
121 echo((___##VAR##_).toJsonObject()); \
122 break; \
123 case QMetaType::QJsonArray: \
124 echo((___##VAR##_).toJsonArray()); \
125 break; \
126 case QMetaType::QJsonDocument: \
127 echo((___##VAR##_).toJsonDocument()); \
128 break; \
129 case QMetaType::QVariantMap: \
130 echo((___##VAR##_).toMap()); \
131 break; \
132 default: \
133 echo(___##VAR##_); \
134 } \
135 } while (0)
136
137
138#define techoex(VAR) T_ECHOEX(VAR)
139
140#define T_ECHOEX_V(VAR, DEFAULT) \
141 do { \
142 auto ___##VAR##_ = variant(QLatin1String(#VAR)); \
143 if ((___##VAR##_).isNull()) { \
144 echo(DEFAULT); \
145 } else { \
146 T_ECHOEX(VAR); \
147 } \
148 } while (0)
149
150#define techoexv(VAR, DEFAULT) T_ECHOEX_V(VAR, DEFAULT)
151
152// alias of techoexv
153#define T_ECHOEX2(VAR, DEFAULT) T_ECHOEX_V(VAR, DEFAULT)
154#define techoex2(VAR, DEFAULT) T_ECHOEX2(VAR, DEFAULT)
155
156#define T_FLASH(VAR) \
157 do { \
158 QVariant ___##VAR##_; \
159 ___##VAR##_.setValue(VAR); \
160 Tf::currentController()->setFlash(QLatin1String(#VAR), (___##VAR##_)); \
161 } while (0)
162
163#define tflash(VAR) T_FLASH(VAR)
164
165#define T_VARIANT(VAR) (variant(QLatin1String(#VAR)).toString())
166
167
168#define tFatal TDebug(Tf::FatalLevel).fatal
169#define tError TDebug(Tf::ErrorLevel).error
170#define tWarn TDebug(Tf::WarnLevel).warn
171#define tInfo TDebug(Tf::InfoLevel).info
172#define tDebug TDebug(Tf::DebugLevel).debug
173#define tTrace TDebug(Tf::TraceLevel).trace
174
175
176#include "tfexception.h"
177#include "tfnamespace.h"
178#include "tdeclexport.h"
179#include <TDebug>
180#include <cstdint>
181#include <cstring>
182#include <functional>
183#include <algorithm>
184#ifdef TF_HAVE_STD_FORMAT // std::format
185#include <format>
186#endif
187
188class TWebApplication;
189class TActionContext;
191class TAbstractActionContext;
192class TAppSettings;
193class TDatabaseContext;
194class TCache;
195class QSqlDatabase;
196
197namespace Tf {
199T_CORE_EXPORT TAppSettings *appSettings() noexcept;
200T_CORE_EXPORT const QVariantMap &conf(const QString &configName) noexcept;
201T_CORE_EXPORT void msleep(int64_t msecs) noexcept;
203
204// Thread-safe std::random number generator
205T_CORE_EXPORT uint32_t rand32_r() noexcept;
206T_CORE_EXPORT uint64_t rand64_r() noexcept;
207T_CORE_EXPORT uint64_t random(uint64_t min, uint64_t max) noexcept;
208T_CORE_EXPORT uint64_t random(uint64_t max) noexcept;
209
210T_CORE_EXPORT TCache *cache() noexcept;
214T_CORE_EXPORT QSqlDatabase &currentSqlDatabase(int id) noexcept;
215T_CORE_EXPORT QMap<QByteArray, std::function<QObject *()>> *objectFactories() noexcept;
216
217// LZ4 lossless compression algorithm
218T_CORE_EXPORT QByteArray lz4Compress(const char *data, int nbytes, int compressionLevel = 1) noexcept;
219T_CORE_EXPORT QByteArray lz4Compress(const QByteArray &data, int compressionLevel = 1) noexcept;
220T_CORE_EXPORT QByteArray lz4Uncompress(const char *data, int nbytes) noexcept;
221T_CORE_EXPORT QByteArray lz4Uncompress(const QByteArray &data) noexcept;
222
223inline bool strcmp(const QByteArray &str1, const QByteArray &str2)
224{
225 return str1.length() == str2.length() && !std::strncmp(str1.data(), str2.data(), str1.length());
226}
227
228#ifdef TF_HAVE_STD_FORMAT // std::format
229
230// Logging for developer
231
236template<typename... Args>
237void fatal(const std::format_string<Args...> &fmt, Args&&... args)
238{
239 std::string msg = std::format(fmt, std::forward<Args>(args)...);
240 Tf::logging(Tf::FatalLevel, QByteArray::fromStdString(msg));
241}
242
247template<typename... Args>
248void error(const std::format_string<Args...> &fmt, Args&&... args)
249{
250 std::string msg = std::format(fmt, std::forward<Args>(args)...);
251 Tf::logging(Tf::ErrorLevel, QByteArray::fromStdString(msg));
252}
253
258template<typename... Args>
259void warn(const std::format_string<Args...> &fmt, Args&&... args)
260{
261 std::string msg = std::format(fmt, std::forward<Args>(args)...);
262 Tf::logging(Tf::WarnLevel, QByteArray::fromStdString(msg));
263}
264
269template<typename... Args>
270void info(const std::format_string<Args...> &fmt, Args&&... args)
271{
272 std::string msg = std::format(fmt, std::forward<Args>(args)...);
273 Tf::logging(Tf::InfoLevel, QByteArray::fromStdString(msg));
274}
275
280template<typename... Args>
281void debug(const std::format_string<Args...> &fmt, Args&&... args)
282{
283 std::string msg = std::format(fmt, std::forward<Args>(args)...);
284 Tf::logging(Tf::DebugLevel, QByteArray::fromStdString(msg));
285}
286
291template<typename... Args>
292void trace(const std::format_string<Args...> &fmt, Args&&... args)
293{
294 std::string msg = std::format(fmt, std::forward<Args>(args)...);
295 Tf::logging(Tf::TraceLevel, QByteArray::fromStdString(msg));
296}
297
298#else
299
300template<typename... Args>
301QByteArray simple_format(const std::string &format, Args&&... args)
302{
303 QByteArray res;
304 const size_t len = format.size();
305 constexpr int cnt = sizeof...(args);
306 QVariantList vars = { QVariant(args)... };
307
308 size_t pos = 0;
309 int argidx = 0;
310 res.reserve(len * 2);
311
312 while (pos < len) {
313 if (format[pos] == '{') {
314 if (pos + 1 < len && format[pos + 1] == '}') {
315 if (argidx < cnt) {
316 res += vars[argidx].toByteArray();
317 argidx++;
318 pos += 2; // Skip 2 characters, '{}'
319 continue;
320 }
321 } else {
322 auto e = format.find('}', pos + 2);
323 if (e != std::string::npos && argidx < cnt) {
324 auto sz = e - pos - 1;
325 auto subs = format.substr(pos + 1, sz);
326 if (subs == ":x") {
327 auto num = vars[argidx].toULongLong();
328 res += QString::number(num, 16).toLatin1();
329 } else if (subs == ":#x") {
330 auto num = vars[argidx].toULongLong();
331 res += "0x";
332 res += QString::number(num, 16).toLatin1();
333 } else {
334 // other format
335 res += vars[argidx].toByteArray();
336 }
337 argidx++;
338 pos += sz + 2;
339 continue;
340 }
341 }
342 }
343 res += format[pos++];
344 }
345 return res;
346}
347
348// Logging for developer
349template<typename... Args>
350void fatal(const std::string &fmt, Args&&... args)
351{
352 auto msg = simple_format(std::string(fmt), std::forward<Args>(args)...);
354}
355
356template<typename... Args>
357void error(const std::string &fmt, Args&&... args)
358{
359 auto msg = simple_format(std::string(fmt), std::forward<Args>(args)...);
361}
362
363template<typename... Args>
364void warn(const std::string &fmt, Args&&... args)
365{
366 auto msg = simple_format(std::string(fmt), std::forward<Args>(args)...);
368}
369
370template<typename... Args>
371void info(const std::string &fmt, Args&&... args)
372{
373 auto msg = simple_format(std::string(fmt), std::forward<Args>(args)...);
375}
376
377template<typename... Args>
378void debug(const std::string &fmt, Args&&... args)
379{
380 auto msg = simple_format(std::string(fmt), std::forward<Args>(args)...);
382}
383
384template<typename... Args>
385void trace(const std::string &fmt, Args&&... args)
386{
387 auto msg = simple_format(std::string(fmt), std::forward<Args>(args)...);
389}
390
391#endif
392
393constexpr auto CR = "\x0d";
394constexpr auto LF = "\x0a";
395constexpr auto CRLF = "\x0d\x0a";
396constexpr auto CRLFCRLF = "\x0d\x0a\x0d\x0a";
397}
The TAbstractController class is the abstract base class of controllers, providing functionality comm...
Definition tabstractcontroller.h:13
The TCache class stores items so that can be served faster.
Definition tcache.h:7
The TDatabaseContext class is the base class of contexts for database access.
Definition tdatabasecontext.h:11
The TWebApplication class provides an event loop for TreeFrog applications.
Definition twebapplication.h:23
The Tf namespace contains miscellaneous identifiers used throughout the library of TreeFrog Framework...
Definition tdebug.h:10
constexpr auto CRLF
Definition tglobal.h:395
T_CORE_EXPORT QByteArray lz4Compress(const char *data, int nbytes, int compressionLevel=1) noexcept
Definition tglobal.cpp:190
void debug(const std::format_string< Args... > &fmt, Args &&... args)
Outputs the debug message to the log file, formatting args according to the format string fmt.
Definition tglobal.h:281
constexpr auto CRLFCRLF
Definition tglobal.h:396
T_CORE_EXPORT const QVariantMap & conf(const QString &configName) noexcept
Returns the map associated with config file configName in 'conf' directory.
Definition tglobal.cpp:57
void error(const std::format_string< Args... > &fmt, Args &&... args)
Outputs the error message to the log file, formatting args according to the format string fmt.
Definition tglobal.h:248
T_CORE_EXPORT uint64_t random(uint64_t min, uint64_t max) noexcept
Random number generator in the range from min to max.
Definition tglobal.cpp:98
T_CORE_EXPORT TWebApplication * app() noexcept
Returns a global pointer referring to the unique application object.
Definition tglobal.cpp:40
bool strcmp(const QByteArray &str1, const QByteArray &str2)
Definition tglobal.h:223
T_CORE_EXPORT TDatabaseContext * currentDatabaseContext()
Definition tglobal.cpp:143
void fatal(const std::format_string< Args... > &fmt, Args &&... args)
Outputs the fatal message to the log file, formatting args according to the format string fmt.
Definition tglobal.h:237
void info(const std::format_string< Args... > &fmt, Args &&... args)
Outputs the infomation message to the log file, formatting args according to the format string fmt.
Definition tglobal.h:270
constexpr auto CR
Definition tglobal.h:393
T_CORE_EXPORT QByteArray lz4Uncompress(const char *data, int nbytes) noexcept
Definition tglobal.cpp:246
T_CORE_EXPORT QMap< QByteArray, std::function< QObject *()> > * objectFactories() noexcept
Definition tglobal.cpp:183
T_CORE_EXPORT uint32_t rand32_r() noexcept
Definition tglobal.cpp:78
@ TraceLevel
Finer-grained informational events than the DEBUG.
Definition tfnamespace.h:236
@ WarnLevel
Potentially harmful situations.
Definition tfnamespace.h:233
@ DebugLevel
Informational events that are most useful to debug the app.
Definition tfnamespace.h:235
@ InfoLevel
Informational messages that highlight the progress of the app.
Definition tfnamespace.h:234
@ FatalLevel
Severe error events that will presumably lead the app to abort.
Definition tfnamespace.h:231
@ ErrorLevel
Error events that might still allow the app to continue running.
Definition tfnamespace.h:232
T_CORE_EXPORT int64_t getMSecsSinceEpoch()
Definition tglobal.cpp:295
void trace(const std::format_string< Args... > &fmt, Args &&... args)
Outputs the trace message to the log file, formatting args according to the format string fmt.
Definition tglobal.h:292
T_CORE_EXPORT void msleep(int64_t msecs) noexcept
Causes the current thread to sleep for msecs milliseconds.
Definition tglobal.cpp:65
constexpr auto LF
Definition tglobal.h:394
T_CORE_EXPORT QSqlDatabase & currentSqlDatabase(int id) noexcept
Definition tglobal.cpp:177
T_CORE_EXPORT TAbstractController * currentController()
Definition tglobal.cpp:122
T_CORE_EXPORT TAppSettings * appSettings() noexcept
Returns a global pointer referring to the unique application settings object.
Definition tglobal.cpp:48
void warn(const std::format_string< Args... > &fmt, Args &&... args)
Outputs the warning message to the log file, formatting args according to the format string fmt.
Definition tglobal.h:259
T_CORE_EXPORT uint64_t rand64_r() noexcept
Definition tglobal.cpp:87
T_CORE_EXPORT TCache * cache() noexcept
Definition tglobal.cpp:116
T_CORE_EXPORT void logging(int priority, const QByteArray &msg)
Definition tdebug.cpp:99
const TAbstractController * constCurrentController()
Definition tglobal.h:212
#define T_CORE_EXPORT
Definition tdeclexport.h:28
constexpr auto TF_SRC_REVISION
Definition tglobal.h:4
constexpr auto TF_VERSION_NUMBER
Definition tglobal.h:3
constexpr auto TF_VERSION_STR
Definition tglobal.h:2