1/****************************************************************************
2**
3** Copyright (C) 2020 Intel Corporation.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtCore module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40// for rand_s
41#define _CRT_RAND_S
42
43#include "qrandom.h"
44#include "qrandom_p.h"
45#include <qobjectdefs.h>
46#include <qmutex.h>
47#include <qthreadstorage.h>
48
49#include <errno.h>
50
51#if !QT_CONFIG(getentropy) && (!defined(Q_OS_BSD4) || defined(__GLIBC__)) && !defined(Q_OS_WIN)
52# include "qdeadlinetimer.h"
53# include "qhashfunctions.h"
54
55# if QT_CONFIG(getauxval)
56# include <sys/auxv.h>
57# endif
58#endif // !QT_CONFIG(getentropy)
59
60#ifdef Q_OS_UNIX
61# include <fcntl.h>
62# include <private/qcore_unix_p.h>
63#else
64# include <qt_windows.h>
65
66// RtlGenRandom is not exported by its name in advapi32.dll, but as SystemFunction036
67// See https://msdn.microsoft.com/en-us/library/windows/desktop/aa387694(v=vs.85).aspx
68// Implementation inspired on https://hg.mozilla.org/mozilla-central/file/722fdbff1efc/security/nss/lib/freebl/win_rand.c#l146
69// Argument why this is safe to use: https://bugzilla.mozilla.org/show_bug.cgi?id=504270
70extern "C" {
71DECLSPEC_IMPORT BOOLEAN WINAPI SystemFunction036(PVOID RandomBuffer, ULONG RandomBufferLength);
72}
73#endif
74
75#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
76# include <private/qjni_p.h>
77#endif
78
79// This file is too low-level for regular Q_ASSERT (the logging framework may
80// recurse back), so use regular assert()
81#undef NDEBUG
82#undef Q_ASSERT_X
83#undef Q_ASSERT
84#define Q_ASSERT(cond) assert(cond)
85#define Q_ASSERT_X(cond, x, msg) assert(cond && msg)
86#if defined(QT_NO_DEBUG) && !defined(QT_FORCE_ASSERTS)
87# define NDEBUG 1
88#endif
89#include <assert.h>
90
91QT_BEGIN_NAMESPACE
92
93enum {
94 // may be "overridden" by a member enum
95 FillBufferNoexcept = true
96};
97
98struct QRandomGenerator::SystemGenerator
99{
100#if QT_CONFIG(getentropy)
101 static qsizetype fillBuffer(void *buffer, qsizetype count) noexcept
102 {
103 // getentropy can read at most 256 bytes, so break the reading
104 qsizetype read = 0;
105 while (count - read > 256) {
106 // getentropy can't fail under normal circumstances
107 int ret = getentropy(reinterpret_cast<uchar *>(buffer) + read, 256);
108 Q_ASSERT(ret == 0);
109 Q_UNUSED(ret);
110 read += 256;
111 }
112
113 int ret = getentropy(reinterpret_cast<uchar *>(buffer) + read, count - read);
114 Q_ASSERT(ret == 0);
115 Q_UNUSED(ret);
116 return count;
117 }
118
119#elif defined(Q_OS_UNIX)
120 enum { FillBufferNoexcept = false };
121
122 QBasicAtomicInt fdp1; // "file descriptor plus 1"
123 int openDevice()
124 {
125 int fd = fdp1.loadAcquire() - 1;
126 if (fd != -1)
127 return fd;
128
129 fd = qt_safe_open("/dev/urandom", O_RDONLY);
130 if (fd == -1)
131 fd = qt_safe_open("/dev/random", O_RDONLY | O_NONBLOCK);
132 if (fd == -1) {
133 // failed on both, set to -2 so we won't try again
134 fd = -2;
135 }
136
137 int opened_fdp1;
138 if (fdp1.testAndSetOrdered(0, fd + 1, opened_fdp1))
139 return fd;
140
141 // failed, another thread has opened the file descriptor
142 if (fd >= 0)
143 qt_safe_close(fd);
144 return opened_fdp1 - 1;
145 }
146
147#ifdef Q_CC_GNU
148 // If it's not GCC or GCC-like, then we'll leak the file descriptor
149 __attribute__((destructor))
150#endif
151 static void closeDevice()
152 {
153 int fd = self().fdp1.loadRelaxed() - 1;
154 if (fd >= 0)
155 qt_safe_close(fd);
156 }
157
158 constexpr SystemGenerator() : fdp1 Q_BASIC_ATOMIC_INITIALIZER(0) {}
159
160 qsizetype fillBuffer(void *buffer, qsizetype count)
161 {
162 int fd = openDevice();
163 if (Q_UNLIKELY(fd < 0))
164 return 0;
165
166 qint64 n = qt_safe_read(fd, buffer, count);
167 return qMax<qsizetype>(n, 0); // ignore any errors
168 }
169
170#elif defined(Q_OS_WIN)
171 qsizetype fillBuffer(void *buffer, qsizetype count) noexcept
172 {
173 auto RtlGenRandom = SystemFunction036;
174 return RtlGenRandom(buffer, ULONG(count)) ? count: 0;
175 }
176#endif // Q_OS_WIN
177
178 static SystemGenerator &self();
179 typedef quint32 result_type;
180 void generate(quint32 *begin, quint32 *end) noexcept(FillBufferNoexcept);
181
182 // For std::mersenne_twister_engine implementations that use something
183 // other than quint32 (unsigned int) to fill their buffers.
184 template<typename T>
185 void generate(T *begin, T *end)
186 {
187 static_assert(sizeof(T) >= sizeof(quint32));
188 if (sizeof(T) == sizeof(quint32)) {
189 // Microsoft Visual Studio uses unsigned long, but that's still 32-bit
190 generate(reinterpret_cast<quint32 *>(begin), reinterpret_cast<quint32 *>(end));
191 } else {
192 // Slow path. Fix your C++ library.
193 std::generate(begin, end, [this]() {
194 quint32 datum;
195 generate(&datum, &datum + 1);
196 return datum;
197 });
198 }
199 }
200};
201
202#if defined(Q_OS_WIN)
203static void fallback_update_seed(unsigned) {}
204static void fallback_fill(quint32 *ptr, qsizetype left) noexcept
205{
206 // on Windows, rand_s is a high-quality random number generator
207 // and it requires no seeding
208 std::generate(ptr, ptr + left, []() {
209 unsigned value;
210 rand_s(&value);
211 return value;
212 });
213}
214#elif QT_CONFIG(getentropy)
215static void fallback_update_seed(unsigned) {}
216static void fallback_fill(quint32 *, qsizetype) noexcept
217{
218 // no fallback necessary, getentropy cannot fail under normal circumstances
219 Q_UNREACHABLE();
220}
221#elif defined(Q_OS_BSD4) && !defined(__GLIBC__)
222static void fallback_update_seed(unsigned) {}
223static void fallback_fill(quint32 *ptr, qsizetype left) noexcept
224{
225 // BSDs have arc4random(4) and these work even in chroot(2)
226 arc4random_buf(ptr, left * sizeof(*ptr));
227}
228#else
229static QBasicAtomicInteger<unsigned> seed = Q_BASIC_ATOMIC_INITIALIZER(0U);
230static void fallback_update_seed(unsigned value)
231{
232 // Update the seed to be used for the fallback mechansim, if we need to.
233 // We can't use QtPrivate::QHashCombine here because that is not an atomic
234 // operation. A simple XOR will have to do then.
235 seed.fetchAndXorRelaxed(value);
236}
237
238Q_NEVER_INLINE
239#ifdef Q_CC_GNU
240__attribute__((cold)) // this function is pretty big, so optimize for size
241#endif
242static void fallback_fill(quint32 *ptr, qsizetype left) noexcept
243{
244 quint32 scratch[12]; // see element count below
245 quint32 *end = scratch;
246
247 auto foldPointer = [](quintptr v) {
248 if (sizeof(quintptr) == sizeof(quint32)) {
249 // For 32-bit systems, we simply return the pointer.
250 return quint32(v);
251 } else {
252 // For 64-bit systems, we try to return the variable part of the
253 // pointer. On current x86-64 and AArch64, the top 17 bits are
254 // architecturally required to be the same, but in reality the top
255 // 24 bits on Linux are likely to be the same for all processes.
256 return quint32(v >> (32 - 24));
257 }
258 };
259
260 Q_ASSERT(left);
261
262 *end++ = foldPointer(quintptr(&seed)); // 1: variable in this library/executable's .data
263 *end++ = foldPointer(quintptr(&scratch)); // 2: variable in the stack
264 *end++ = foldPointer(quintptr(&errno)); // 3: veriable either in libc or thread-specific
265 *end++ = foldPointer(quintptr(reinterpret_cast<void*>(strerror))); // 4: function in libc (and unlikely to be a macro)
266
267#ifndef QT_BOOTSTRAPPED
268 quint64 nsecs = QDeadlineTimer::current(Qt::PreciseTimer).deadline();
269 *end++ = quint32(nsecs); // 5
270#endif
271
272 if (quint32 v = seed.loadRelaxed())
273 *end++ = v; // 6
274
275#if QT_CONFIG(getauxval)
276 // works on Linux -- all modern libc have getauxval
277# ifdef AT_RANDOM
278 // ELF's auxv AT_RANDOM has 16 random bytes
279 // (other ELF-based systems don't seem to have AT_RANDOM)
280 ulong auxvSeed = getauxval(AT_RANDOM);
281 if (auxvSeed) {
282 memcpy(end, reinterpret_cast<void *>(auxvSeed), 16);
283 end += 4; // 7 to 10
284 }
285# endif
286
287 // Both AT_BASE and AT_SYSINFO_EHDR have some randomness in them due to the
288 // system's ASLR, even if many bits are the same. They also have randomness
289 // between them.
290# ifdef AT_BASE
291 // present at least on the BSDs too, indicates the address of the loader
292 ulong base = getauxval(AT_BASE);
293 if (base)
294 *end++ = foldPointer(base); // 11
295# endif
296# ifdef AT_SYSINFO_EHDR
297 // seems to be Linux-only, indicates the global page of the sysinfo
298 ulong sysinfo_ehdr = getauxval(AT_SYSINFO_EHDR);
299 if (sysinfo_ehdr)
300 *end++ = foldPointer(sysinfo_ehdr); // 12
301# endif
302#endif
303
304 Q_ASSERT(end <= std::end(scratch));
305
306 // this is highly inefficient, we should save the generator across calls...
307 std::seed_seq sseq(scratch, end);
308 std::mt19937 generator(sseq);
309 std::generate(ptr, ptr + left, generator);
310
311 fallback_update_seed(*ptr);
312}
313#endif
314
315Q_NEVER_INLINE void QRandomGenerator::SystemGenerator::generate(quint32 *begin, quint32 *end)
316 noexcept(FillBufferNoexcept)
317{
318 quint32 *buffer = begin;
319 qsizetype count = end - begin;
320
321 if (Q_UNLIKELY(uint(qt_randomdevice_control.loadAcquire()) & SetRandomData)) {
322 uint value = uint(qt_randomdevice_control.loadAcquire()) & RandomDataMask;
323 std::fill_n(buffer, count, value);
324 return;
325 }
326
327 qsizetype filled = 0;
328 if (qHasHwrng() && (uint(qt_randomdevice_control.loadAcquire()) & SkipHWRNG) == 0)
329 filled += qRandomCpu(buffer, count);
330
331 if (filled != count && (uint(qt_randomdevice_control.loadAcquire()) & SkipSystemRNG) == 0) {
332 qsizetype bytesFilled =
333 fillBuffer(buffer + filled, (count - filled) * qsizetype(sizeof(*buffer)));
334 filled += bytesFilled / qsizetype(sizeof(*buffer));
335 }
336 if (filled)
337 fallback_update_seed(*buffer);
338
339 if (Q_UNLIKELY(filled != count)) {
340 // failed to fill the entire buffer, try the faillback mechanism
341 fallback_fill(buffer + filled, count - filled);
342 }
343}
344
345struct QRandomGenerator::SystemAndGlobalGenerators
346{
347 // Construction notes:
348 // 1) The global PRNG state is in a different cacheline compared to the
349 // mutex that protects it. This avoids any false cacheline sharing of
350 // the state in case another thread tries to lock the mutex. It's not
351 // a common scenario, but since sizeof(QRandomGenerator) >= 2560, the
352 // overhead is actually acceptable.
353 // 2) We use both alignas and std::aligned_storage<..., 64> because
354 // some implementations of std::aligned_storage can't align to more
355 // than a primitive type's alignment.
356 // 3) We don't store the entire system QRandomGenerator, only the space
357 // used by the QRandomGenerator::type member. This is fine because we
358 // (ab)use the common initial sequence exclusion to aliasing rules.
359 QBasicMutex globalPRNGMutex;
360 struct ShortenedSystem { uint type; } system_;
361 SystemGenerator sys;
362 alignas(64) std::aligned_storage<sizeof(QRandomGenerator64), 64>::type global_;
363
364#ifdef Q_COMPILER_CONSTEXPR
365 constexpr SystemAndGlobalGenerators()
366 : globalPRNGMutex{}, system_{0}, sys{}, global_{}
367 {}
368#endif
369
370 void confirmLiteral()
371 {
372#if defined(Q_COMPILER_CONSTEXPR) && !defined(Q_CC_MSVC) && !defined(Q_OS_INTEGRITY)
373 // Currently fails to compile with MSVC 2017, saying QBasicMutex is not
374 // a literal type. Disassembly with MSVC 2013 and 2015 shows it is
375 // actually a literal; MSVC 2017 has a bug relating to this, so we're
376 // withhold judgement for now. Integrity's compiler is unable to
377 // guarantee g's alignment for some reason.
378
379 constexpr SystemAndGlobalGenerators g = {};
380 Q_UNUSED(g);
381 static_assert(std::is_literal_type<SystemAndGlobalGenerators>::value);
382#endif
383 }
384
385 static SystemAndGlobalGenerators *self()
386 {
387 static SystemAndGlobalGenerators g;
388 static_assert(sizeof(g) > sizeof(QRandomGenerator64));
389 return &g;
390 }
391
392 static QRandomGenerator64 *system()
393 {
394 // Though we never call the constructor, the system QRandomGenerator is
395 // properly initialized by the zero initialization performed in self().
396 // Though QRandomGenerator is has non-vacuous initialization, we
397 // consider it initialized because of the common initial sequence.
398 return reinterpret_cast<QRandomGenerator64 *>(&self()->system_);
399 }
400
401 static QRandomGenerator64 *globalNoInit()
402 {
403 // This function returns the pointer to the global QRandomGenerator,
404 // but does not initialize it. Only call it directly if you meant to do
405 // a pointer comparison.
406 return reinterpret_cast<QRandomGenerator64 *>(&self()->global_);
407 }
408
409 static void securelySeed(QRandomGenerator *rng)
410 {
411 // force reconstruction, just to be pedantic
412 new (rng) QRandomGenerator{System{}};
413
414 rng->type = MersenneTwister;
415 new (&rng->storage.engine()) RandomEngine(self()->sys);
416 }
417
418 struct PRNGLocker
419 {
420 const bool locked;
421 PRNGLocker(const QRandomGenerator *that)
422 : locked(that == globalNoInit())
423 {
424 if (locked)
425 self()->globalPRNGMutex.lock();
426 }
427 ~PRNGLocker()
428 {
429 if (locked)
430 self()->globalPRNGMutex.unlock();
431 }
432 };
433};
434
435inline QRandomGenerator::SystemGenerator &QRandomGenerator::SystemGenerator::self()
436{
437 return SystemAndGlobalGenerators::self()->sys;
438}
439
440/*!
441 \class QRandomGenerator
442 \inmodule QtCore
443 \reentrant
444 \since 5.10
445
446 \brief The QRandomGenerator class allows one to obtain random values from a
447 high-quality Random Number Generator.
448
449 QRandomGenerator may be used to generate random values from a high-quality
450 random number generator. Like the C++ random engines, QRandomGenerator can
451 be seeded with user-provided values through the constructor.
452 When seeded, the sequence of numbers generated by this
453 class is deterministic. That is to say, given the same seed data,
454 QRandomGenerator will generate the same sequence of numbers. But given
455 different seeds, the results should be considerably different.
456
457 QRandomGenerator::securelySeeded() can be used to create a QRandomGenerator
458 that is securely seeded with QRandomGenerator::system(), meaning that the
459 sequence of numbers it generates cannot be easily predicted. Additionally,
460 QRandomGenerator::global() returns a global instance of QRandomGenerator
461 that Qt will ensure to be securely seeded. This object is thread-safe, may
462 be shared for most uses, and is always seeded from
463 QRandomGenerator::system()
464
465 QRandomGenerator::system() may be used to access the system's
466 cryptographically-safe random generator. On Unix systems, it's equivalent
467 to reading from \c {/dev/urandom} or the \c {getrandom()} or \c
468 {getentropy()} system calls.
469
470 The class can generate 32-bit or 64-bit quantities, or fill an array of
471 those. The most common way of generating new values is to call the generate(),
472 generate64() or fillRange() functions. One would use it as:
473
474 \snippet code/src_corelib_global_qrandom.cpp 0
475
476 Additionally, it provides a floating-point function generateDouble() that
477 returns a number in the range [0, 1) (that is, inclusive of zero and
478 exclusive of 1). There's also a set of convenience functions that
479 facilitate obtaining a random number in a bounded, integral range.
480
481 \section1 Seeding and determinism
482
483 QRandomGenerator may be seeded with specific seed data. When that is done,
484 the numbers generated by the object will always be the same, as in the
485 following example:
486
487 \snippet code/src_corelib_global_qrandom.cpp 1
488
489 The seed data takes the form of one or more 32-bit words. The ideal seed
490 size is approximately equal to the size of the QRandomGenerator class
491 itself. Due to mixing of the seed data, QRandomGenerator cannot guarantee
492 that distinct seeds will produce different sequences.
493
494 QRandomGenerator::global(), like all generators created by
495 QRandomGenerator::securelySeeded(), is always seeded from
496 QRandomGenerator::system(), so it's not possible to make it produce
497 identical sequences.
498
499 \section1 Bulk data
500
501 When operating in deterministic mode, QRandomGenerator may be used for bulk
502 data generation. In fact, applications that do not need
503 cryptographically-secure or true random data are advised to use a regular
504 QRandomGenerator instead of QRandomGenerator::system() for their random
505 data needs.
506
507 For ease of use, QRandomGenerator provides a global object that can
508 be easily used, as in the following example:
509
510 \snippet code/src_corelib_global_qrandom.cpp 2
511
512 \section1 System-wide random number generator
513
514 QRandomGenerator::system() may be used to access the system-wide random
515 number generator, which is cryptographically-safe on all systems that Qt
516 runs on. This function will use hardware facilities to generate random
517 numbers where available. On such systems, those facilities are true Random
518 Number Generators. However, if they are true RNGs, those facilities have
519 finite entropy sources and thus may fail to produce any results if their
520 entropy pool is exhausted.
521
522 If that happens, first the operating system then QRandomGenerator will fall
523 back to Pseudo Random Number Generators of decreasing qualities (Qt's
524 fallback generator being the simplest). Whether those generators are still
525 of cryptographic quality is implementation-defined. Therefore,
526 QRandomGenerator::system() should not be used for high-frequency random
527 number generation, lest the entropy pool become empty. As a rule of thumb,
528 this class should not be called upon to generate more than a kilobyte per
529 second of random data (note: this may vary from system to system).
530
531 If an application needs true RNG data in bulk, it should use the operating
532 system facilities (such as \c{/dev/random} on Linux) directly and wait for
533 entropy to become available. If the application requires PRNG engines of
534 cryptographic quality but not of true randomness,
535 QRandomGenerator::system() may still be used (see section below).
536
537 If neither a true RNG nor a cryptographically secure PRNG are required,
538 applications should instead use PRNG engines like QRandomGenerator's
539 deterministic mode and those from the C++ Standard Library.
540 QRandomGenerator::system() can be used to seed those.
541
542 \section2 Fallback quality
543
544 QRandomGenerator::system() uses the operating system facilities to obtain
545 random numbers, which attempt to collect real entropy from the surrounding
546 environment to produce true random numbers. However, it's possible that the
547 entropy pool becomes exhausted, in which case the operating system will
548 fall back to a pseudo-random engine for a time. Under no circumstances will
549 QRandomGenerator::system() block, waiting for more entropy to be collected.
550
551 The following operating systems guarantee that the results from their
552 random-generation API will be of at least cryptographically-safe quality,
553 even if the entropy pool is exhausted: Apple OSes (Darwin), BSDs, Linux,
554 Windows. Barring a system installation problem (such as \c{/dev/urandom}
555 not being readable by the current process), QRandomGenerator::system() will
556 therefore have the same guarantees.
557
558 On other operating systems, QRandomGenerator will fall back to a PRNG of
559 good numeric distribution, but it cannot guarantee proper seeding in all
560 cases. Please consult the OS documentation for more information.
561
562 Applications that require QRandomGenerator not to fall back to
563 non-cryptographic quality generators are advised to check their operating
564 system documentation or restrict their deployment to one of the above.
565
566 \section1 Reentrancy and thread-safety
567
568 QRandomGenerator is reentrant, meaning that multiple threads can operate on
569 this class at the same time, so long as they operate on different objects.
570 If multiple threads need to share one PRNG sequence, external locking by a
571 mutex is required.
572
573 The exceptions are the objects returned by QRandomGenerator::global() and
574 QRandomGenerator::system(): those objects are thread-safe and may be used
575 by any thread without external locking. Note that thread-safety does not
576 extend to copying those objects: they should always be used by reference.
577
578 \section1 Standard C++ Library compatibility
579
580 QRandomGenerator is modeled after the requirements for random number
581 engines in the C++ Standard Library and may be used in almost all contexts
582 that the Standard Library engines can. Exceptions to the requirements are
583 the following:
584
585 \list
586 \li QRandomGenerator does not support seeding from another seed
587 sequence-like class besides std::seed_seq itself;
588 \li QRandomGenerator is not comparable (but is copyable) or
589 streamable to \c{std::ostream} or from \c{std::istream}.
590 \endlist
591
592 QRandomGenerator is also compatible with the uniform distribution classes
593 \c{std::uniform_int_distribution} and \c{std:uniform_real_distribution}, as
594 well as the free function \c{std::generate_canonical}. For example, the
595 following code may be used to generate a floating-point number in the range
596 [1, 2.5):
597
598 \snippet code/src_corelib_global_qrandom.cpp 3
599
600 \sa QRandomGenerator64
601 */
602
603/*!
604 \enum QRandomGenerator::System
605 \internal
606*/
607
608/*!
609 \fn QRandomGenerator::QRandomGenerator(quint32 seedValue)
610
611 Initializes this QRandomGenerator object with the value \a seedValue as
612 the seed. Two objects constructed or reseeded with the same seed value will
613 produce the same number sequence.
614
615 \sa seed(), securelySeeded()
616 */
617
618/*!
619 \fn template <qsizetype N> QRandomGenerator::QRandomGenerator(const quint32 (&seedBuffer)[N])
620 \overload
621
622 Initializes this QRandomGenerator object with the values found in the
623 array \a seedBuffer as the seed. Two objects constructed or reseeded with
624 the same seed value will produce the same number sequence.
625
626 \sa seed(), securelySeeded()
627 */
628
629/*!
630 \fn QRandomGenerator::QRandomGenerator(const quint32 *seedBuffer, qsizetype len)
631 \overload
632
633 Initializes this QRandomGenerator object with \a len values found in
634 the array \a seedBuffer as the seed. Two objects constructed or reseeded
635 with the same seed value will produce the same number sequence.
636
637 This constructor is equivalent to:
638 \snippet code/src_corelib_global_qrandom.cpp 4
639
640 \sa seed(), securelySeeded()
641 */
642
643/*!
644 \fn QRandomGenerator::QRandomGenerator(const quint32 *begin, const quint32 *end)
645 \overload
646
647 Initializes this QRandomGenerator object with the values found in the range
648 from \a begin to \a end as the seed. Two objects constructed or reseeded
649 with the same seed value will produce the same number sequence.
650
651 This constructor is equivalent to:
652 \snippet code/src_corelib_global_qrandom.cpp 5
653
654 \sa seed(), securelySeeded()
655 */
656
657/*!
658 \fn QRandomGenerator::QRandomGenerator(std::seed_seq &sseq)
659 \overload
660
661 Initializes this QRandomGenerator object with the seed sequence \a
662 sseq as the seed. Two objects constructed or reseeded with the same seed
663 value will produce the same number sequence.
664
665 \sa seed(), securelySeeded()
666 */
667
668/*!
669 \fn QRandomGenerator::QRandomGenerator(const QRandomGenerator &other)
670
671 Creates a copy of the generator state in the \a other object. If \a other is
672 QRandomGenerator::system() or a copy of that, this object will also read
673 from the operating system random-generating facilities. In that case, the
674 sequences generated by the two objects will be different.
675
676 In all other cases, the new QRandomGenerator object will start at the same
677 position in the deterministic sequence as the \a other object was. Both
678 objects will generate the same sequence from this point on.
679
680 For that reason, it is not adviseable to create a copy of
681 QRandomGenerator::global(). If one needs an exclusive deterministic
682 generator, consider instead using securelySeeded() to obtain a new object
683 that shares no relationship with the QRandomGenerator::global().
684 */
685
686/*!
687 \fn bool operator==(const QRandomGenerator &rng1, const QRandomGenerator &rng2)
688 \relates QRandomGenerator
689
690 Returns true if the two the two engines \a rng1 and \a rng2 are at the same
691 state or if they are both reading from the operating system facilities,
692 false otherwise.
693*/
694
695/*!
696 \fn bool QRandomGenerator::operator!=(const QRandomGenerator &rng1, const QRandomGenerator &rng2)
697
698 Returns true if the two the two engines \a rng1 and \a rng2 are at
699 different states or if one of them is reading from the operating system
700 facilities and the other is not, false otherwise.
701*/
702
703/*!
704 \typedef QRandomGenerator::result_type
705
706 A typedef to the type that operator() returns. That is, quint32.
707
708 \sa operator()
709 */
710
711/*!
712 \fn result_type QRandomGenerator::operator()()
713
714 Generates a 32-bit random quantity and returns it.
715
716 \sa generate(), generate64()
717 */
718
719/*!
720 \fn quint32 QRandomGenerator::generate()
721
722 Generates a 32-bit random quantity and returns it.
723
724 \sa {QRandomGenerator::operator()}{operator()()}, generate64()
725 */
726
727/*!
728 \fn quint64 QRandomGenerator::generate64()
729
730 Generates a 64-bit random quantity and returns it.
731
732 \sa {QRandomGenerator::operator()}{operator()()}, generate()
733 */
734
735/*!
736 \fn result_type QRandomGenerator::min()
737
738 Returns the minimum value that QRandomGenerator may ever generate. That is, 0.
739
740 \sa max(), QRandomGenerator64::min()
741 */
742
743/*!
744 \fn result_type QRandomGenerator::max()
745
746 Returns the maximum value that QRandomGenerator may ever generate. That is,
747 \c {std::numeric_limits<result_type>::max()}.
748
749 \sa min(), QRandomGenerator64::max()
750 */
751
752/*!
753 \fn void QRandomGenerator::seed(quint32 seed)
754
755 Reseeds this object using the value \a seed as the seed.
756 */
757
758/*!
759 \fn void QRandomGenerator::seed(std::seed_seq &seed)
760 \overload
761
762 Reseeds this object using the seed sequence \a seed as the seed.
763 */
764
765/*!
766 \fn void QRandomGenerator::discard(unsigned long long z)
767
768 Discards the next \a z entries from the sequence. This method is equivalent
769 to calling generate() \a z times and discarding the result, as in:
770
771 \snippet code/src_corelib_global_qrandom.cpp 6
772*/
773
774/*!
775 \fn template <typename ForwardIterator> void QRandomGenerator::generate(ForwardIterator begin, ForwardIterator end)
776
777 Generates 32-bit quantities and stores them in the range between \a begin
778 and \a end. This function is equivalent to (and is implemented as):
779
780 \snippet code/src_corelib_global_qrandom.cpp 7
781
782 This function complies with the requirements for the function
783 \l{http://en.cppreference.com/w/cpp/numeric/random/seed_seq/generate}{\c std::seed_seq::generate},
784 which requires unsigned 32-bit integer values.
785
786 Note that if the [begin, end) range refers to an area that can store more
787 than 32 bits per element, the elements will still be initialized with only
788 32 bits of data. Any other bits will be zero. To fill the range with 64 bit
789 quantities, one can write:
790
791 \snippet code/src_corelib_global_qrandom.cpp 8
792
793 If the range refers to contiguous memory (such as an array or the data from
794 a QList), the fillRange() function may be used too.
795
796 \sa fillRange()
797 */
798
799/*!
800 \fn void QRandomGenerator::generate(quint32 *begin, quint32 *end)
801 \overload
802 \internal
803
804 Same as the other overload, but more efficiently fills \a begin to \a end.
805 */
806
807/*!
808 \fn template <typename UInt> void QRandomGenerator::fillRange(UInt *buffer, qsizetype count)
809
810 Generates \a count 32- or 64-bit quantities (depending on the type \c UInt)
811 and stores them in the buffer pointed by \a buffer. This is the most
812 efficient way to obtain more than one quantity at a time, as it reduces the
813 number of calls into the Random Number Generator source.
814
815 For example, to fill a list of 16 entries with random values, one may
816 write:
817
818 \snippet code/src_corelib_global_qrandom.cpp 9
819
820 \sa generate()
821 */
822
823/*!
824 \fn template <typename UInt, size_t N> void QRandomGenerator::fillRange(UInt (&buffer)[N])
825
826 Generates \c N 32- or 64-bit quantities (depending on the type \c UInt) and
827 stores them in the \a buffer array. This is the most efficient way to
828 obtain more than one quantity at a time, as it reduces the number of calls
829 into the Random Number Generator source.
830
831 For example, to fill generate two 32-bit quantities, one may write:
832
833 \snippet code/src_corelib_global_qrandom.cpp 10
834
835 It would have also been possible to make one call to generate64() and then split
836 the two halves of the 64-bit value.
837
838 \sa generate()
839 */
840
841/*!
842 \fn qreal QRandomGenerator::generateDouble()
843
844 Generates one random qreal in the canonical range [0, 1) (that is,
845 inclusive of zero and exclusive of 1).
846
847 This function is equivalent to:
848 \snippet code/src_corelib_global_qrandom.cpp 11
849
850 The same may also be obtained by using
851 \l{http://en.cppreference.com/w/cpp/numeric/random/uniform_real_distribution}{\c std::uniform_real_distribution}
852 with parameters 0 and 1.
853
854 \sa generate(), generate64(), bounded()
855 */
856
857/*!
858 \fn double QRandomGenerator::bounded(double highest)
859
860 Generates one random double in the range between 0 (inclusive) and \a
861 highest (exclusive). This function is equivalent to and is implemented as:
862
863 \snippet code/src_corelib_global_qrandom.cpp 12
864
865 If the \a highest parameter is negative, the result will be negative too;
866 if it is infinite or NaN, the result will be infinite or NaN too (that is,
867 not random).
868
869 \sa generateDouble(), bounded()
870 */
871
872/*!
873 \fn quint32 QRandomGenerator::bounded(quint32 highest)
874 \overload
875
876 Generates one random 32-bit quantity in the range between 0 (inclusive) and
877 \a highest (exclusive). The same result may also be obtained by using
878 \l{http://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution}{\c std::uniform_int_distribution}
879 with parameters 0 and \c{highest - 1}. That class can also be used to obtain
880 quantities larger than 32 bits; for 64 bits, the 64-bit bounded() overload
881 can be used too.
882
883 For example, to obtain a value between 0 and 255 (inclusive), one would write:
884
885 \snippet code/src_corelib_global_qrandom.cpp 13
886
887 Naturally, the same could also be obtained by masking the result of generate()
888 to only the lower 8 bits. Either solution is as efficient.
889
890 Note that this function cannot be used to obtain values in the full 32-bit
891 range of quint32. Instead, use generate().
892
893 \sa generate(), generate64(), generateDouble()
894 */
895
896/*!
897 \fn int QRandomGenerator::bounded(int highest)
898 \overload
899
900 Generates one random 32-bit quantity in the range between 0 (inclusive) and
901 \a highest (exclusive). \a highest must be positive.
902
903 Note that this function cannot be used to obtain values in the full 32-bit
904 range of int. Instead, use generate() and cast to int.
905
906 \sa generate(), generate64(), generateDouble()
907 */
908
909/*!
910 \fn quint64 QRandomGenerator::bounded(quint64 highest)
911 \overload
912
913 Generates one random 64-bit quantity in the range between 0 (inclusive) and
914 \a highest (exclusive). The same result may also be obtained by using
915 \l{http://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution}{\c std::uniform_int_distribution<quint64>}
916 with parameters 0 and \c{highest - 1}.
917
918 Note that this function cannot be used to obtain values in the full 64-bit
919 range of \c{quint64}. Instead, use generate64().
920
921 \note This function is implemented as a loop, which depends on the random
922 value obtained. On the long run, on average it should loop just under 2
923 times, but if the random generator is defective, this function may take
924 considerably longer to execute.
925
926 \sa generate(), generate64(), generateDouble()
927 */
928
929/*!
930 \fn qint64 QRandomGenerator::bounded(qint64 highest)
931 \overload
932
933 Generates one random 64-bit quantity in the range between 0 (inclusive) and
934 \a highest (exclusive). \a highest must be positive.
935
936 Note that this function cannot be used to obtain values in the full 64-bit
937 range of \c{qint64}. Instead, use generate64() and cast to qint64 or instead
938 use the unsigned version of this function.
939
940 \note This function is implemented as a loop, which depends on the random
941 value obtained. On the long run, on average it should loop just under 2
942 times, but if the random generator is defective, this function may take
943 considerably longer to execute.
944
945 \sa generate(), generate64(), generateDouble()
946 */
947
948/*!
949 \fn quint32 QRandomGenerator::bounded(quint32 lowest, quint32 highest)
950 \overload
951
952 Generates one random 32-bit quantity in the range between \a lowest
953 (inclusive) and \a highest (exclusive). The \a highest parameter must be
954 greater than \a lowest.
955
956 The same result may also be obtained by using
957 \l{http://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution}{\c std::uniform_int_distribution}
958 with parameters \a lowest and \c{\a highest - 1}. That class can also be used to
959 obtain quantities larger than 32 bits.
960
961 For example, to obtain a value between 1000 (incl.) and 2000 (excl.), one
962 would write:
963
964 \snippet code/src_corelib_global_qrandom.cpp 14
965
966 Note that this function cannot be used to obtain values in the full 32-bit
967 range of quint32. Instead, use generate().
968
969 \sa generate(), generate64(), generateDouble()
970 */
971
972/*!
973 \fn int QRandomGenerator::bounded(int lowest, int highest)
974 \overload
975
976 Generates one random 32-bit quantity in the range between \a lowest
977 (inclusive) and \a highest (exclusive), both of which may be negative, but
978 \a highest must be greater than \a lowest.
979
980 Note that this function cannot be used to obtain values in the full 32-bit
981 range of int. Instead, use generate() and cast to int.
982
983 \sa generate(), generate64(), generateDouble()
984 */
985
986/*!
987 \fn quint64 QRandomGenerator::bounded(quint64 lowest, quint64 highest)
988 \overload
989
990 Generates one random 64-bit quantity in the range between \a lowest
991 (inclusive) and \a highest (exclusive). The \a highest parameter must be
992 greater than \a lowest.
993
994 The same result may also be obtained by using
995 \l{http://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution}{\c std::uniform_int_distribution<quint64>}
996 with parameters \a lowest and \c{\a highest - 1}.
997
998 Note that this function cannot be used to obtain values in the full 64-bit
999 range of \c{quint64}. Instead, use generate64().
1000
1001 \note This function is implemented as a loop, which depends on the random
1002 value obtained. On the long run, on average it should loop just under 2
1003 times, but if the random generator is defective, this function may take
1004 considerably longer to execute.
1005
1006 \sa generate(), generate64(), generateDouble()
1007 */
1008
1009/*!
1010 \fn qint64 QRandomGenerator::bounded(qint64 lowest, qint64 highest)
1011 \overload
1012
1013 Generates one random 64-bit quantity in the range between \a lowest
1014 (inclusive) and \a highest (exclusive), both of which may be negative, but
1015 \a highest must be greater than \a lowest.
1016
1017 Note that this function cannot be used to obtain values in the full 64-bit
1018 range of \c{qint64}. Instead, use generate64() and cast to qint64.
1019
1020 \note This function is implemented as a loop, which depends on the random
1021 value obtained. On the long run, on average it should loop just under 2
1022 times, but if the random generator is defective, this function may take
1023 considerably longer to execute.
1024
1025 \sa generate(), generate64(), generateDouble()
1026 */
1027
1028/*!
1029 \fn qint64 QRandomGenerator::bounded(int lowest, qint64 highest)
1030 \fn qint64 QRandomGenerator::bounded(qint64 lowest, int highest)
1031 \fn quint64 QRandomGenerator::bounded(unsigned lowest, quint64 highest)
1032 \fn quint64 QRandomGenerator::bounded(quint64 lowest, unsigned highest)
1033 \overload
1034
1035 This function exists to help with overload resolution when the types of the
1036 parameters don't exactly match. They will promote the smaller type to the
1037 type of the larger one and call the correct overload.
1038 */
1039
1040/*!
1041 \fn QRandomGenerator *QRandomGenerator::system()
1042 \threadsafe
1043
1044 Returns a pointer to a shared QRandomGenerator that always uses the
1045 facilities provided by the operating system to generate random numbers. The
1046 system facilities are considered to be cryptographically safe on at least
1047 the following operating systems: Apple OSes (Darwin), BSDs, Linux, Windows.
1048 That may also be the case on other operating systems.
1049
1050 They are also possibly backed by a true hardware random number generator.
1051 For that reason, the QRandomGenerator returned by this function should not
1052 be used for bulk data generation. Instead, use it to seed QRandomGenerator
1053 or a random engine from the <random> header.
1054
1055 The object returned by this function is thread-safe and may be used in any
1056 thread without locks. It may also be copied and the resulting
1057 QRandomGenerator will also access the operating system facilities, but they
1058 will not generate the same sequence.
1059
1060 \sa securelySeeded(), global()
1061*/
1062
1063/*!
1064 \fn QRandomGenerator *QRandomGenerator::global()
1065 \threadsafe
1066
1067 Returns a pointer to a shared QRandomGenerator that was seeded using
1068 securelySeeded(). This function should be used to create random data
1069 without the expensive creation of a securely-seeded QRandomGenerator
1070 for a specific use or storing the rather large QRandomGenerator object.
1071
1072 For example, the following creates a random RGB color:
1073
1074 \snippet code/src_corelib_global_qrandom.cpp 15
1075
1076 Accesses to this object are thread-safe and it may therefore be used in any
1077 thread without locks. The object may also be copied and the sequence
1078 produced by the copy will be the same as the shared object will produce.
1079 Note, however, that if there are other threads accessing the global object,
1080 those threads may obtain samples at unpredictable intervals.
1081
1082 \sa securelySeeded(), system()
1083*/
1084
1085/*!
1086 \fn QRandomGenerator QRandomGenerator::securelySeeded()
1087
1088 Returns a new QRandomGenerator object that was securely seeded with
1089 QRandomGenerator::system(). This function will obtain the ideal seed size
1090 for the algorithm that QRandomGenerator uses and is therefore the
1091 recommended way for creating a new QRandomGenerator object that will be
1092 kept for some time.
1093
1094 Given the amount of data required to securely seed the deterministic
1095 engine, this function is somewhat expensive and should not be used for
1096 short-term uses of QRandomGenerator (using it to generate fewer than 2600
1097 bytes of random data is effectively a waste of resources). If the use
1098 doesn't require that much data, consider using QRandomGenerator::global()
1099 and not storing a QRandomGenerator object instead.
1100
1101 \sa global(), system()
1102 */
1103
1104/*!
1105 \class QRandomGenerator64
1106 \inmodule QtCore
1107 \since 5.10
1108
1109 \brief The QRandomGenerator64 class allows one to obtain 64-bit random values
1110 from a high-quality, seed-less Random Number Generator.
1111
1112 QRandomGenerator64 is a simple adaptor class around QRandomGenerator, making the
1113 QRandomGenerator::generate64() function the default for operator()(), instead of the
1114 function that returns 32-bit quantities. This class is intended to be used
1115 in conjunction with Standard Library algorithms that need 64-bit quantities
1116 instead of 32-bit ones.
1117
1118 In all other aspects, the class is the same. Please refer to
1119 QRandomGenerator's documentation for more information.
1120
1121 \sa QRandomGenerator
1122*/
1123
1124/*!
1125 \typedef QRandomGenerator64::result_type
1126
1127 A typedef to the type that operator() returns. That is, quint64.
1128
1129 \sa operator()
1130 */
1131
1132/*!
1133 \fn quint64 QRandomGenerator64::generate()
1134
1135 Generates one 64-bit random value and returns it.
1136
1137 Note about casting to a signed integer: all bits returned by this function
1138 are random, so there's a 50% chance that the most significant bit will be
1139 set. If you wish to cast the returned value to qint64 and keep it positive,
1140 you should mask the sign bit off:
1141
1142 \snippet code/src_corelib_global_qrandom.cpp 16
1143
1144 \sa QRandomGenerator, QRandomGenerator::generate64()
1145 */
1146
1147/*!
1148 \fn result_type QRandomGenerator64::operator()()
1149
1150 Generates a 64-bit random quantity and returns it.
1151
1152 \sa QRandomGenerator::generate(), QRandomGenerator::generate64()
1153 */
1154
1155constexpr QRandomGenerator::Storage::Storage()
1156 : dummy(0)
1157{
1158 // nothing
1159}
1160
1161inline QRandomGenerator64::QRandomGenerator64(System s)
1162 : QRandomGenerator(s)
1163{
1164}
1165
1166QRandomGenerator64 *QRandomGenerator64::system()
1167{
1168 auto self = SystemAndGlobalGenerators::system();
1169 Q_ASSERT(self->type == SystemRNG);
1170 return self;
1171}
1172
1173QRandomGenerator64 *QRandomGenerator64::global()
1174{
1175 auto self = SystemAndGlobalGenerators::globalNoInit();
1176
1177 // Yes, this is a double-checked lock.
1178 // We can return even if the type is not completely initialized yet:
1179 // any thread trying to actually use the contents of the random engine
1180 // will necessarily wait on the lock.
1181 if (Q_LIKELY(self->type != SystemRNG))
1182 return self;
1183
1184 SystemAndGlobalGenerators::PRNGLocker locker(self);
1185 if (self->type == SystemRNG)
1186 SystemAndGlobalGenerators::securelySeed(self);
1187
1188 return self;
1189}
1190
1191QRandomGenerator64 QRandomGenerator64::securelySeeded()
1192{
1193 QRandomGenerator64 result(System{});
1194 SystemAndGlobalGenerators::securelySeed(&result);
1195 return result;
1196}
1197
1198/*!
1199 \internal
1200*/
1201inline QRandomGenerator::QRandomGenerator(System)
1202 : type(SystemRNG)
1203{
1204 // don't touch storage
1205}
1206
1207QRandomGenerator::QRandomGenerator(const QRandomGenerator &other)
1208 : type(other.type)
1209{
1210 Q_ASSERT(this != system());
1211 Q_ASSERT(this != SystemAndGlobalGenerators::globalNoInit());
1212
1213 if (type != SystemRNG) {
1214 SystemAndGlobalGenerators::PRNGLocker lock(&other);
1215 storage.engine() = other.storage.engine();
1216 }
1217}
1218
1219QRandomGenerator &QRandomGenerator::operator=(const QRandomGenerator &other)
1220{
1221 if (Q_UNLIKELY(this == system()) || Q_UNLIKELY(this == SystemAndGlobalGenerators::globalNoInit()))
1222 qFatal("Attempted to overwrite a QRandomGenerator to system() or global().");
1223
1224 if ((type = other.type) != SystemRNG) {
1225 SystemAndGlobalGenerators::PRNGLocker lock(&other);
1226 storage.engine() = other.storage.engine();
1227 }
1228 return *this;
1229}
1230
1231QRandomGenerator::QRandomGenerator(std::seed_seq &sseq) noexcept
1232 : type(MersenneTwister)
1233{
1234 Q_ASSERT(this != system());
1235 Q_ASSERT(this != SystemAndGlobalGenerators::globalNoInit());
1236
1237 new (&storage.engine()) RandomEngine(sseq);
1238}
1239
1240QRandomGenerator::QRandomGenerator(const quint32 *begin, const quint32 *end)
1241 : type(MersenneTwister)
1242{
1243 Q_ASSERT(this != system());
1244 Q_ASSERT(this != SystemAndGlobalGenerators::globalNoInit());
1245
1246 std::seed_seq s(begin, end);
1247 new (&storage.engine()) RandomEngine(s);
1248}
1249
1250void QRandomGenerator::discard(unsigned long long z)
1251{
1252 if (Q_UNLIKELY(type == SystemRNG))
1253 return;
1254
1255 SystemAndGlobalGenerators::PRNGLocker lock(this);
1256 storage.engine().discard(z);
1257}
1258
1259bool operator==(const QRandomGenerator &rng1, const QRandomGenerator &rng2)
1260{
1261 if (rng1.type != rng2.type)
1262 return false;
1263 if (rng1.type == SystemRNG)
1264 return true;
1265
1266 // Lock global() if either is it (otherwise this locking is a no-op)
1267 using PRNGLocker = QRandomGenerator::SystemAndGlobalGenerators::PRNGLocker;
1268 PRNGLocker locker(&rng1 == QRandomGenerator::global() ? &rng1 : &rng2);
1269 return rng1.storage.engine() == rng2.storage.engine();
1270}
1271
1272/*!
1273 \internal
1274
1275 Fills the range pointed by \a buffer with \a count 32-bit random values.
1276 The buffer must be correctly aligned.
1277
1278 Returns the value of the first two 32-bit entries as a \c{quint64}.
1279 */
1280quint64 QRandomGenerator::_fillRange(void *buffer, qptrdiff count)
1281{
1282 // Verify that the pointers are properly aligned for 32-bit
1283 Q_ASSERT(quintptr(buffer) % sizeof(quint32) == 0);
1284 Q_ASSERT(count >= 0);
1285 Q_ASSERT(buffer || count <= 2);
1286
1287 quint64 dummy;
1288 quint32 *begin = static_cast<quint32 *>(buffer ? buffer : &dummy);
1289 quint32 *end = begin + count;
1290
1291 if (type == SystemRNG || Q_UNLIKELY(uint(qt_randomdevice_control.loadAcquire()) & (UseSystemRNG|SetRandomData))) {
1292 SystemGenerator::self().generate(begin, end);
1293 } else {
1294 SystemAndGlobalGenerators::PRNGLocker lock(this);
1295 std::generate(begin, end, [this]() { return storage.engine()(); });
1296 }
1297
1298 if (end - begin == 1)
1299 return *begin;
1300 return begin[0] | (quint64(begin[1]) << 32);
1301}
1302
1303namespace {
1304struct QRandEngine
1305{
1306 std::minstd_rand engine;
1307 QRandEngine() : engine(1) {}
1308
1309 int generate()
1310 {
1311 std::minstd_rand::result_type v = engine();
1312 if (std::numeric_limits<int>::max() != RAND_MAX)
1313 v %= uint(RAND_MAX) + 1;
1314
1315 return int(v);
1316 }
1317
1318 void seed(std::minstd_rand::result_type q)
1319 {
1320 engine.seed(q);
1321 }
1322};
1323}
1324
1325QT_END_NAMESPACE
1326