From 2e1763d83a1dacfc5b747934fb77fa7cec7bfe47 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 3 Mar 2016 20:20:42 +0100 Subject: Non-associative containers: add range constructors Something nice we'd like to detect for array-backed containers is if the iterator passed is a Contiguous one; if the type is also trivially copyable / Q_PRIMITIVE_TYPE, we could memcpy() the whole range. However, there's no trait in the Standard to detect contiguous iterators (the best approximation would be detecting if the iterator is actually a pointer). Also, it's probably not smart to do the work now for QVector since QVector needs refactoring anyhow, and this work will be lost. QString and QByteArray are left in another commit. [ChangeLog][QtCore][QVector] Added range constructor. [ChangeLog][QtCore][QVarLengthArray] Added range constructor. [ChangeLog][QtCore][QList] Added range constructor. [ChangeLog][QtCore][QStringList] Added range constructor. [ChangeLog][QtCore][QLinkedList] Added range constructor. [ChangeLog][QtCore][QSet] Added range constructor. Change-Id: I220edb796053c9c4d31a6dbdc7efc5fc0f6678f9 Reviewed-by: Milian Wolff --- src/corelib/tools/qcontainertools_impl.h | 93 ++++++++++++++++++++++++++++++++ src/corelib/tools/qlinkedlist.cpp | 8 +++ src/corelib/tools/qlinkedlist.h | 10 ++-- src/corelib/tools/qlist.cpp | 8 +++ src/corelib/tools/qlist.h | 16 +++++- src/corelib/tools/qset.h | 14 +++-- src/corelib/tools/qset.qdoc | 11 ++++ src/corelib/tools/qstringlist.cpp | 7 +++ src/corelib/tools/qstringlist.h | 4 ++ src/corelib/tools/qvarlengtharray.h | 13 +++-- src/corelib/tools/qvarlengtharray.qdoc | 8 +++ src/corelib/tools/qvector.h | 13 +++++ src/corelib/tools/qvector.qdoc | 7 +++ src/corelib/tools/tools.pri | 1 + 14 files changed, 201 insertions(+), 12 deletions(-) create mode 100644 src/corelib/tools/qcontainertools_impl.h (limited to 'src') diff --git a/src/corelib/tools/qcontainertools_impl.h b/src/corelib/tools/qcontainertools_impl.h new file mode 100644 index 0000000000..c2de50b145 --- /dev/null +++ b/src/corelib/tools/qcontainertools_impl.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz +** Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#if 0 +#pragma qt_sync_skip_header_check +#pragma qt_sync_stop_processing +#endif + +#ifndef QCONTAINERTOOLS_IMPL_H +#define QCONTAINERTOOLS_IMPL_H + +#include +#include + +#ifndef Q_QDOC + +QT_BEGIN_NAMESPACE + +namespace QtPrivate +{ +template +using IfIsInputIterator = typename std::enable_if< + std::is_convertible::iterator_category, std::input_iterator_tag>::value, + bool>::type; + +template +using IfIsForwardIterator = typename std::enable_if< + std::is_convertible::iterator_category, std::forward_iterator_tag>::value, + bool>::type; + +template +using IfIsNotForwardIterator = typename std::enable_if< + !std::is_convertible::iterator_category, std::forward_iterator_tag>::value, + bool>::type; + +template = true> +void reserveIfForwardIterator(Container *, InputIterator, InputIterator) +{ +} + +template = true> +void reserveIfForwardIterator(Container *c, ForwardIterator f, ForwardIterator l) +{ + c->reserve(static_cast(std::distance(f, l))); +} +} // namespace QtPrivate + +QT_END_NAMESPACE + +#endif // Q_QDOC + +#endif // QCONTAINERTOOLS_IMPL_H diff --git a/src/corelib/tools/qlinkedlist.cpp b/src/corelib/tools/qlinkedlist.cpp index d9d93862e5..c0450f5cd8 100644 --- a/src/corelib/tools/qlinkedlist.cpp +++ b/src/corelib/tools/qlinkedlist.cpp @@ -153,6 +153,14 @@ const QLinkedListData QLinkedListData::shared_null = { initializer lists. */ +/*! \fn template template QLinkedList::QLinkedList(InputIterator first, InputIterator last) + \since 5.14 + + Constructs a list with the contents in the iterator range [\a first, \a last). + + The value type of \c InputIterator must be convertible to \c T. +*/ + /*! \fn template QLinkedList::~QLinkedList() Destroys the list. References to the values in the list, and all diff --git a/src/corelib/tools/qlinkedlist.h b/src/corelib/tools/qlinkedlist.h index 91367a74b3..83f70deceb 100644 --- a/src/corelib/tools/qlinkedlist.h +++ b/src/corelib/tools/qlinkedlist.h @@ -42,6 +42,7 @@ #include #include +#include #include #include @@ -84,11 +85,14 @@ public: inline QLinkedList(const QLinkedList &l) : d(l.d) { d->ref.ref(); if (!d->sharable) detach(); } #if defined(Q_COMPILER_INITIALIZER_LISTS) inline QLinkedList(std::initializer_list list) - : d(const_cast(&QLinkedListData::shared_null)) + : QLinkedList(list.begin(), list.end()) {} +#endif + template = true> + inline QLinkedList(InputIterator first, InputIterator last) + : QLinkedList() { - std::copy(list.begin(), list.end(), std::back_inserter(*this)); + std::copy(first, last, std::back_inserter(*this)); } -#endif ~QLinkedList(); QLinkedList &operator=(const QLinkedList &); #ifdef Q_COMPILER_RVALUE_REFS diff --git a/src/corelib/tools/qlist.cpp b/src/corelib/tools/qlist.cpp index 6f8084c676..48617f0539 100644 --- a/src/corelib/tools/qlist.cpp +++ b/src/corelib/tools/qlist.cpp @@ -545,6 +545,14 @@ void **QListData::erase(void **xi) \since 5.2 */ +/*! \fn template template QList::QList(InputIterator first, InputIterator last) + \since 5.14 + + Constructs a QList with the contents in the iterator range [\a first, \a last). + + The value type of \c InputIterator must be convertible to \c T. +*/ + /*! \fn template QList QList::mid(int pos, int length) const diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index 77d8df4a88..dfb8a8a4ab 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -46,6 +46,7 @@ #include #include #include +#include #include #include @@ -169,9 +170,11 @@ public: inline void swap(QList &other) noexcept { qSwap(d, other.d); } #ifdef Q_COMPILER_INITIALIZER_LISTS inline QList(std::initializer_list args) - : d(const_cast(&QListData::shared_null)) - { reserve(int(args.size())); std::copy(args.begin(), args.end(), std::back_inserter(*this)); } + : QList(args.begin(), args.end()) {} #endif + template = true> + QList(InputIterator first, InputIterator last); + bool operator==(const QList &l) const; inline bool operator!=(const QList &l) const { return !(*this == l); } @@ -842,6 +845,15 @@ Q_OUTOFLINE_TEMPLATE QList::~QList() dealloc(d); } +template +template > +QList::QList(InputIterator first, InputIterator last) + : QList() +{ + QtPrivate::reserveIfForwardIterator(this, first, last); + std::copy(first, last, std::back_inserter(*this)); +} + template Q_OUTOFLINE_TEMPLATE bool QList::operator==(const QList &l) const { diff --git a/src/corelib/tools/qset.h b/src/corelib/tools/qset.h index aa915f7ed1..7ae715d247 100644 --- a/src/corelib/tools/qset.h +++ b/src/corelib/tools/qset.h @@ -41,6 +41,8 @@ #define QSET_H #include +#include + #ifdef Q_COMPILER_INITIALIZER_LISTS #include #endif @@ -59,12 +61,16 @@ public: inline QSet() noexcept {} #ifdef Q_COMPILER_INITIALIZER_LISTS inline QSet(std::initializer_list list) + : QSet(list.begin(), list.end()) {} +#endif + template = true> + inline QSet(InputIterator first, InputIterator last) { - reserve(int(list.size())); - for (typename std::initializer_list::const_iterator it = list.begin(); it != list.end(); ++it) - insert(*it); + QtPrivate::reserveIfForwardIterator(this, first, last); + for (; first != last; ++first) + insert(*first); } -#endif + // compiler-generated copy/move ctor/assignment operators are fine! // compiler-generated destructor is fine! diff --git a/src/corelib/tools/qset.qdoc b/src/corelib/tools/qset.qdoc index 48863f2399..2e7a5a29ce 100644 --- a/src/corelib/tools/qset.qdoc +++ b/src/corelib/tools/qset.qdoc @@ -113,6 +113,17 @@ compiled in C++11 mode. */ +/*! \fn template template QSet::QSet(InputIterator first, InputIterator last) + \since 5.14 + + Constructs a set with the contents in the iterator range [\a first, \a last). + + The value type of \c InputIterator must be convertible to \c T. + + \note If the range [\a first, \a last) contains duplicate elements, + the first one is retained. +*/ + /*! \fn template void QSet::swap(QSet &other) diff --git a/src/corelib/tools/qstringlist.cpp b/src/corelib/tools/qstringlist.cpp index cc6eaf8ad2..49247d66b8 100644 --- a/src/corelib/tools/qstringlist.cpp +++ b/src/corelib/tools/qstringlist.cpp @@ -847,5 +847,12 @@ int QtPrivate::QStringList_removeDuplicates(QStringList *that) lists. */ + /*! \fn template QStringList::QStringList(InputIterator first, InputIterator last) + \since 5.14 + + Constructs a QStringList with the contents in the iterator range [\a first, \a last). + + The value type of \c InputIterator must be convertible to \c QString. + */ QT_END_NAMESPACE diff --git a/src/corelib/tools/qstringlist.h b/src/corelib/tools/qstringlist.h index 6387161269..5ad01a0658 100644 --- a/src/corelib/tools/qstringlist.h +++ b/src/corelib/tools/qstringlist.h @@ -44,6 +44,7 @@ #define QSTRINGLIST_H #include +#include #include #include #include @@ -109,6 +110,9 @@ public: #ifdef Q_COMPILER_INITIALIZER_LISTS inline QStringList(std::initializer_list args) : QList(args) { } #endif + template = true> + inline QStringList(InputIterator first, InputIterator last) + : QList(first, last) { } QStringList &operator=(const QList &other) { QList::operator=(other); return *this; } diff --git a/src/corelib/tools/qvarlengtharray.h b/src/corelib/tools/qvarlengtharray.h index c03fbb2218..c81af68593 100644 --- a/src/corelib/tools/qvarlengtharray.h +++ b/src/corelib/tools/qvarlengtharray.h @@ -43,6 +43,7 @@ #include #include #include +#include #include #include @@ -71,13 +72,19 @@ public: #ifdef Q_COMPILER_INITIALIZER_LISTS QVarLengthArray(std::initializer_list args) - : a(Prealloc), s(0), ptr(reinterpret_cast(array)) + : QVarLengthArray(args.begin(), args.end()) { - if (args.size()) - append(args.begin(), int(args.size())); } #endif + template = true> + inline QVarLengthArray(InputIterator first, InputIterator last) + : QVarLengthArray() + { + QtPrivate::reserveIfForwardIterator(this, first, last); + std::copy(first, last, std::back_inserter(*this)); + } + inline ~QVarLengthArray() { if (QTypeInfo::isComplex) { T *i = ptr + s; diff --git a/src/corelib/tools/qvarlengtharray.qdoc b/src/corelib/tools/qvarlengtharray.qdoc index bc8df82517..80769e3769 100644 --- a/src/corelib/tools/qvarlengtharray.qdoc +++ b/src/corelib/tools/qvarlengtharray.qdoc @@ -110,6 +110,14 @@ lists. */ +/*! \fn template template QVarLengthArray::QVarLengthArray(InputIterator first, InputIterator last) + \since 5.14 + + Constructs an array with the contents in the iterator range [\a first, \a last). + + The value type of \c InputIterator must be convertible to \c T. +*/ + /*! \fn template QVarLengthArray::~QVarLengthArray() diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h index 096c369e51..6cbf794c6c 100644 --- a/src/corelib/tools/qvector.h +++ b/src/corelib/tools/qvector.h @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -81,6 +82,9 @@ public: inline QVector(std::initializer_list args); QVector &operator=(std::initializer_list args); #endif + template = true> + inline QVector(InputIterator first, InputIterator last); + bool operator==(const QVector &v) const; inline bool operator!=(const QVector &v) const { return !(*this == v); } @@ -557,6 +561,15 @@ QT_WARNING_POP # endif // Q_CC_MSVC #endif // Q_COMPILER_INITIALIZER_LISTS +template +template > +QVector::QVector(InputIterator first, InputIterator last) + : QVector() +{ + QtPrivate::reserveIfForwardIterator(this, first, last); + std::copy(first, last, std::back_inserter(*this)); +} + template void QVector::freeData(Data *x) { diff --git a/src/corelib/tools/qvector.qdoc b/src/corelib/tools/qvector.qdoc index 69bbb5f9a2..cb47d36356 100644 --- a/src/corelib/tools/qvector.qdoc +++ b/src/corelib/tools/qvector.qdoc @@ -243,6 +243,13 @@ lists. */ +/*! \fn template template QVector::QVector(InputIterator first, InputIterator last) + \since 5.14 + + Constructs a vector with the contents in the iterator range [\a first, \a last). + + The value type of \c InputIterator must be convertible to \c T. +*/ /*! \fn template QVector::~QVector() diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri index 995bab694e..5dcb6c9ee0 100644 --- a/src/corelib/tools/tools.pri +++ b/src/corelib/tools/tools.pri @@ -18,6 +18,7 @@ HEADERS += \ tools/qcollator.h \ tools/qcollator_p.h \ tools/qcontainerfwd.h \ + tools/qcontainertools_impl.h \ tools/qcryptographichash.h \ tools/qdatetime.h \ tools/qdatetime_p.h \ -- cgit v1.2.3 From dea94de304e92f162ed0f1d4a30f03717a19b198 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Mon, 18 Dec 2017 07:54:00 +0100 Subject: Import MD4C Markdown parser into 3rdparty MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It has an MIT license and will be used to add Markdown (CommonMark) support to QTextDocument. Currently this is version 0.3.0 RC plus a few more patches. [ChangeLog][Third-Party Code] Qt Gui: Added md4c markdown parser to src/3rdparty/md4c (MIT licensed). Change-Id: Ie74373c89f2a30ba76ee728aee5e1ca166829f44 Reviewed-by: Lisandro Damián Nicanor Pérez Meyer Reviewed-by: Lars Knoll Reviewed-by: Gatis Paeglis --- src/3rdparty/md4c.pri | 3 + src/3rdparty/md4c/LICENSE.md | 22 + src/3rdparty/md4c/md4c.c | 6016 +++++++++++++++++++++++++++++++++ src/3rdparty/md4c/md4c.h | 359 ++ src/3rdparty/md4c/qt_attribution.json | 15 + 5 files changed, 6415 insertions(+) create mode 100644 src/3rdparty/md4c.pri create mode 100644 src/3rdparty/md4c/LICENSE.md create mode 100644 src/3rdparty/md4c/md4c.c create mode 100644 src/3rdparty/md4c/md4c.h create mode 100644 src/3rdparty/md4c/qt_attribution.json (limited to 'src') diff --git a/src/3rdparty/md4c.pri b/src/3rdparty/md4c.pri new file mode 100644 index 0000000000..e0150dc6ed --- /dev/null +++ b/src/3rdparty/md4c.pri @@ -0,0 +1,3 @@ +INCLUDEPATH += $$PWD/md4c +HEADERS += $$PWD/md4c/md4c.h +SOURCES += $$PWD/md4c/md4c.c diff --git a/src/3rdparty/md4c/LICENSE.md b/src/3rdparty/md4c/LICENSE.md new file mode 100644 index 0000000000..d58ef9341d --- /dev/null +++ b/src/3rdparty/md4c/LICENSE.md @@ -0,0 +1,22 @@ + +# The MIT License (MIT) + +Copyright © 2016-2019 Martin Mitáš + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the “Software”), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. diff --git a/src/3rdparty/md4c/md4c.c b/src/3rdparty/md4c/md4c.c new file mode 100644 index 0000000000..4c0ad5c0fc --- /dev/null +++ b/src/3rdparty/md4c/md4c.c @@ -0,0 +1,6016 @@ +/* + * MD4C: Markdown parser for C + * (http://github.com/mity/md4c) + * + * Copyright (c) 2016-2019 Martin Mitas + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "md4c.h" + +#include +#include +#include + + +/***************************** + *** Miscellaneous Stuff *** + *****************************/ + +#ifdef _MSC_VER + /* MSVC does not understand "inline" when building as pure C (not C++). + * However it understands "__inline" */ + #ifndef __cplusplus + #define inline __inline + #endif +#endif + +#ifdef _T + #undef _T +#endif +#if defined MD4C_USE_UTF16 + #define _T(x) L##x +#else + #define _T(x) x +#endif + +/* Misc. macros. */ +#define SIZEOF_ARRAY(a) (sizeof(a) / sizeof(a[0])) + +#define STRINGIZE_(x) #x +#define STRINGIZE(x) STRINGIZE_(x) + +#ifndef TRUE + #define TRUE 1 + #define FALSE 0 +#endif + + +/************************ + *** Internal Types *** + ************************/ + +/* These are omnipresent so lets save some typing. */ +#define CHAR MD_CHAR +#define SZ MD_SIZE +#define OFF MD_OFFSET + +typedef struct MD_MARK_tag MD_MARK; +typedef struct MD_BLOCK_tag MD_BLOCK; +typedef struct MD_CONTAINER_tag MD_CONTAINER; +typedef struct MD_REF_DEF_tag MD_REF_DEF; + + +/* During analyzes of inline marks, we need to manage some "mark chains", + * of (yet unresolved) openers. This structure holds start/end of the chain. + * The chain internals are then realized through MD_MARK::prev and ::next. + */ +typedef struct MD_MARKCHAIN_tag MD_MARKCHAIN; +struct MD_MARKCHAIN_tag { + int head; /* Index of first mark in the chain, or -1 if empty. */ + int tail; /* Index of last mark in the chain, or -1 if empty. */ +}; + +/* Context propagated through all the parsing. */ +typedef struct MD_CTX_tag MD_CTX; +struct MD_CTX_tag { + /* Immutable stuff (parameters of md_parse()). */ + const CHAR* text; + SZ size; + MD_PARSER parser; + void* userdata; + + /* Helper temporary growing buffer. */ + CHAR* buffer; + unsigned alloc_buffer; + + /* Reference definitions. */ + MD_REF_DEF* ref_defs; + int n_ref_defs; + int alloc_ref_defs; + void** ref_def_hashtable; + int ref_def_hashtable_size; + + /* Stack of inline/span markers. + * This is only used for parsing a single block contents but by storing it + * here we may reuse the stack for subsequent blocks; i.e. we have fewer + * (re)allocations. */ + MD_MARK* marks; + int n_marks; + int alloc_marks; + +#if defined MD4C_USE_UTF16 + char mark_char_map[128]; +#else + char mark_char_map[256]; +#endif + + /* For resolving of inline spans. */ + MD_MARKCHAIN mark_chains[8]; +#define PTR_CHAIN ctx->mark_chains[0] +#define TABLECELLBOUNDARIES ctx->mark_chains[1] +#define BACKTICK_OPENERS ctx->mark_chains[2] +#define LOWERTHEN_OPENERS ctx->mark_chains[3] +#define ASTERISK_OPENERS ctx->mark_chains[4] +#define UNDERSCORE_OPENERS ctx->mark_chains[5] +#define TILDE_OPENERS ctx->mark_chains[6] +#define BRACKET_OPENERS ctx->mark_chains[7] +#define OPENERS_CHAIN_FIRST 2 +#define OPENERS_CHAIN_LAST 7 + + int n_table_cell_boundaries; + + /* For resolving links. */ + int unresolved_link_head; + int unresolved_link_tail; + + /* For block analysis. + * Notes: + * -- It holds MD_BLOCK as well as MD_LINE structures. After each + * MD_BLOCK, its (multiple) MD_LINE(s) follow. + * -- For MD_BLOCK_HTML and MD_BLOCK_CODE, MD_VERBATIMLINE(s) are used + * instead of MD_LINE(s). + */ + void* block_bytes; + MD_BLOCK* current_block; + int n_block_bytes; + int alloc_block_bytes; + + /* For container block analysis. */ + MD_CONTAINER* containers; + int n_containers; + int alloc_containers; + + int last_line_has_list_loosening_effect; + int last_list_item_starts_with_two_blank_lines; + + /* Minimal indentation to call the block "indented code block". */ + unsigned code_indent_offset; + + /* Contextual info for line analysis. */ + SZ code_fence_length; /* For checking closing fence length. */ + int html_block_type; /* For checking closing raw HTML condition. */ +}; + +typedef enum MD_LINETYPE_tag MD_LINETYPE; +enum MD_LINETYPE_tag { + MD_LINE_BLANK, + MD_LINE_HR, + MD_LINE_ATXHEADER, + MD_LINE_SETEXTHEADER, + MD_LINE_SETEXTUNDERLINE, + MD_LINE_INDENTEDCODE, + MD_LINE_FENCEDCODE, + MD_LINE_HTML, + MD_LINE_TEXT, + MD_LINE_TABLE, + MD_LINE_TABLEUNDERLINE +}; + +typedef struct MD_LINE_ANALYSIS_tag MD_LINE_ANALYSIS; +struct MD_LINE_ANALYSIS_tag { + MD_LINETYPE type : 16; + unsigned data : 16; + OFF beg; + OFF end; + unsigned indent; /* Indentation level. */ +}; + +typedef struct MD_LINE_tag MD_LINE; +struct MD_LINE_tag { + OFF beg; + OFF end; +}; + +typedef struct MD_VERBATIMLINE_tag MD_VERBATIMLINE; +struct MD_VERBATIMLINE_tag { + OFF beg; + OFF end; + OFF indent; +}; + + +/******************* + *** Debugging *** + *******************/ + +#define MD_LOG(msg) \ + do { \ + if(ctx->parser.debug_log != NULL) \ + ctx->parser.debug_log((msg), ctx->userdata); \ + } while(0) + +#ifdef DEBUG + #define MD_ASSERT(cond) \ + do { \ + if(!(cond)) { \ + MD_LOG(__FILE__ ":" STRINGIZE(__LINE__) ": " \ + "Assertion '" STRINGIZE(cond) "' failed."); \ + exit(1); \ + } \ + } while(0) + + #define MD_UNREACHABLE() MD_ASSERT(1 == 0) +#else + #ifdef __GNUC__ + #define MD_ASSERT(cond) do { if(!(cond)) __builtin_unreachable(); } while(0) + #define MD_UNREACHABLE() do { __builtin_unreachable(); } while(0) + #elif defined _MSC_VER && _MSC_VER > 120 + #define MD_ASSERT(cond) do { __assume(cond); } while(0) + #define MD_UNREACHABLE() do { __assume(0); } while(0) + #else + #define MD_ASSERT(cond) do {} while(0) + #define MD_UNREACHABLE() do {} while(0) + #endif +#endif + + +/***************** + *** Helpers *** + *****************/ + +/* Character accessors. */ +#define CH(off) (ctx->text[(off)]) +#define STR(off) (ctx->text + (off)) + +/* Character classification. + * Note we assume ASCII compatibility of code points < 128 here. */ +#define ISIN_(ch, ch_min, ch_max) ((ch_min) <= (unsigned)(ch) && (unsigned)(ch) <= (ch_max)) +#define ISANYOF_(ch, palette) (md_strchr((palette), (ch)) != NULL) +#define ISANYOF2_(ch, ch1, ch2) ((ch) == (ch1) || (ch) == (ch2)) +#define ISANYOF3_(ch, ch1, ch2, ch3) ((ch) == (ch1) || (ch) == (ch2) || (ch) == (ch3)) +#define ISASCII_(ch) ((unsigned)(ch) <= 127) +#define ISBLANK_(ch) (ISANYOF2_((ch), _T(' '), _T('\t'))) +#define ISNEWLINE_(ch) (ISANYOF2_((ch), _T('\r'), _T('\n'))) +#define ISWHITESPACE_(ch) (ISBLANK_(ch) || ISANYOF2_((ch), _T('\v'), _T('\f'))) +#define ISCNTRL_(ch) ((unsigned)(ch) <= 31 || (unsigned)(ch) == 127) +#define ISPUNCT_(ch) (ISIN_(ch, 33, 47) || ISIN_(ch, 58, 64) || ISIN_(ch, 91, 96) || ISIN_(ch, 123, 126)) +#define ISUPPER_(ch) (ISIN_(ch, _T('A'), _T('Z'))) +#define ISLOWER_(ch) (ISIN_(ch, _T('a'), _T('z'))) +#define ISALPHA_(ch) (ISUPPER_(ch) || ISLOWER_(ch)) +#define ISDIGIT_(ch) (ISIN_(ch, _T('0'), _T('9'))) +#define ISXDIGIT_(ch) (ISDIGIT_(ch) || ISIN_(ch, _T('A'), _T('F')) || ISIN_(ch, _T('a'), _T('f'))) +#define ISALNUM_(ch) (ISALPHA_(ch) || ISDIGIT_(ch)) + +#define ISANYOF(off, palette) ISANYOF_(CH(off), (palette)) +#define ISANYOF2(off, ch1, ch2) ISANYOF2_(CH(off), (ch1), (ch2)) +#define ISANYOF3(off, ch1, ch2, ch3) ISANYOF3_(CH(off), (ch1), (ch2), (ch3)) +#define ISASCII(off) ISASCII_(CH(off)) +#define ISBLANK(off) ISBLANK_(CH(off)) +#define ISNEWLINE(off) ISNEWLINE_(CH(off)) +#define ISWHITESPACE(off) ISWHITESPACE_(CH(off)) +#define ISCNTRL(off) ISCNTRL_(CH(off)) +#define ISPUNCT(off) ISPUNCT_(CH(off)) +#define ISUPPER(off) ISUPPER_(CH(off)) +#define ISLOWER(off) ISLOWER_(CH(off)) +#define ISALPHA(off) ISALPHA_(CH(off)) +#define ISDIGIT(off) ISDIGIT_(CH(off)) +#define ISXDIGIT(off) ISXDIGIT_(CH(off)) +#define ISALNUM(off) ISALNUM_(CH(off)) +static inline const CHAR* +md_strchr(const CHAR* str, CHAR ch) +{ + OFF i; + for(i = 0; str[i] != _T('\0'); i++) { + if(ch == str[i]) + return (str + i); + } + return NULL; +} + +/* Case insensitive check of string equality. */ +static inline int +md_ascii_case_eq(const CHAR* s1, const CHAR* s2, SZ n) +{ + OFF i; + for(i = 0; i < n; i++) { + CHAR ch1 = s1[i]; + CHAR ch2 = s2[i]; + + if(ISLOWER_(ch1)) + ch1 += ('A'-'a'); + if(ISLOWER_(ch2)) + ch2 += ('A'-'a'); + if(ch1 != ch2) + return FALSE; + } + return TRUE; +} + +static inline int +md_ascii_eq(const CHAR* s1, const CHAR* s2, SZ n) +{ + return memcmp(s1, s2, n * sizeof(CHAR)) == 0; +} + +static int +md_text_with_null_replacement(MD_CTX* ctx, MD_TEXTTYPE type, const CHAR* str, SZ size) +{ + OFF off = 0; + int ret = 0; + + while(1) { + while(off < size && str[off] != _T('\0')) + off++; + + if(off > 0) { + ret = ctx->parser.text(type, str, off, ctx->userdata); + if(ret != 0) + return ret; + + str += off; + size -= off; + off = 0; + } + + if(off >= size) + return 0; + + ret = ctx->parser.text(MD_TEXT_NULLCHAR, _T(""), 1, ctx->userdata); + if(ret != 0) + return ret; + off++; + } +} + + +#define MD_CHECK(func) \ + do { \ + ret = (func); \ + if(ret < 0) \ + goto abort; \ + } while(0) + + +#define MD_TEMP_BUFFER(sz) \ + do { \ + if(sz > ctx->alloc_buffer) { \ + CHAR* new_buffer; \ + SZ new_size = ((sz) + (sz) / 2 + 128) & ~127; \ + \ + new_buffer = realloc(ctx->buffer, new_size); \ + if(new_buffer == NULL) { \ + MD_LOG("realloc() failed."); \ + ret = -1; \ + goto abort; \ + } \ + \ + ctx->buffer = new_buffer; \ + ctx->alloc_buffer = new_size; \ + } \ + } while(0) + + +#define MD_ENTER_BLOCK(type, arg) \ + do { \ + ret = ctx->parser.enter_block((type), (arg), ctx->userdata); \ + if(ret != 0) { \ + MD_LOG("Aborted from enter_block() callback."); \ + goto abort; \ + } \ + } while(0) + +#define MD_LEAVE_BLOCK(type, arg) \ + do { \ + ret = ctx->parser.leave_block((type), (arg), ctx->userdata); \ + if(ret != 0) { \ + MD_LOG("Aborted from leave_block() callback."); \ + goto abort; \ + } \ + } while(0) + +#define MD_ENTER_SPAN(type, arg) \ + do { \ + ret = ctx->parser.enter_span((type), (arg), ctx->userdata); \ + if(ret != 0) { \ + MD_LOG("Aborted from enter_span() callback."); \ + goto abort; \ + } \ + } while(0) + +#define MD_LEAVE_SPAN(type, arg) \ + do { \ + ret = ctx->parser.leave_span((type), (arg), ctx->userdata); \ + if(ret != 0) { \ + MD_LOG("Aborted from leave_span() callback."); \ + goto abort; \ + } \ + } while(0) + +#define MD_TEXT(type, str, size) \ + do { \ + if(size > 0) { \ + ret = ctx->parser.text((type), (str), (size), ctx->userdata); \ + if(ret != 0) { \ + MD_LOG("Aborted from text() callback."); \ + goto abort; \ + } \ + } \ + } while(0) + +#define MD_TEXT_INSECURE(type, str, size) \ + do { \ + if(size > 0) { \ + ret = md_text_with_null_replacement(ctx, type, str, size); \ + if(ret != 0) { \ + MD_LOG("Aborted from text() callback."); \ + goto abort; \ + } \ + } \ + } while(0) + + + +/************************* + *** Unicode Support *** + *************************/ + +typedef struct MD_UNICODE_FOLD_INFO_tag MD_UNICODE_FOLD_INFO; +struct MD_UNICODE_FOLD_INFO_tag { + int codepoints[3]; + int n_codepoints; +}; + + +#if defined MD4C_USE_UTF16 || defined MD4C_USE_UTF8 + static int + md_is_unicode_whitespace__(int codepoint) + { + /* The ASCII ones are the most frequently used ones, so lets check them first. */ + if(codepoint <= 0x7f) + return ISWHITESPACE_(codepoint); + + /* Check for Unicode codepoints in Zs class above 127. */ + if(codepoint == 0x00a0 || codepoint == 0x1680) + return TRUE; + if(0x2000 <= codepoint && codepoint <= 0x200a) + return TRUE; + if(codepoint == 0x202f || codepoint == 0x205f || codepoint == 0x3000) + return TRUE; + + return FALSE; + } + + static int + md_unicode_cmp__(const void* p_codepoint_a, const void* p_codepoint_b) + { + return (*(const int*)p_codepoint_a - *(const int*)p_codepoint_b); + } + + static int + md_is_unicode_punct__(int codepoint) + { + /* non-ASCII (above 127) Unicode punctuation codepoints (classes + * Pc, Pd, Pe, Pf, Pi, Po, Ps). + * + * Warning: Keep the array sorted. + */ + static const int punct_list[] = { + 0x00a1, 0x00a7, 0x00ab, 0x00b6, 0x00b7, 0x00bb, 0x00bf, 0x037e, 0x0387, 0x055a, 0x055b, 0x055c, 0x055d, 0x055e, 0x055f, 0x0589, + 0x058a, 0x05be, 0x05c0, 0x05c3, 0x05c6, 0x05f3, 0x05f4, 0x0609, 0x060a, 0x060c, 0x060d, 0x061b, 0x061e, 0x061f, 0x066a, 0x066b, + 0x066c, 0x066d, 0x06d4, 0x0700, 0x0701, 0x0702, 0x0703, 0x0704, 0x0705, 0x0706, 0x0707, 0x0708, 0x0709, 0x070a, 0x070b, 0x070c, + 0x070d, 0x07f7, 0x07f8, 0x07f9, 0x0830, 0x0831, 0x0832, 0x0833, 0x0834, 0x0835, 0x0836, 0x0837, 0x0838, 0x0839, 0x083a, 0x083b, + 0x083c, 0x083d, 0x083e, 0x085e, 0x0964, 0x0965, 0x0970, 0x0af0, 0x0df4, 0x0e4f, 0x0e5a, 0x0e5b, 0x0f04, 0x0f05, 0x0f06, 0x0f07, + 0x0f08, 0x0f09, 0x0f0a, 0x0f0b, 0x0f0c, 0x0f0d, 0x0f0e, 0x0f0f, 0x0f10, 0x0f11, 0x0f12, 0x0f14, 0x0f3a, 0x0f3b, 0x0f3c, 0x0f3d, + 0x0f85, 0x0fd0, 0x0fd1, 0x0fd2, 0x0fd3, 0x0fd4, 0x0fd9, 0x0fda, 0x104a, 0x104b, 0x104c, 0x104d, 0x104e, 0x104f, 0x10fb, 0x1360, + 0x1361, 0x1362, 0x1363, 0x1364, 0x1365, 0x1366, 0x1367, 0x1368, 0x1400, 0x166d, 0x166e, 0x169b, 0x169c, 0x16eb, 0x16ec, 0x16ed, + 0x1735, 0x1736, 0x17d4, 0x17d5, 0x17d6, 0x17d8, 0x17d9, 0x17da, 0x1800, 0x1801, 0x1802, 0x1803, 0x1804, 0x1805, 0x1806, 0x1807, + 0x1808, 0x1809, 0x180a, 0x1944, 0x1945, 0x1a1e, 0x1a1f, 0x1aa0, 0x1aa1, 0x1aa2, 0x1aa3, 0x1aa4, 0x1aa5, 0x1aa6, 0x1aa8, 0x1aa9, + 0x1aaa, 0x1aab, 0x1aac, 0x1aad, 0x1b5a, 0x1b5b, 0x1b5c, 0x1b5d, 0x1b5e, 0x1b5f, 0x1b60, 0x1bfc, 0x1bfd, 0x1bfe, 0x1bff, 0x1c3b, + 0x1c3c, 0x1c3d, 0x1c3e, 0x1c3f, 0x1c7e, 0x1c7f, 0x1cc0, 0x1cc1, 0x1cc2, 0x1cc3, 0x1cc4, 0x1cc5, 0x1cc6, 0x1cc7, 0x1cd3, 0x2010, + 0x2011, 0x2012, 0x2013, 0x2014, 0x2015, 0x2016, 0x2017, 0x2018, 0x2019, 0x201a, 0x201b, 0x201c, 0x201d, 0x201e, 0x201f, 0x2020, + 0x2021, 0x2022, 0x2023, 0x2024, 0x2025, 0x2026, 0x2027, 0x2030, 0x2031, 0x2032, 0x2033, 0x2034, 0x2035, 0x2036, 0x2037, 0x2038, + 0x2039, 0x203a, 0x203b, 0x203c, 0x203d, 0x203e, 0x203f, 0x2040, 0x2041, 0x2042, 0x2043, 0x2045, 0x2046, 0x2047, 0x2048, 0x2049, + 0x204a, 0x204b, 0x204c, 0x204d, 0x204e, 0x204f, 0x2050, 0x2051, 0x2053, 0x2054, 0x2055, 0x2056, 0x2057, 0x2058, 0x2059, 0x205a, + 0x205b, 0x205c, 0x205d, 0x205e, 0x207d, 0x207e, 0x208d, 0x208e, 0x2308, 0x2309, 0x230a, 0x230b, 0x2329, 0x232a, 0x2768, 0x2769, + 0x276a, 0x276b, 0x276c, 0x276d, 0x276e, 0x276f, 0x2770, 0x2771, 0x2772, 0x2773, 0x2774, 0x2775, 0x27c5, 0x27c6, 0x27e6, 0x27e7, + 0x27e8, 0x27e9, 0x27ea, 0x27eb, 0x27ec, 0x27ed, 0x27ee, 0x27ef, 0x2983, 0x2984, 0x2985, 0x2986, 0x2987, 0x2988, 0x2989, 0x298a, + 0x298b, 0x298c, 0x298d, 0x298e, 0x298f, 0x2990, 0x2991, 0x2992, 0x2993, 0x2994, 0x2995, 0x2996, 0x2997, 0x2998, 0x29d8, 0x29d9, + 0x29da, 0x29db, 0x29fc, 0x29fd, 0x2cf9, 0x2cfa, 0x2cfb, 0x2cfc, 0x2cfe, 0x2cff, 0x2d70, 0x2e00, 0x2e01, 0x2e02, 0x2e03, 0x2e04, + 0x2e05, 0x2e06, 0x2e07, 0x2e08, 0x2e09, 0x2e0a, 0x2e0b, 0x2e0c, 0x2e0d, 0x2e0e, 0x2e0f, 0x2e10, 0x2e11, 0x2e12, 0x2e13, 0x2e14, + 0x2e15, 0x2e16, 0x2e17, 0x2e18, 0x2e19, 0x2e1a, 0x2e1b, 0x2e1c, 0x2e1d, 0x2e1e, 0x2e1f, 0x2e20, 0x2e21, 0x2e22, 0x2e23, 0x2e24, + 0x2e25, 0x2e26, 0x2e27, 0x2e28, 0x2e29, 0x2e2a, 0x2e2b, 0x2e2c, 0x2e2d, 0x2e2e, 0x2e30, 0x2e31, 0x2e32, 0x2e33, 0x2e34, 0x2e35, + 0x2e36, 0x2e37, 0x2e38, 0x2e39, 0x2e3a, 0x2e3b, 0x2e3c, 0x2e3d, 0x2e3e, 0x2e3f, 0x2e40, 0x2e41, 0x2e42, 0x2e43, 0x2e44, 0x3001, + 0x3002, 0x3003, 0x3008, 0x3009, 0x300a, 0x300b, 0x300c, 0x300d, 0x300e, 0x300f, 0x3010, 0x3011, 0x3014, 0x3015, 0x3016, 0x3017, + 0x3018, 0x3019, 0x301a, 0x301b, 0x301c, 0x301d, 0x301e, 0x301f, 0x3030, 0x303d, 0x30a0, 0x30fb, 0xa4fe, 0xa4ff, 0xa60d, 0xa60e, + 0xa60f, 0xa673, 0xa67e, 0xa6f2, 0xa6f3, 0xa6f4, 0xa6f5, 0xa6f6, 0xa6f7, 0xa874, 0xa875, 0xa876, 0xa877, 0xa8ce, 0xa8cf, 0xa8f8, + 0xa8f9, 0xa8fa, 0xa8fc, 0xa92e, 0xa92f, 0xa95f, 0xa9c1, 0xa9c2, 0xa9c3, 0xa9c4, 0xa9c5, 0xa9c6, 0xa9c7, 0xa9c8, 0xa9c9, 0xa9ca, + 0xa9cb, 0xa9cc, 0xa9cd, 0xa9de, 0xa9df, 0xaa5c, 0xaa5d, 0xaa5e, 0xaa5f, 0xaade, 0xaadf, 0xaaf0, 0xaaf1, 0xabeb, 0xfd3e, 0xfd3f, + 0xfe10, 0xfe11, 0xfe12, 0xfe13, 0xfe14, 0xfe15, 0xfe16, 0xfe17, 0xfe18, 0xfe19, 0xfe30, 0xfe31, 0xfe32, 0xfe33, 0xfe34, 0xfe35, + 0xfe36, 0xfe37, 0xfe38, 0xfe39, 0xfe3a, 0xfe3b, 0xfe3c, 0xfe3d, 0xfe3e, 0xfe3f, 0xfe40, 0xfe41, 0xfe42, 0xfe43, 0xfe44, 0xfe45, + 0xfe46, 0xfe47, 0xfe48, 0xfe49, 0xfe4a, 0xfe4b, 0xfe4c, 0xfe4d, 0xfe4e, 0xfe4f, 0xfe50, 0xfe51, 0xfe52, 0xfe54, 0xfe55, 0xfe56, + 0xfe57, 0xfe58, 0xfe59, 0xfe5a, 0xfe5b, 0xfe5c, 0xfe5d, 0xfe5e, 0xfe5f, 0xfe60, 0xfe61, 0xfe63, 0xfe68, 0xfe6a, 0xfe6b, 0xff01, + 0xff02, 0xff03, 0xff05, 0xff06, 0xff07, 0xff08, 0xff09, 0xff0a, 0xff0c, 0xff0d, 0xff0e, 0xff0f, 0xff1a, 0xff1b, 0xff1f, 0xff20, + 0xff3b, 0xff3c, 0xff3d, 0xff3f, 0xff5b, 0xff5d, 0xff5f, 0xff60, 0xff61, 0xff62, 0xff63, 0xff64, 0xff65, 0x10100, 0x10101, 0x10102, + 0x1039f, 0x103d0, 0x1056f, 0x10857, 0x1091f, 0x1093f, 0x10a50, 0x10a51, 0x10a52, 0x10a53, 0x10a54, 0x10a55, 0x10a56, 0x10a57, 0x10a58, 0x10a7f, + 0x10af0, 0x10af1, 0x10af2, 0x10af3, 0x10af4, 0x10af5, 0x10af6, 0x10b39, 0x10b3a, 0x10b3b, 0x10b3c, 0x10b3d, 0x10b3e, 0x10b3f, 0x10b99, 0x10b9a, + 0x10b9b, 0x10b9c, 0x11047, 0x11048, 0x11049, 0x1104a, 0x1104b, 0x1104c, 0x1104d, 0x110bb, 0x110bc, 0x110be, 0x110bf, 0x110c0, 0x110c1, 0x11140, + 0x11141, 0x11142, 0x11143, 0x11174, 0x11175, 0x111c5, 0x111c6, 0x111c7, 0x111c8, 0x111c9, 0x111cd, 0x111db, 0x111dd, 0x111de, 0x111df, 0x11238, + 0x11239, 0x1123a, 0x1123b, 0x1123c, 0x1123d, 0x112a9, 0x1144b, 0x1144c, 0x1144d, 0x1144e, 0x1144f, 0x1145b, 0x1145d, 0x114c6, 0x115c1, 0x115c2, + 0x115c3, 0x115c4, 0x115c5, 0x115c6, 0x115c7, 0x115c8, 0x115c9, 0x115ca, 0x115cb, 0x115cc, 0x115cd, 0x115ce, 0x115cf, 0x115d0, 0x115d1, 0x115d2, + 0x115d3, 0x115d4, 0x115d5, 0x115d6, 0x115d7, 0x11641, 0x11642, 0x11643, 0x11660, 0x11661, 0x11662, 0x11663, 0x11664, 0x11665, 0x11666, 0x11667, + 0x11668, 0x11669, 0x1166a, 0x1166b, 0x1166c, 0x1173c, 0x1173d, 0x1173e, 0x11c41, 0x11c42, 0x11c43, 0x11c44, 0x11c45, 0x11c70, 0x11c71, 0x12470, + 0x12471, 0x12472, 0x12473, 0x12474, 0x16a6e, 0x16a6f, 0x16af5, 0x16b37, 0x16b38, 0x16b39, 0x16b3a, 0x16b3b, 0x16b44, 0x1bc9f, 0x1da87, 0x1da88, + 0x1da89, 0x1da8a, 0x1da8b, 0x1e95e, 0x1e95f + }; + + /* The ASCII ones are the most frequently used ones, so lets check them first. */ + if(codepoint <= 0x7f) + return ISPUNCT_(codepoint); + + return (bsearch(&codepoint, punct_list, SIZEOF_ARRAY(punct_list), sizeof(int), md_unicode_cmp__) != NULL); + } + + static void + md_get_unicode_fold_info(int codepoint, MD_UNICODE_FOLD_INFO* info) + { + /* This maps single codepoint within a range to a single codepoint + * within an offseted range. */ + static const struct { + int min_codepoint; + int max_codepoint; + int offset; + } range_map[] = { + { 0x00c0, 0x00d6, 32 }, { 0x00d8, 0x00de, 32 }, { 0x0388, 0x038a, 37 }, { 0x0391, 0x03a1, 32 }, { 0x03a3, 0x03ab, 32 }, { 0x0400, 0x040f, 80 }, + { 0x0410, 0x042f, 32 }, { 0x0531, 0x0556, 48 }, { 0x1f08, 0x1f0f, -8 }, { 0x1f18, 0x1f1d, -8 }, { 0x1f28, 0x1f2f, -8 }, { 0x1f38, 0x1f3f, -8 }, + { 0x1f48, 0x1f4d, -8 }, { 0x1f68, 0x1f6f, -8 }, { 0x1fc8, 0x1fcb, -86 }, { 0x2160, 0x216f, 16 }, { 0x24b6, 0x24cf, 26 }, { 0xff21, 0xff3a, 32 }, + { 0x10400, 0x10425, 40 } + }; + + /* This maps single codepoint to another single codepoint. */ + static const struct { + int src_codepoint; + int dest_codepoint; + } single_map[] = { + { 0x00b5, 0x03bc }, { 0x0100, 0x0101 }, { 0x0102, 0x0103 }, { 0x0104, 0x0105 }, { 0x0106, 0x0107 }, { 0x0108, 0x0109 }, { 0x010a, 0x010b }, { 0x010c, 0x010d }, + { 0x010e, 0x010f }, { 0x0110, 0x0111 }, { 0x0112, 0x0113 }, { 0x0114, 0x0115 }, { 0x0116, 0x0117 }, { 0x0118, 0x0119 }, { 0x011a, 0x011b }, { 0x011c, 0x011d }, + { 0x011e, 0x011f }, { 0x0120, 0x0121 }, { 0x0122, 0x0123 }, { 0x0124, 0x0125 }, { 0x0126, 0x0127 }, { 0x0128, 0x0129 }, { 0x012a, 0x012b }, { 0x012c, 0x012d }, + { 0x012e, 0x012f }, { 0x0132, 0x0133 }, { 0x0134, 0x0135 }, { 0x0136, 0x0137 }, { 0x0139, 0x013a }, { 0x013b, 0x013c }, { 0x013d, 0x013e }, { 0x013f, 0x0140 }, + { 0x0141, 0x0142 }, { 0x0143, 0x0144 }, { 0x0145, 0x0146 }, { 0x0147, 0x0148 }, { 0x014a, 0x014b }, { 0x014c, 0x014d }, { 0x014e, 0x014f }, { 0x0150, 0x0151 }, + { 0x0152, 0x0153 }, { 0x0154, 0x0155 }, { 0x0156, 0x0157 }, { 0x0158, 0x0159 }, { 0x015a, 0x015b }, { 0x015c, 0x015d }, { 0x015e, 0x015f }, { 0x0160, 0x0161 }, + { 0x0162, 0x0163 }, { 0x0164, 0x0165 }, { 0x0166, 0x0167 }, { 0x0168, 0x0169 }, { 0x016a, 0x016b }, { 0x016c, 0x016d }, { 0x016e, 0x016f }, { 0x0170, 0x0171 }, + { 0x0172, 0x0173 }, { 0x0174, 0x0175 }, { 0x0176, 0x0177 }, { 0x0178, 0x00ff }, { 0x0179, 0x017a }, { 0x017b, 0x017c }, { 0x017d, 0x017e }, { 0x017f, 0x0073 }, + { 0x0181, 0x0253 }, { 0x0182, 0x0183 }, { 0x0184, 0x0185 }, { 0x0186, 0x0254 }, { 0x0187, 0x0188 }, { 0x0189, 0x0256 }, { 0x018a, 0x0257 }, { 0x018b, 0x018c }, + { 0x018e, 0x01dd }, { 0x018f, 0x0259 }, { 0x0190, 0x025b }, { 0x0191, 0x0192 }, { 0x0193, 0x0260 }, { 0x0194, 0x0263 }, { 0x0196, 0x0269 }, { 0x0197, 0x0268 }, + { 0x0198, 0x0199 }, { 0x019c, 0x026f }, { 0x019d, 0x0272 }, { 0x019f, 0x0275 }, { 0x01a0, 0x01a1 }, { 0x01a2, 0x01a3 }, { 0x01a4, 0x01a5 }, { 0x01a6, 0x0280 }, + { 0x01a7, 0x01a8 }, { 0x01a9, 0x0283 }, { 0x01ac, 0x01ad }, { 0x01ae, 0x0288 }, { 0x01af, 0x01b0 }, { 0x01b1, 0x028a }, { 0x01b2, 0x028b }, { 0x01b3, 0x01b4 }, + { 0x01b5, 0x01b6 }, { 0x01b7, 0x0292 }, { 0x01b8, 0x01b9 }, { 0x01bc, 0x01bd }, { 0x01c4, 0x01c6 }, { 0x01c5, 0x01c6 }, { 0x01c7, 0x01c9 }, { 0x01c8, 0x01c9 }, + { 0x01ca, 0x01cc }, { 0x01cb, 0x01cc }, { 0x01cd, 0x01ce }, { 0x01cf, 0x01d0 }, { 0x01d1, 0x01d2 }, { 0x01d3, 0x01d4 }, { 0x01d5, 0x01d6 }, { 0x01d7, 0x01d8 }, + { 0x01d9, 0x01da }, { 0x01db, 0x01dc }, { 0x01de, 0x01df }, { 0x01e0, 0x01e1 }, { 0x01e2, 0x01e3 }, { 0x01e4, 0x01e5 }, { 0x01e6, 0x01e7 }, { 0x01e8, 0x01e9 }, + { 0x01ea, 0x01eb }, { 0x01ec, 0x01ed }, { 0x01ee, 0x01ef }, { 0x01f1, 0x01f3 }, { 0x01f2, 0x01f3 }, { 0x01f4, 0x01f5 }, { 0x01f6, 0x0195 }, { 0x01f7, 0x01bf }, + { 0x01f8, 0x01f9 }, { 0x01fa, 0x01fb }, { 0x01fc, 0x01fd }, { 0x01fe, 0x01ff }, { 0x0200, 0x0201 }, { 0x0202, 0x0203 }, { 0x0204, 0x0205 }, { 0x0206, 0x0207 }, + { 0x0208, 0x0209 }, { 0x020a, 0x020b }, { 0x020c, 0x020d }, { 0x020e, 0x020f }, { 0x0210, 0x0211 }, { 0x0212, 0x0213 }, { 0x0214, 0x0215 }, { 0x0216, 0x0217 }, + { 0x0218, 0x0219 }, { 0x021a, 0x021b }, { 0x021c, 0x021d }, { 0x021e, 0x021f }, { 0x0220, 0x019e }, { 0x0222, 0x0223 }, { 0x0224, 0x0225 }, { 0x0226, 0x0227 }, + { 0x0228, 0x0229 }, { 0x022a, 0x022b }, { 0x022c, 0x022d }, { 0x022e, 0x022f }, { 0x0230, 0x0231 }, { 0x0232, 0x0233 }, { 0x0345, 0x03b9 }, { 0x0386, 0x03ac }, + { 0x038c, 0x03cc }, { 0x038e, 0x03cd }, { 0x038f, 0x03ce }, { 0x03c2, 0x03c3 }, { 0x03d0, 0x03b2 }, { 0x03d1, 0x03b8 }, { 0x03d5, 0x03c6 }, { 0x03d6, 0x03c0 }, + { 0x03d8, 0x03d9 }, { 0x03da, 0x03db }, { 0x03dc, 0x03dd }, { 0x03de, 0x03df }, { 0x03e0, 0x03e1 }, { 0x03e2, 0x03e3 }, { 0x03e4, 0x03e5 }, { 0x03e6, 0x03e7 }, + { 0x03e8, 0x03e9 }, { 0x03ea, 0x03eb }, { 0x03ec, 0x03ed }, { 0x03ee, 0x03ef }, { 0x03f0, 0x03ba }, { 0x03f1, 0x03c1 }, { 0x03f2, 0x03c3 }, { 0x03f4, 0x03b8 }, + { 0x03f5, 0x03b5 }, { 0x0460, 0x0461 }, { 0x0462, 0x0463 }, { 0x0464, 0x0465 }, { 0x0466, 0x0467 }, { 0x0468, 0x0469 }, { 0x046a, 0x046b }, { 0x046c, 0x046d }, + { 0x046e, 0x046f }, { 0x0470, 0x0471 }, { 0x0472, 0x0473 }, { 0x0474, 0x0475 }, { 0x0476, 0x0477 }, { 0x0478, 0x0479 }, { 0x047a, 0x047b }, { 0x047c, 0x047d }, + { 0x047e, 0x047f }, { 0x0480, 0x0481 }, { 0x048a, 0x048b }, { 0x048c, 0x048d }, { 0x048e, 0x048f }, { 0x0490, 0x0491 }, { 0x0492, 0x0493 }, { 0x0494, 0x0495 }, + { 0x0496, 0x0497 }, { 0x0498, 0x0499 }, { 0x049a, 0x049b }, { 0x049c, 0x049d }, { 0x049e, 0x049f }, { 0x04a0, 0x04a1 }, { 0x04a2, 0x04a3 }, { 0x04a4, 0x04a5 }, + { 0x04a6, 0x04a7 }, { 0x04a8, 0x04a9 }, { 0x04aa, 0x04ab }, { 0x04ac, 0x04ad }, { 0x04ae, 0x04af }, { 0x04b0, 0x04b1 }, { 0x04b2, 0x04b3 }, { 0x04b4, 0x04b5 }, + { 0x04b6, 0x04b7 }, { 0x04b8, 0x04b9 }, { 0x04ba, 0x04bb }, { 0x04bc, 0x04bd }, { 0x04be, 0x04bf }, { 0x04c1, 0x04c2 }, { 0x04c3, 0x04c4 }, { 0x04c5, 0x04c6 }, + { 0x04c7, 0x04c8 }, { 0x04c9, 0x04ca }, { 0x04cb, 0x04cc }, { 0x04cd, 0x04ce }, { 0x04d0, 0x04d1 }, { 0x04d2, 0x04d3 }, { 0x04d4, 0x04d5 }, { 0x04d6, 0x04d7 }, + { 0x04d8, 0x04d9 }, { 0x04da, 0x04db }, { 0x04dc, 0x04dd }, { 0x04de, 0x04df }, { 0x04e0, 0x04e1 }, { 0x04e2, 0x04e3 }, { 0x04e4, 0x04e5 }, { 0x04e6, 0x04e7 }, + { 0x04e8, 0x04e9 }, { 0x04ea, 0x04eb }, { 0x04ec, 0x04ed }, { 0x04ee, 0x04ef }, { 0x04f0, 0x04f1 }, { 0x04f2, 0x04f3 }, { 0x04f4, 0x04f5 }, { 0x04f8, 0x04f9 }, + { 0x0500, 0x0501 }, { 0x0502, 0x0503 }, { 0x0504, 0x0505 }, { 0x0506, 0x0507 }, { 0x0508, 0x0509 }, { 0x050a, 0x050b }, { 0x050c, 0x050d }, { 0x050e, 0x050f }, + { 0x1e00, 0x1e01 }, { 0x1e02, 0x1e03 }, { 0x1e04, 0x1e05 }, { 0x1e06, 0x1e07 }, { 0x1e08, 0x1e09 }, { 0x1e0a, 0x1e0b }, { 0x1e0c, 0x1e0d }, { 0x1e0e, 0x1e0f }, + { 0x1e10, 0x1e11 }, { 0x1e12, 0x1e13 }, { 0x1e14, 0x1e15 }, { 0x1e16, 0x1e17 }, { 0x1e18, 0x1e19 }, { 0x1e1a, 0x1e1b }, { 0x1e1c, 0x1e1d }, { 0x1e1e, 0x1e1f }, + { 0x1e20, 0x1e21 }, { 0x1e22, 0x1e23 }, { 0x1e24, 0x1e25 }, { 0x1e26, 0x1e27 }, { 0x1e28, 0x1e29 }, { 0x1e2a, 0x1e2b }, { 0x1e2c, 0x1e2d }, { 0x1e2e, 0x1e2f }, + { 0x1e30, 0x1e31 }, { 0x1e32, 0x1e33 }, { 0x1e34, 0x1e35 }, { 0x1e36, 0x1e37 }, { 0x1e38, 0x1e39 }, { 0x1e3a, 0x1e3b }, { 0x1e3c, 0x1e3d }, { 0x1e3e, 0x1e3f }, + { 0x1e40, 0x1e41 }, { 0x1e42, 0x1e43 }, { 0x1e44, 0x1e45 }, { 0x1e46, 0x1e47 }, { 0x1e48, 0x1e49 }, { 0x1e4a, 0x1e4b }, { 0x1e4c, 0x1e4d }, { 0x1e4e, 0x1e4f }, + { 0x1e50, 0x1e51 }, { 0x1e52, 0x1e53 }, { 0x1e54, 0x1e55 }, { 0x1e56, 0x1e57 }, { 0x1e58, 0x1e59 }, { 0x1e5a, 0x1e5b }, { 0x1e5c, 0x1e5d }, { 0x1e5e, 0x1e5f }, + { 0x1e60, 0x1e61 }, { 0x1e62, 0x1e63 }, { 0x1e64, 0x1e65 }, { 0x1e66, 0x1e67 }, { 0x1e68, 0x1e69 }, { 0x1e6a, 0x1e6b }, { 0x1e6c, 0x1e6d }, { 0x1e6e, 0x1e6f }, + { 0x1e70, 0x1e71 }, { 0x1e72, 0x1e73 }, { 0x1e74, 0x1e75 }, { 0x1e76, 0x1e77 }, { 0x1e78, 0x1e79 }, { 0x1e7a, 0x1e7b }, { 0x1e7c, 0x1e7d }, { 0x1e7e, 0x1e7f }, + { 0x1e80, 0x1e81 }, { 0x1e82, 0x1e83 }, { 0x1e84, 0x1e85 }, { 0x1e86, 0x1e87 }, { 0x1e88, 0x1e89 }, { 0x1e8a, 0x1e8b }, { 0x1e8c, 0x1e8d }, { 0x1e8e, 0x1e8f }, + { 0x1e90, 0x1e91 }, { 0x1e92, 0x1e93 }, { 0x1e94, 0x1e95 }, { 0x1e9b, 0x1e61 }, { 0x1ea0, 0x1ea1 }, { 0x1ea2, 0x1ea3 }, { 0x1ea4, 0x1ea5 }, { 0x1ea6, 0x1ea7 }, + { 0x1ea8, 0x1ea9 }, { 0x1eaa, 0x1eab }, { 0x1eac, 0x1ead }, { 0x1eae, 0x1eaf }, { 0x1eb0, 0x1eb1 }, { 0x1eb2, 0x1eb3 }, { 0x1eb4, 0x1eb5 }, { 0x1eb6, 0x1eb7 }, + { 0x1eb8, 0x1eb9 }, { 0x1eba, 0x1ebb }, { 0x1ebc, 0x1ebd }, { 0x1ebe, 0x1ebf }, { 0x1ec0, 0x1ec1 }, { 0x1ec2, 0x1ec3 }, { 0x1ec4, 0x1ec5 }, { 0x1ec6, 0x1ec7 }, + { 0x1ec8, 0x1ec9 }, { 0x1eca, 0x1ecb }, { 0x1ecc, 0x1ecd }, { 0x1ece, 0x1ecf }, { 0x1ed0, 0x1ed1 }, { 0x1ed2, 0x1ed3 }, { 0x1ed4, 0x1ed5 }, { 0x1ed6, 0x1ed7 }, + { 0x1ed8, 0x1ed9 }, { 0x1eda, 0x1edb }, { 0x1edc, 0x1edd }, { 0x1ede, 0x1edf }, { 0x1ee0, 0x1ee1 }, { 0x1ee2, 0x1ee3 }, { 0x1ee4, 0x1ee5 }, { 0x1ee6, 0x1ee7 }, + { 0x1ee8, 0x1ee9 }, { 0x1eea, 0x1eeb }, { 0x1eec, 0x1eed }, { 0x1eee, 0x1eef }, { 0x1ef0, 0x1ef1 }, { 0x1ef2, 0x1ef3 }, { 0x1ef4, 0x1ef5 }, { 0x1ef6, 0x1ef7 }, + { 0x1ef8, 0x1ef9 }, { 0x1f59, 0x1f51 }, { 0x1f5b, 0x1f53 }, { 0x1f5d, 0x1f55 }, { 0x1f5f, 0x1f57 }, { 0x1fb8, 0x1fb0 }, { 0x1fb9, 0x1fb1 }, { 0x1fba, 0x1f70 }, + { 0x1fbb, 0x1f71 }, { 0x1fbe, 0x03b9 }, { 0x1fd8, 0x1fd0 }, { 0x1fd9, 0x1fd1 }, { 0x1fda, 0x1f76 }, { 0x1fdb, 0x1f77 }, { 0x1fe8, 0x1fe0 }, { 0x1fe9, 0x1fe1 }, + { 0x1fea, 0x1f7a }, { 0x1feb, 0x1f7b }, { 0x1fec, 0x1fe5 }, { 0x1ff8, 0x1f78 }, { 0x1ff9, 0x1f79 }, { 0x1ffa, 0x1f7c }, { 0x1ffb, 0x1f7d }, { 0x2126, 0x03c9 }, + { 0x212a, 0x006b }, { 0x212b, 0x00e5 }, + }; + + /* This maps single codepoint to two codepoints. */ + static const struct { + int src_codepoint; + int dest_codepoint0; + int dest_codepoint1; + } double_map[] = { + { 0x00df, 0x0073, 0x0073 }, { 0x0130, 0x0069, 0x0307 }, { 0x0149, 0x02bc, 0x006e }, { 0x01f0, 0x006a, 0x030c }, { 0x0587, 0x0565, 0x0582 }, { 0x1e96, 0x0068, 0x0331 }, + { 0x1e97, 0x0074, 0x0308 }, { 0x1e98, 0x0077, 0x030a }, { 0x1e99, 0x0079, 0x030a }, { 0x1e9a, 0x0061, 0x02be }, { 0x1f50, 0x03c5, 0x0313 }, { 0x1f80, 0x1f00, 0x03b9 }, + { 0x1f81, 0x1f01, 0x03b9 }, { 0x1f82, 0x1f02, 0x03b9 }, { 0x1f83, 0x1f03, 0x03b9 }, { 0x1f84, 0x1f04, 0x03b9 }, { 0x1f85, 0x1f05, 0x03b9 }, { 0x1f86, 0x1f06, 0x03b9 }, + { 0x1f87, 0x1f07, 0x03b9 }, { 0x1f88, 0x1f00, 0x03b9 }, { 0x1f89, 0x1f01, 0x03b9 }, { 0x1f8a, 0x1f02, 0x03b9 }, { 0x1f8b, 0x1f03, 0x03b9 }, { 0x1f8c, 0x1f04, 0x03b9 }, + { 0x1f8d, 0x1f05, 0x03b9 }, { 0x1f8e, 0x1f06, 0x03b9 }, { 0x1f8f, 0x1f07, 0x03b9 }, { 0x1f90, 0x1f20, 0x03b9 }, { 0x1f91, 0x1f21, 0x03b9 }, { 0x1f92, 0x1f22, 0x03b9 }, + { 0x1f93, 0x1f23, 0x03b9 }, { 0x1f94, 0x1f24, 0x03b9 }, { 0x1f95, 0x1f25, 0x03b9 }, { 0x1f96, 0x1f26, 0x03b9 }, { 0x1f97, 0x1f27, 0x03b9 }, { 0x1f98, 0x1f20, 0x03b9 }, + { 0x1f99, 0x1f21, 0x03b9 }, { 0x1f9a, 0x1f22, 0x03b9 }, { 0x1f9b, 0x1f23, 0x03b9 }, { 0x1f9c, 0x1f24, 0x03b9 }, { 0x1f9d, 0x1f25, 0x03b9 }, { 0x1f9e, 0x1f26, 0x03b9 }, + { 0x1f9f, 0x1f27, 0x03b9 }, { 0x1fa0, 0x1f60, 0x03b9 }, { 0x1fa1, 0x1f61, 0x03b9 }, { 0x1fa2, 0x1f62, 0x03b9 }, { 0x1fa3, 0x1f63, 0x03b9 }, { 0x1fa4, 0x1f64, 0x03b9 }, + { 0x1fa5, 0x1f65, 0x03b9 }, { 0x1fa6, 0x1f66, 0x03b9 }, { 0x1fa7, 0x1f67, 0x03b9 }, { 0x1fa8, 0x1f60, 0x03b9 }, { 0x1fa9, 0x1f61, 0x03b9 }, { 0x1faa, 0x1f62, 0x03b9 }, + { 0x1fab, 0x1f63, 0x03b9 }, { 0x1fac, 0x1f64, 0x03b9 }, { 0x1fad, 0x1f65, 0x03b9 }, { 0x1fae, 0x1f66, 0x03b9 }, { 0x1faf, 0x1f67, 0x03b9 }, { 0x1fb2, 0x1f70, 0x03b9 }, + { 0x1fb3, 0x03b1, 0x03b9 }, { 0x1fb4, 0x03ac, 0x03b9 }, { 0x1fb6, 0x03b1, 0x0342 }, { 0x1fbc, 0x03b1, 0x03b9 }, { 0x1fc2, 0x1f74, 0x03b9 }, { 0x1fc3, 0x03b7, 0x03b9 }, + { 0x1fc4, 0x03ae, 0x03b9 }, { 0x1fc6, 0x03b7, 0x0342 }, { 0x1fcc, 0x03b7, 0x03b9 }, { 0x1fd6, 0x03b9, 0x0342 }, { 0x1fe4, 0x03c1, 0x0313 }, { 0x1fe6, 0x03c5, 0x0342 }, + { 0x1ff2, 0x1f7c, 0x03b9 }, { 0x1ff3, 0x03c9, 0x03b9 }, { 0x1ff4, 0x03ce, 0x03b9 }, { 0x1ff6, 0x03c9, 0x0342 }, { 0x1ffc, 0x03c9, 0x03b9 }, { 0xfb00, 0x0066, 0x0066 }, + { 0xfb01, 0x0066, 0x0069 }, { 0xfb02, 0x0066, 0x006c }, { 0xfb05, 0x0073, 0x0074 }, { 0xfb06, 0x0073, 0x0074 }, { 0xfb13, 0x0574, 0x0576 }, { 0xfb14, 0x0574, 0x0565 }, + { 0xfb15, 0x0574, 0x056b }, { 0xfb16, 0x057e, 0x0576 }, { 0xfb17, 0x0574, 0x056d } + }; + + /* This maps single codepoint to three codepoints. */ + static const struct { + int src_codepoint; + int dest_codepoint0; + int dest_codepoint1; + int dest_codepoint2; + } triple_map[] = { + { 0x0390, 0x03b9, 0x0308, 0x0301 }, { 0x03b0, 0x03c5, 0x0308, 0x0301 }, { 0x1f52, 0x03c5, 0x0313, 0x0300 }, { 0x1f54, 0x03c5, 0x0313, 0x0301 }, + { 0x1f56, 0x03c5, 0x0313, 0x0342 }, { 0x1fb7, 0x03b1, 0x0342, 0x03b9 }, { 0x1fc7, 0x03b7, 0x0342, 0x03b9 }, { 0x1fd2, 0x03b9, 0x0308, 0x0300 }, + { 0x1fd3, 0x03b9, 0x0308, 0x0301 }, { 0x1fd7, 0x03b9, 0x0308, 0x0342 }, { 0x1fe2, 0x03c5, 0x0308, 0x0300 }, { 0x1fe3, 0x03c5, 0x0308, 0x0301 }, + { 0x1fe7, 0x03c5, 0x0308, 0x0342 }, { 0x1ff7, 0x03c9, 0x0342, 0x03b9 }, { 0xfb03, 0x0066, 0x0066, 0x0069 }, { 0xfb04, 0x0066, 0x0066, 0x006c } + }; + + int i; + + /* Fast path for ASCII characters. */ + if(codepoint <= 0x7f) { + info->codepoints[0] = codepoint; + if(ISUPPER_(codepoint)) + info->codepoints[0] += 'a' - 'A'; + info->n_codepoints = 1; + return; + } + + for(i = 0; i < SIZEOF_ARRAY(range_map); i++) { + if(range_map[i].min_codepoint <= codepoint && codepoint <= range_map[i].max_codepoint) { + info->codepoints[0] = codepoint + range_map[i].offset; + info->n_codepoints = 1; + return; + } + } + + for(i = 0; i < SIZEOF_ARRAY(single_map); i++) { + if(codepoint == single_map[i].src_codepoint) { + info->codepoints[0] = single_map[i].dest_codepoint; + info->n_codepoints = 1; + return; + } + } + + for(i = 0; i < SIZEOF_ARRAY(double_map); i++) { + if(codepoint == double_map[i].src_codepoint) { + info->codepoints[0] = double_map[i].dest_codepoint0; + info->codepoints[1] = double_map[i].dest_codepoint1; + info->n_codepoints = 2; + return; + } + } + + for(i = 0; i < SIZEOF_ARRAY(triple_map); i++) { + if(codepoint == triple_map[i].src_codepoint) { + info->codepoints[0] = triple_map[i].dest_codepoint0; + info->codepoints[1] = triple_map[i].dest_codepoint1; + info->codepoints[2] = triple_map[i].dest_codepoint2; + info->n_codepoints = 3; + return; + } + } + + info->codepoints[0] = codepoint; + info->n_codepoints = 1; + } +#endif + + +#if defined MD4C_USE_UTF16 + #define IS_UTF16_SURROGATE_HI(word) (((WORD)(word) & 0xfc00) == 0xd800) + #define IS_UTF16_SURROGATE_LO(word) (((WORD)(word) & 0xfc00) == 0xdc00) + #define UTF16_DECODE_SURROGATE(hi, lo) (0x10000 + ((((unsigned)(hi) & 0x3ff) << 10) | (((unsigned)(lo) & 0x3ff) << 0))) + + static int + md_decode_utf16le__(const CHAR* str, SZ str_size, SZ* p_size) + { + if(IS_UTF16_SURROGATE_HI(str[0])) { + if(1 < str_size && IS_UTF16_SURROGATE_LO(str[1])) { + if(p_size != NULL) + *p_size = 2; + return UTF16_DECODE_SURROGATE(str[0], str[1]); + } + } + + if(p_size != NULL) + *p_size = 1; + return str[0]; + } + + static int + md_decode_utf16le_before__(MD_CTX* ctx, OFF off) + { + if(off > 2 && IS_UTF16_SURROGATE_HI(CH(off-2)) && IS_UTF16_SURROGATE_LO(CH(off-1))) + return UTF16_DECODE_SURROGATE(CH(off-2), CH(off-1)); + + return CH(off); + } + + /* No whitespace uses surrogates, so no decoding needed here. */ + #define ISUNICODEWHITESPACE_(codepoint) md_is_unicode_whitespace__(codepoint) + #define ISUNICODEWHITESPACE(off) md_is_unicode_whitespace__(CH(off)) + #define ISUNICODEWHITESPACEBEFORE(off) md_is_unicode_whitespace__(CH((off)-1)) + + #define ISUNICODEPUNCT(off) md_is_unicode_punct__(md_decode_utf16le__(STR(off), ctx->size - (off), NULL)) + #define ISUNICODEPUNCTBEFORE(off) md_is_unicode_punct__(md_decode_utf16le_before__(ctx, off)) + + static inline int + md_decode_unicode(const CHAR* str, OFF off, SZ str_size, SZ* p_char_size) + { + return md_decode_utf16le__(str+off, str_size-off, p_char_size); + } +#elif defined MD4C_USE_UTF8 + #define IS_UTF8_LEAD1(byte) ((unsigned char)(byte) <= 0x7f) + #define IS_UTF8_LEAD2(byte) (((unsigned char)(byte) & 0xe0) == 0xc0) + #define IS_UTF8_LEAD3(byte) (((unsigned char)(byte) & 0xf0) == 0xe0) + #define IS_UTF8_LEAD4(byte) (((unsigned char)(byte) & 0xf8) == 0xf0) + #define IS_UTF8_TAIL(byte) (((unsigned char)(byte) & 0xc0) == 0x80) + + static int + md_decode_utf8__(const CHAR* str, SZ str_size, SZ* p_size) + { + if(!IS_UTF8_LEAD1(str[0])) { + if(IS_UTF8_LEAD2(str[0])) { + if(1 < str_size && IS_UTF8_TAIL(str[1])) { + if(p_size != NULL) + *p_size = 2; + + return (((unsigned int)str[0] & 0x1f) << 6) | + (((unsigned int)str[1] & 0x3f) << 0); + } + } else if(IS_UTF8_LEAD3(str[0])) { + if(2 < str_size && IS_UTF8_TAIL(str[1]) && IS_UTF8_TAIL(str[2])) { + if(p_size != NULL) + *p_size = 3; + + return (((unsigned int)str[0] & 0x0f) << 12) | + (((unsigned int)str[1] & 0x3f) << 6) | + (((unsigned int)str[2] & 0x3f) << 0); + } + } else if(IS_UTF8_LEAD4(str[0])) { + if(3 < str_size && IS_UTF8_TAIL(str[1]) && IS_UTF8_TAIL(str[2]) && IS_UTF8_TAIL(str[3])) { + if(p_size != NULL) + *p_size = 4; + + return (((unsigned int)str[0] & 0x07) << 18) | + (((unsigned int)str[1] & 0x3f) << 12) | + (((unsigned int)str[2] & 0x3f) << 6) | + (((unsigned int)str[3] & 0x3f) << 0); + } + } + } + + if(p_size != NULL) + *p_size = 1; + return str[0]; + } + + static int + md_decode_utf8_before__(MD_CTX* ctx, OFF off) + { + if(!IS_UTF8_LEAD1(CH(off-1))) { + if(off > 1 && IS_UTF8_LEAD2(CH(off-2)) && IS_UTF8_TAIL(CH(off-1))) + return (((unsigned int)CH(off-2) & 0x1f) << 6) | + (((unsigned int)CH(off-1) & 0x3f) << 0); + + if(off > 2 && IS_UTF8_LEAD3(CH(off-3)) && IS_UTF8_TAIL(CH(off-2)) && IS_UTF8_TAIL(CH(off-1))) + return (((unsigned int)CH(off-3) & 0x0f) << 12) | + (((unsigned int)CH(off-2) & 0x3f) << 6) | + (((unsigned int)CH(off-1) & 0x3f) << 0); + + if(off > 3 && IS_UTF8_LEAD4(CH(off-4)) && IS_UTF8_TAIL(CH(off-3)) && IS_UTF8_TAIL(CH(off-2)) && IS_UTF8_TAIL(CH(off-1))) + return (((unsigned int)CH(off-4) & 0x07) << 18) | + (((unsigned int)CH(off-3) & 0x3f) << 12) | + (((unsigned int)CH(off-2) & 0x3f) << 6) | + (((unsigned int)CH(off-1) & 0x3f) << 0); + } + + return CH(off-1); + } + + #define ISUNICODEWHITESPACE_(codepoint) md_is_unicode_whitespace__(codepoint) + #define ISUNICODEWHITESPACE(off) md_is_unicode_whitespace__(md_decode_utf8__(STR(off), ctx->size - (off), NULL)) + #define ISUNICODEWHITESPACEBEFORE(off) md_is_unicode_whitespace__(md_decode_utf8_before__(ctx, off)) + + #define ISUNICODEPUNCT(off) md_is_unicode_punct__(md_decode_utf8__(STR(off), ctx->size - (off), NULL)) + #define ISUNICODEPUNCTBEFORE(off) md_is_unicode_punct__(md_decode_utf8_before__(ctx, off)) + + static inline int + md_decode_unicode(const CHAR* str, OFF off, SZ str_size, SZ* p_char_size) + { + return md_decode_utf8__(str+off, str_size-off, p_char_size); + } +#else + #define ISUNICODEWHITESPACE_(codepoint) ISWHITESPACE_(codepoint) + #define ISUNICODEWHITESPACE(off) ISWHITESPACE(off) + #define ISUNICODEWHITESPACEBEFORE(off) ISWHITESPACE((off)-1) + + #define ISUNICODEPUNCT(off) ISPUNCT(off) + #define ISUNICODEPUNCTBEFORE(off) ISPUNCT((off)-1) + + static inline void + md_get_unicode_fold_info(int codepoint, MD_UNICODE_FOLD_INFO* info) + { + info->codepoints[0] = codepoint; + if(ISUPPER_(codepoint)) + info->codepoints[0] += 'a' - 'A'; + info->n_codepoints = 1; + } + + static inline int + md_decode_unicode(const CHAR* str, OFF off, SZ str_size, SZ* p_size) + { + *p_size = 1; + return str[off]; + } +#endif + + +/************************************* + *** Helper string manipulations *** + *************************************/ + +/* Fill buffer with copy of the string between 'beg' and 'end' but replace any + * line breaks with given replacement character. + * + * NOTE: Caller is responsible to make sure the buffer is large enough. + * (Given the output is always shorter then input, (end - beg) is good idea + * what the caller should allocate.) + */ +static void +md_merge_lines(MD_CTX* ctx, OFF beg, OFF end, const MD_LINE* lines, int n_lines, + CHAR line_break_replacement_char, CHAR* buffer, SZ* p_size) +{ + CHAR* ptr = buffer; + int line_index = 0; + OFF off = beg; + + while(1) { + const MD_LINE* line = &lines[line_index]; + OFF line_end = line->end; + if(end < line_end) + line_end = end; + + while(off < line_end) { + *ptr = CH(off); + ptr++; + off++; + } + + if(off >= end) { + *p_size = ptr - buffer; + return; + } + + *ptr = line_break_replacement_char; + ptr++; + + line_index++; + off = lines[line_index].beg; + } +} + +/* Wrapper of md_merge_lines() which allocates new buffer for the output string. + */ +static int +md_merge_lines_alloc(MD_CTX* ctx, OFF beg, OFF end, const MD_LINE* lines, int n_lines, + CHAR line_break_replacement_char, CHAR** p_str, SZ* p_size) +{ + CHAR* buffer; + + buffer = (CHAR*) malloc(sizeof(CHAR) * (end - beg)); + if(buffer == NULL) { + MD_LOG("malloc() failed."); + return -1; + } + + md_merge_lines(ctx, beg, end, lines, n_lines, + line_break_replacement_char, buffer, p_size); + + *p_str = buffer; + return 0; +} + +static OFF +md_skip_unicode_whitespace(const CHAR* label, OFF off, SZ size) +{ + SZ char_size; + int codepoint; + + while(off < size) { + codepoint = md_decode_unicode(label, off, size, &char_size); + if(!ISUNICODEWHITESPACE_(codepoint) && !ISNEWLINE_(label[off])) + break; + off += char_size; + } + + return off; +} + + +/****************************** + *** Recognizing raw HTML *** + ******************************/ + +/* md_is_html_tag() may be called when processing inlines (inline raw HTML) + * or when breaking document to blocks (checking for start of HTML block type 7). + * + * When breaking document to blocks, we do not yet know line boundaries, but + * in that case the whole tag has to live on a single line. We distinguish this + * by n_lines == 0. + */ +static int +md_is_html_tag(MD_CTX* ctx, const MD_LINE* lines, int n_lines, OFF beg, OFF max_end, OFF* p_end) +{ + int attr_state; + OFF off = beg; + OFF line_end = (n_lines > 0) ? lines[0].end : ctx->size; + int i = 0; + + MD_ASSERT(CH(beg) == _T('<')); + + if(off + 1 >= line_end) + return FALSE; + off++; + + /* For parsing attributes, we need a little state automaton below. + * State -1: no attributes are allowed. + * State 0: attribute could follow after some whitespace. + * State 1: after a whitespace (attribute name may follow). + * State 2: after attribute name ('=' MAY follow). + * State 3: after '=' (value specification MUST follow). + * State 41: in middle of unquoted attribute value. + * State 42: in middle of single-quoted attribute value. + * State 43: in middle of double-quoted attribute value. + */ + attr_state = 0; + + if(CH(off) == _T('/')) { + /* Closer tag "". No attributes may be present. */ + attr_state = -1; + off++; + } + + /* Tag name */ + if(off >= line_end || !ISALPHA(off)) + return FALSE; + off++; + while(off < line_end && (ISALNUM(off) || CH(off) == _T('-'))) + off++; + + /* (Optional) attributes (if not closer), (optional) '/' (if not closer) + * and final '>'. */ + while(1) { + while(off < line_end && !ISNEWLINE(off)) { + if(attr_state > 40) { + if(attr_state == 41 && (ISBLANK(off) || ISANYOF(off, _T("\"'=<>`")))) { + attr_state = 0; + off--; /* Put the char back for re-inspection in the new state. */ + } else if(attr_state == 42 && CH(off) == _T('\'')) { + attr_state = 0; + } else if(attr_state == 43 && CH(off) == _T('"')) { + attr_state = 0; + } + off++; + } else if(ISWHITESPACE(off)) { + if(attr_state == 0) + attr_state = 1; + off++; + } else if(attr_state <= 2 && CH(off) == _T('>')) { + /* End. */ + goto done; + } else if(attr_state <= 2 && CH(off) == _T('/') && off+1 < line_end && CH(off+1) == _T('>')) { + /* End with digraph '/>' */ + off++; + goto done; + } else if((attr_state == 1 || attr_state == 2) && (ISALPHA(off) || CH(off) == _T('_') || CH(off) == _T(':'))) { + off++; + /* Attribute name */ + while(off < line_end && (ISALNUM(off) || ISANYOF(off, _T("_.:-")))) + off++; + attr_state = 2; + } else if(attr_state == 2 && CH(off) == _T('=')) { + /* Attribute assignment sign */ + off++; + attr_state = 3; + } else if(attr_state == 3) { + /* Expecting start of attribute value. */ + if(CH(off) == _T('"')) + attr_state = 43; + else if(CH(off) == _T('\'')) + attr_state = 42; + else if(!ISANYOF(off, _T("\"'=<>`")) && !ISNEWLINE(off)) + attr_state = 41; + else + return FALSE; + off++; + } else { + /* Anything unexpected. */ + return FALSE; + } + } + + /* We have to be on a single line. See definition of start condition + * of HTML block, type 7. */ + if(n_lines == 0) + return FALSE; + + i++; + if(i >= n_lines) + return FALSE; + + off = lines[i].beg; + line_end = lines[i].end; + + if(attr_state == 0 || attr_state == 41) + attr_state = 1; + + if(off >= max_end) + return FALSE; + } + +done: + if(off >= max_end) + return FALSE; + + *p_end = off+1; + return TRUE; +} + +static int +md_is_html_comment(MD_CTX* ctx, const MD_LINE* lines, int n_lines, OFF beg, OFF max_end, OFF* p_end) +{ + OFF off = beg; + int i = 0; + + MD_ASSERT(CH(beg) == _T('<')); + + if(off + 4 >= lines[0].end) + return FALSE; + if(CH(off+1) != _T('!') || CH(off+2) != _T('-') || CH(off+3) != _T('-')) + return FALSE; + off += 4; + + /* ">" and "->" must follow the opening. */ + if(off < lines[0].end && CH(off) == _T('>')) + return FALSE; + if(off+1 < lines[0].end && CH(off) == _T('-') && CH(off+1) == _T('>')) + return FALSE; + + while(1) { + while(off + 2 < lines[i].end) { + if(CH(off) == _T('-') && CH(off+1) == _T('-')) { + if(CH(off+2) == _T('>')) { + /* Success. */ + off += 2; + goto done; + } else { + /* "--" is prohibited inside the comment. */ + return FALSE; + } + } + + off++; + } + + i++; + if(i >= n_lines) + return FALSE; + + off = lines[i].beg; + + if(off >= max_end) + return FALSE; + } + +done: + if(off >= max_end) + return FALSE; + + *p_end = off+1; + return TRUE; +} + +static int +md_is_html_processing_instruction(MD_CTX* ctx, const MD_LINE* lines, int n_lines, OFF beg, OFF max_end, OFF* p_end) +{ + OFF off = beg; + int i = 0; + + MD_ASSERT(CH(beg) == _T('<')); + + if(off + 2 >= lines[0].end) + return FALSE; + if(CH(off+1) != _T('?')) + return FALSE; + off += 2; + + while(1) { + while(off + 1 < lines[i].end) { + if(CH(off) == _T('?') && CH(off+1) == _T('>')) { + /* Success. */ + off++; + goto done; + } + + off++; + } + + i++; + if(i >= n_lines) + return FALSE; + + off = lines[i].beg; + if(off >= max_end) + return FALSE; + } + +done: + if(off >= max_end) + return FALSE; + + *p_end = off+1; + return TRUE; +} + +static int +md_is_html_declaration(MD_CTX* ctx, const MD_LINE* lines, int n_lines, OFF beg, OFF max_end, OFF* p_end) +{ + OFF off = beg; + int i = 0; + + MD_ASSERT(CH(beg) == _T('<')); + + if(off + 2 >= lines[0].end) + return FALSE; + if(CH(off+1) != _T('!')) + return FALSE; + off += 2; + + /* Declaration name. */ + if(off >= lines[0].end || !ISALPHA(off)) + return FALSE; + off++; + while(off < lines[0].end && ISALPHA(off)) + off++; + if(off < lines[0].end && !ISWHITESPACE(off)) + return FALSE; + + while(1) { + while(off < lines[i].end) { + if(CH(off) == _T('>')) { + /* Success. */ + goto done; + } + + off++; + } + + i++; + if(i >= n_lines) + return FALSE; + + off = lines[i].beg; + if(off >= max_end) + return FALSE; + } + +done: + if(off >= max_end) + return FALSE; + + *p_end = off+1; + return TRUE; +} + +static int +md_is_html_cdata(MD_CTX* ctx, const MD_LINE* lines, int n_lines, OFF beg, OFF max_end, OFF* p_end) +{ + static const CHAR open_str[] = _T("= lines[0].end) + return FALSE; + if(memcmp(STR(off), open_str, open_size) != 0) + return FALSE; + off += open_size; + + while(1) { + while(off + 2 < lines[i].end) { + if(CH(off) == _T(']') && CH(off+1) == _T(']') && CH(off+2) == _T('>')) { + /* Success. */ + off += 2; + goto done; + } + + off++; + } + + i++; + if(i >= n_lines) + return FALSE; + + off = lines[i].beg; + if(off >= max_end) + return FALSE; + } + +done: + if(off >= max_end) + return FALSE; + + *p_end = off+1; + return TRUE; +} + +static int +md_is_html_any(MD_CTX* ctx, const MD_LINE* lines, int n_lines, OFF beg, OFF max_end, OFF* p_end) +{ + if(md_is_html_tag(ctx, lines, n_lines, beg, max_end, p_end) == TRUE) + return TRUE; + if(md_is_html_comment(ctx, lines, n_lines, beg, max_end, p_end) == TRUE) + return TRUE; + if(md_is_html_processing_instruction(ctx, lines, n_lines, beg, max_end, p_end) == TRUE) + return TRUE; + if(md_is_html_declaration(ctx, lines, n_lines, beg, max_end, p_end) == TRUE) + return TRUE; + if(md_is_html_cdata(ctx, lines, n_lines, beg, max_end, p_end) == TRUE) + return TRUE; + + return FALSE; +} + + +/**************************** + *** Recognizing Entity *** + ****************************/ + +static int +md_is_hex_entity_contents(MD_CTX* ctx, const CHAR* text, OFF beg, OFF max_end, OFF* p_end) +{ + OFF off = beg; + + while(off < max_end && ISXDIGIT_(text[off]) && off - beg <= 8) + off++; + + if(1 <= off - beg && off - beg <= 8) { + *p_end = off; + return TRUE; + } else { + return FALSE; + } +} + +static int +md_is_dec_entity_contents(MD_CTX* ctx, const CHAR* text, OFF beg, OFF max_end, OFF* p_end) +{ + OFF off = beg; + + while(off < max_end && ISDIGIT_(text[off]) && off - beg <= 8) + off++; + + if(1 <= off - beg && off - beg <= 8) { + *p_end = off; + return TRUE; + } else { + return FALSE; + } +} + +static int +md_is_named_entity_contents(MD_CTX* ctx, const CHAR* text, OFF beg, OFF max_end, OFF* p_end) +{ + OFF off = beg; + + if(off < max_end && ISALPHA_(text[off])) + off++; + else + return FALSE; + + while(off < max_end && ISALNUM_(text[off]) && off - beg <= 48) + off++; + + if(2 <= off - beg && off - beg <= 48) { + *p_end = off; + return TRUE; + } else { + return FALSE; + } +} + +static int +md_is_entity_str(MD_CTX* ctx, const CHAR* text, OFF beg, OFF max_end, OFF* p_end) +{ + int is_contents; + OFF off = beg; + + MD_ASSERT(text[off] == _T('&')); + off++; + + if(off+2 < max_end && text[off] == _T('#') && (text[off+1] == _T('x') || text[off+1] == _T('X'))) + is_contents = md_is_hex_entity_contents(ctx, text, off+2, max_end, &off); + else if(off+1 < max_end && text[off] == _T('#')) + is_contents = md_is_dec_entity_contents(ctx, text, off+1, max_end, &off); + else + is_contents = md_is_named_entity_contents(ctx, text, off, max_end, &off); + + if(is_contents && off < max_end && text[off] == _T(';')) { + *p_end = off+1; + return TRUE; + } else { + return FALSE; + } +} + +static inline int +md_is_entity(MD_CTX* ctx, OFF beg, OFF max_end, OFF* p_end) +{ + return md_is_entity_str(ctx, ctx->text, beg, max_end, p_end); +} + + +/****************************** + *** Attribute Management *** + ******************************/ + +typedef struct MD_ATTRIBUTE_BUILD_tag MD_ATTRIBUTE_BUILD; +struct MD_ATTRIBUTE_BUILD_tag { + CHAR* text; + MD_TEXTTYPE* substr_types; + OFF* substr_offsets; + int substr_count; + int substr_alloc; + MD_TEXTTYPE trivial_types[1]; + OFF trivial_offsets[2]; +}; + + +#define MD_BUILD_ATTR_NO_ESCAPES 0x0001 + +static int +md_build_attr_append_substr(MD_CTX* ctx, MD_ATTRIBUTE_BUILD* build, + MD_TEXTTYPE type, OFF off) +{ + if(build->substr_count >= build->substr_alloc) { + MD_TEXTTYPE* new_substr_types; + OFF* new_substr_offsets; + + build->substr_alloc = (build->substr_alloc == 0 ? 8 : build->substr_alloc * 2); + + new_substr_types = (MD_TEXTTYPE*) realloc(build->substr_types, + build->substr_alloc * sizeof(MD_TEXTTYPE)); + if(new_substr_types == NULL) { + MD_LOG("realloc() failed."); + return -1; + } + /* Note +1 to reserve space for final offset (== raw_size). */ + new_substr_offsets = (OFF*) realloc(build->substr_offsets, + (build->substr_alloc+1) * sizeof(OFF)); + if(new_substr_offsets == NULL) { + MD_LOG("realloc() failed."); + free(new_substr_types); + return -1; + } + + build->substr_types = new_substr_types; + build->substr_offsets = new_substr_offsets; + } + + build->substr_types[build->substr_count] = type; + build->substr_offsets[build->substr_count] = off; + build->substr_count++; + return 0; +} + +static void +md_free_attribute(MD_CTX* ctx, MD_ATTRIBUTE_BUILD* build) +{ + if(build->substr_alloc > 0) { + free(build->text); + free(build->substr_types); + free(build->substr_offsets); + } +} + +static int +md_build_attribute(MD_CTX* ctx, const CHAR* raw_text, SZ raw_size, + unsigned flags, MD_ATTRIBUTE* attr, MD_ATTRIBUTE_BUILD* build) +{ + OFF raw_off, off; + int is_trivial; + int ret = 0; + + memset(build, 0, sizeof(MD_ATTRIBUTE_BUILD)); + + /* If there is no backslash and no ampersand, build trivial attribute + * without any malloc(). */ + is_trivial = TRUE; + for(raw_off = 0; raw_off < raw_size; raw_off++) { + if(ISANYOF3_(raw_text[raw_off], _T('\\'), _T('&'), _T('\0'))) { + is_trivial = FALSE; + break; + } + } + + if(is_trivial) { + build->text = (CHAR*) (raw_size ? raw_text : NULL); + build->substr_types = build->trivial_types; + build->substr_offsets = build->trivial_offsets; + build->substr_count = 1; + build->substr_alloc = 0; + build->trivial_types[0] = MD_TEXT_NORMAL; + build->trivial_offsets[0] = 0; + build->trivial_offsets[1] = raw_size; + off = raw_size; + } else { + build->text = (CHAR*) malloc(raw_size * sizeof(CHAR)); + if(build->text == NULL) { + MD_LOG("malloc() failed."); + goto abort; + } + + raw_off = 0; + off = 0; + + while(raw_off < raw_size) { + if(raw_text[raw_off] == _T('\0')) { + MD_CHECK(md_build_attr_append_substr(ctx, build, MD_TEXT_NULLCHAR, off)); + memcpy(build->text + off, raw_text + raw_off, 1); + off++; + raw_off++; + continue; + } + + if(raw_text[raw_off] == _T('&')) { + OFF ent_end; + + if(md_is_entity_str(ctx, raw_text, raw_off, raw_size, &ent_end)) { + MD_CHECK(md_build_attr_append_substr(ctx, build, MD_TEXT_ENTITY, off)); + memcpy(build->text + off, raw_text + raw_off, ent_end - raw_off); + off += ent_end - raw_off; + raw_off = ent_end; + continue; + } + } + + if(build->substr_count == 0 || build->substr_types[build->substr_count-1] != MD_TEXT_NORMAL) + MD_CHECK(md_build_attr_append_substr(ctx, build, MD_TEXT_NORMAL, off)); + + if(!(flags & MD_BUILD_ATTR_NO_ESCAPES) && + raw_text[raw_off] == _T('\\') && raw_off+1 < raw_size && + (ISPUNCT_(raw_text[raw_off+1]) || ISNEWLINE_(raw_text[raw_off+1]))) + raw_off++; + + build->text[off++] = raw_text[raw_off++]; + } + build->substr_offsets[build->substr_count] = off; + } + + attr->text = build->text; + attr->size = off; + attr->substr_offsets = build->substr_offsets; + attr->substr_types = build->substr_types; + return 0; + +abort: + md_free_attribute(ctx, build); + return -1; +} + + +/********************************************* + *** Dictionary of Reference Definitions *** + *********************************************/ + +#define MD_FNV1A_BASE 2166136261 +#define MD_FNV1A_PRIME 16777619 + +static inline unsigned +md_fnv1a(unsigned base, const void* data, size_t n) +{ + const unsigned char* buf = (const unsigned char*) data; + unsigned hash = base; + size_t i; + + for(i = 0; i < n; i++) { + hash ^= buf[i]; + hash *= MD_FNV1A_PRIME; + } + + return hash; +} + + +struct MD_REF_DEF_tag { + CHAR* label; + CHAR* title; + unsigned hash; + SZ label_size : 24; + unsigned label_needs_free : 1; + unsigned title_needs_free : 1; + SZ title_size; + OFF dest_beg; + OFF dest_end; +}; + +/* Label equivalence is quite complicated with regards to whitespace and case + * folding. This complicates computing a hash of it as well as direct comparison + * of two labels. */ + +static unsigned +md_link_label_hash(const CHAR* label, SZ size) +{ + unsigned hash = MD_FNV1A_BASE; + OFF off; + int codepoint; + int is_whitespace = FALSE; + + off = md_skip_unicode_whitespace(label, 0, size); + while(off < size) { + SZ char_size; + + codepoint = md_decode_unicode(label, off, size, &char_size); + is_whitespace = ISUNICODEWHITESPACE_(codepoint) || ISNEWLINE_(label[off]); + + if(is_whitespace) { + codepoint = ' '; + hash = md_fnv1a(hash, &codepoint, 1 * sizeof(int)); + + off = md_skip_unicode_whitespace(label, off, size); + } else { + MD_UNICODE_FOLD_INFO fold_info; + + md_get_unicode_fold_info(codepoint, &fold_info); + hash = md_fnv1a(hash, fold_info.codepoints, fold_info.n_codepoints * sizeof(int)); + + off += char_size; + } + } + + if(!is_whitespace) { + codepoint = ' '; + hash = md_fnv1a(hash, &codepoint, 1 * sizeof(int)); + } + + return hash; +} + +static int +md_link_label_cmp(const CHAR* a_label, SZ a_size, const CHAR* b_label, SZ b_size) +{ + OFF a_off; + OFF b_off; + + /* The slow path, with Unicode case folding and Unicode whitespace collapsing. */ + a_off = md_skip_unicode_whitespace(a_label, 0, a_size); + b_off = md_skip_unicode_whitespace(b_label, 0, b_size); + while(a_off < a_size || b_off < b_size) { + int a_codepoint, b_codepoint; + SZ a_char_size, b_char_size; + int a_is_whitespace, b_is_whitespace; + + if(a_off < a_size) { + a_codepoint = md_decode_unicode(a_label, a_off, a_size, &a_char_size); + a_is_whitespace = ISUNICODEWHITESPACE_(a_codepoint) || ISNEWLINE_(a_label[a_off]); + } else { + /* Treat end of label as a whitespace. */ + a_codepoint = -1; + a_is_whitespace = TRUE; + } + + if(b_off < b_size) { + b_codepoint = md_decode_unicode(b_label, b_off, b_size, &b_char_size); + b_is_whitespace = ISUNICODEWHITESPACE_(b_codepoint) || ISNEWLINE_(b_label[b_off]); + } else { + /* Treat end of label as a whitespace. */ + b_codepoint = -1; + b_is_whitespace = TRUE; + } + + if(a_is_whitespace || b_is_whitespace) { + if(!a_is_whitespace || !b_is_whitespace) + return (a_is_whitespace ? -1 : +1); + + a_off = md_skip_unicode_whitespace(a_label, a_off, a_size); + b_off = md_skip_unicode_whitespace(b_label, b_off, b_size); + } else { + MD_UNICODE_FOLD_INFO a_fold_info, b_fold_info; + int cmp; + + md_get_unicode_fold_info(a_codepoint, &a_fold_info); + md_get_unicode_fold_info(b_codepoint, &b_fold_info); + + if(a_fold_info.n_codepoints != b_fold_info.n_codepoints) + return (a_fold_info.n_codepoints - b_fold_info.n_codepoints); + cmp = memcmp(a_fold_info.codepoints, b_fold_info.codepoints, a_fold_info.n_codepoints * sizeof(int)); + if(cmp != 0) + return cmp; + + a_off += a_char_size; + b_off += b_char_size; + } + } + + return 0; +} + +typedef struct MD_REF_DEF_LIST_tag MD_REF_DEF_LIST; +struct MD_REF_DEF_LIST_tag { + int n_ref_defs; + int alloc_ref_defs; + MD_REF_DEF* ref_defs[]; /* Valid items always point into ctx->ref_defs[] */ +}; + +static int +md_ref_def_cmp(const void* a, const void* b) +{ + const MD_REF_DEF* a_ref = *(const MD_REF_DEF**)a; + const MD_REF_DEF* b_ref = *(const MD_REF_DEF**)b; + + if(a_ref->hash < b_ref->hash) + return -1; + else if(a_ref->hash > b_ref->hash) + return +1; + else + return md_link_label_cmp(a_ref->label, a_ref->label_size, b_ref->label, b_ref->label_size); +} + +static int +md_ref_def_cmp_stable(const void* a, const void* b) +{ + int cmp; + + cmp = md_ref_def_cmp(a, b); + + /* Ensure stability of the sorting. */ + if(cmp == 0) { + const MD_REF_DEF* a_ref = *(const MD_REF_DEF**)a; + const MD_REF_DEF* b_ref = *(const MD_REF_DEF**)b; + + if(a_ref < b_ref) + cmp = -1; + else if(a_ref > b_ref) + cmp = +1; + else + cmp = 0; + } + + return cmp; +} + +static int +md_build_ref_def_hashtable(MD_CTX* ctx) +{ + int i, j; + + if(ctx->n_ref_defs == 0) + return 0; + + ctx->ref_def_hashtable_size = (ctx->n_ref_defs * 5) / 4; + ctx->ref_def_hashtable = malloc(ctx->ref_def_hashtable_size * sizeof(void*)); + if(ctx->ref_def_hashtable == NULL) { + MD_LOG("malloc() failed."); + goto abort; + } + memset(ctx->ref_def_hashtable, 0, ctx->ref_def_hashtable_size * sizeof(void*)); + + /* Each member of ctx->ref_def_hashtable[] can be: + * -- NULL, + * -- pointer to the MD_REF_DEF in ctx->ref_defs[], or + * -- pointer to a MD_REF_DEF_LIST, which holds multiple pointers to + * such MD_REF_DEFs. + */ + for(i = 0; i < ctx->n_ref_defs; i++) { + MD_REF_DEF* def = &ctx->ref_defs[i]; + void* bucket; + MD_REF_DEF_LIST* list; + + def->hash = md_link_label_hash(def->label, def->label_size); + bucket = ctx->ref_def_hashtable[def->hash % ctx->ref_def_hashtable_size]; + + if(bucket == NULL) { + ctx->ref_def_hashtable[def->hash % ctx->ref_def_hashtable_size] = def; + continue; + } + + if(ctx->ref_defs <= (MD_REF_DEF*) bucket && (MD_REF_DEF*) bucket < ctx->ref_defs + ctx->n_ref_defs) { + /* The bucket already contains one ref. def. Lets see whether it + * is the same label (ref. def. duplicate) or different one + * (hash conflict). */ + MD_REF_DEF* old_def = (MD_REF_DEF*) bucket; + + if(md_link_label_cmp(def->label, def->label_size, old_def->label, old_def->label_size) == 0) { + /* Ignore this ref. def. */ + continue; + } + + /* Make the bucket capable of holding more ref. defs. */ + list = (MD_REF_DEF_LIST*) malloc(sizeof(MD_REF_DEF_LIST) + 4 * sizeof(MD_REF_DEF)); + if(list == NULL) { + MD_LOG("malloc() failed."); + goto abort; + } + list->ref_defs[0] = old_def; + list->ref_defs[1] = def; + list->n_ref_defs = 2; + list->alloc_ref_defs = 4; + ctx->ref_def_hashtable[def->hash % ctx->ref_def_hashtable_size] = list; + continue; + } + + /* Append the def to the bucket list. */ + list = (MD_REF_DEF_LIST*) bucket; + if(list->n_ref_defs >= list->alloc_ref_defs) { + MD_REF_DEF_LIST* list_tmp = (MD_REF_DEF_LIST*) realloc(list, + sizeof(MD_REF_DEF_LIST) + 2 * list->alloc_ref_defs * sizeof(MD_REF_DEF)); + if(list_tmp == NULL) { + MD_LOG("realloc() failed."); + goto abort; + } + list = list_tmp; + list->alloc_ref_defs *= 2; + ctx->ref_def_hashtable[def->hash % ctx->ref_def_hashtable_size] = list; + } + + list->ref_defs[list->n_ref_defs] = def; + list->n_ref_defs++; + } + + /* Sort the complex buckets so we can use bsearch() with them. */ + for(i = 0; i < ctx->ref_def_hashtable_size; i++) { + void* bucket = ctx->ref_def_hashtable[i]; + MD_REF_DEF_LIST* list; + + if(bucket == NULL) + continue; + if(ctx->ref_defs <= (MD_REF_DEF*) bucket && (MD_REF_DEF*) bucket < ctx->ref_defs + ctx->n_ref_defs) + continue; + + list = (MD_REF_DEF_LIST*) bucket; + qsort(list->ref_defs, list->n_ref_defs, sizeof(MD_REF_DEF*), md_ref_def_cmp_stable); + + /* Disable duplicates. */ + for(j = 1; j < list->n_ref_defs; j++) { + if(md_ref_def_cmp(&list->ref_defs[j-1], &list->ref_defs[j]) == 0) + list->ref_defs[j] = list->ref_defs[j-1]; + } + } + + return 0; + +abort: + return -1; +} + +static void +md_free_ref_def_hashtable(MD_CTX* ctx) +{ + if(ctx->ref_def_hashtable != NULL) { + int i; + + for(i = 0; i < ctx->ref_def_hashtable_size; i++) { + void* bucket = ctx->ref_def_hashtable[i]; + if(bucket == NULL) + continue; + if(ctx->ref_defs <= (MD_REF_DEF*) bucket && (MD_REF_DEF*) bucket < ctx->ref_defs + ctx->n_ref_defs) + continue; + free(bucket); + } + + free(ctx->ref_def_hashtable); + } +} + +static const MD_REF_DEF* +md_lookup_ref_def(MD_CTX* ctx, const CHAR* label, SZ label_size) +{ + unsigned hash; + void* bucket; + + if(ctx->ref_def_hashtable_size == 0) + return NULL; + + hash = md_link_label_hash(label, label_size); + bucket = ctx->ref_def_hashtable[hash % ctx->ref_def_hashtable_size]; + + if(bucket == NULL) { + return NULL; + } else if(ctx->ref_defs <= (MD_REF_DEF*) bucket && (MD_REF_DEF*) bucket < ctx->ref_defs + ctx->n_ref_defs) { + const MD_REF_DEF* def = (MD_REF_DEF*) bucket; + + if(md_link_label_cmp(def->label, def->label_size, label, label_size) == 0) + return def; + else + return NULL; + } else { + MD_REF_DEF_LIST* list = (MD_REF_DEF_LIST*) bucket; + MD_REF_DEF key_buf; + const MD_REF_DEF* key = &key_buf; + const MD_REF_DEF** ret; + + key_buf.label = (CHAR*) label; + key_buf.label_size = label_size; + key_buf.hash = md_link_label_hash(key_buf.label, key_buf.label_size); + + ret = (const MD_REF_DEF**) bsearch(&key, list->ref_defs, + list->n_ref_defs, sizeof(MD_REF_DEF*), md_ref_def_cmp); + if(ret != NULL) + return *ret; + else + return NULL; + } +} + + +/*************************** + *** Recognizing Links *** + ***************************/ + +/* Note this code is partially shared between processing inlines and blocks + * as reference definitions and links share some helper parser functions. + */ + +typedef struct MD_LINK_ATTR_tag MD_LINK_ATTR; +struct MD_LINK_ATTR_tag { + OFF dest_beg; + OFF dest_end; + + CHAR* title; + SZ title_size; + int title_needs_free; +}; + + +static int +md_is_link_label(MD_CTX* ctx, const MD_LINE* lines, int n_lines, OFF beg, + OFF* p_end, int* p_beg_line_index, int* p_end_line_index, + OFF* p_contents_beg, OFF* p_contents_end) +{ + OFF off = beg; + OFF contents_beg = 0; + OFF contents_end = 0; + int line_index = 0; + int len = 0; + + if(CH(off) != _T('[')) + return FALSE; + off++; + + while(1) { + OFF line_end = lines[line_index].end; + + while(off < line_end) { + if(CH(off) == _T('\\') && off+1 < ctx->size && (ISPUNCT(off+1) || ISNEWLINE(off+1))) { + if(contents_end == 0) { + contents_beg = off; + *p_beg_line_index = line_index; + } + contents_end = off + 2; + off += 2; + } else if(CH(off) == _T('[')) { + return FALSE; + } else if(CH(off) == _T(']')) { + if(contents_beg < contents_end) { + /* Success. */ + *p_contents_beg = contents_beg; + *p_contents_end = contents_end; + *p_end = off+1; + *p_end_line_index = line_index; + return TRUE; + } else { + /* Link label must have some non-whitespace contents. */ + return FALSE; + } + } else { + int codepoint; + SZ char_size; + + codepoint = md_decode_unicode(ctx->text, off, ctx->size, &char_size); + if(!ISUNICODEWHITESPACE_(codepoint)) { + if(contents_end == 0) { + contents_beg = off; + *p_beg_line_index = line_index; + } + contents_end = off + char_size; + } + + off += char_size; + } + + len++; + if(len > 999) + return FALSE; + } + + line_index++; + len++; + if(line_index < n_lines) + off = lines[line_index].beg; + else + break; + } + + return FALSE; +} + +static int +md_is_link_destination_A(MD_CTX* ctx, OFF beg, OFF max_end, OFF* p_end, + OFF* p_contents_beg, OFF* p_contents_end) +{ + OFF off = beg; + + if(off >= max_end || CH(off) != _T('<')) + return FALSE; + off++; + + while(off < max_end) { + if(CH(off) == _T('\\') && off+1 < max_end && ISPUNCT(off+1)) { + off += 2; + continue; + } + + if(ISWHITESPACE(off) || CH(off) == _T('<')) + return FALSE; + + if(CH(off) == _T('>')) { + /* Success. */ + *p_contents_beg = beg+1; + *p_contents_end = off; + *p_end = off+1; + return TRUE; + } + + off++; + } + + return FALSE; +} + +static int +md_is_link_destination_B(MD_CTX* ctx, OFF beg, OFF max_end, OFF* p_end, + OFF* p_contents_beg, OFF* p_contents_end) +{ + OFF off = beg; + int parenthesis_level = 0; + + while(off < max_end) { + if(CH(off) == _T('\\') && off+1 < max_end && ISPUNCT(off+1)) { + off += 2; + continue; + } + + if(ISWHITESPACE(off) || ISCNTRL(off)) + break; + + /* Link destination may include balanced pairs of unescaped '(' ')'. + * Note we limit the maximal nesting level by 32 to protect us from + * https://github.com/jgm/cmark/issues/214 */ + if(CH(off) == _T('(')) { + parenthesis_level++; + if(parenthesis_level > 32) + return FALSE; + } else if(CH(off) == _T(')')) { + if(parenthesis_level == 0) + break; + parenthesis_level--; + } + + off++; + } + + if(parenthesis_level != 0 || off == beg) + return FALSE; + + /* Success. */ + *p_contents_beg = beg; + *p_contents_end = off; + *p_end = off; + return TRUE; +} + +static int +md_is_link_title(MD_CTX* ctx, const MD_LINE* lines, int n_lines, OFF beg, + OFF* p_end, int* p_beg_line_index, int* p_end_line_index, + OFF* p_contents_beg, OFF* p_contents_end) +{ + OFF off = beg; + CHAR closer_char; + int line_index = 0; + + /* Optional white space with up to one line break. */ + while(off < lines[line_index].end && ISWHITESPACE(off)) + off++; + if(off >= lines[line_index].end) { + line_index++; + if(line_index >= n_lines) + return FALSE; + off = lines[line_index].beg; + } + + *p_beg_line_index = line_index; + + /* First char determines how to detect end of it. */ + switch(CH(off)) { + case _T('"'): closer_char = _T('"'); break; + case _T('\''): closer_char = _T('\''); break; + case _T('('): closer_char = _T(')'); break; + default: return FALSE; + } + off++; + + *p_contents_beg = off; + + while(line_index < n_lines) { + OFF line_end = lines[line_index].end; + + while(off < line_end) { + if(CH(off) == _T('\\') && off+1 < ctx->size && (ISPUNCT(off+1) || ISNEWLINE(off+1))) { + off++; + } else if(CH(off) == closer_char) { + /* Success. */ + *p_contents_end = off; + *p_end = off+1; + *p_end_line_index = line_index; + return TRUE; + } + + off++; + } + + line_index++; + } + + return FALSE; +} + +/* Returns 0 if it is not a reference definition. + * + * Returns N > 0 if it is a reference definition. N then corresponds to the + * number of lines forming it). In this case the definition is stored for + * resolving any links referring to it. + * + * Returns -1 in case of an error (out of memory). + */ +static int +md_is_link_reference_definition_helper( + MD_CTX* ctx, const MD_LINE* lines, int n_lines, + int (*is_link_dest_fn)(MD_CTX*, OFF, OFF, OFF*, OFF*, OFF*)) +{ + OFF label_contents_beg; + OFF label_contents_end; + int label_contents_line_index = -1; + int label_is_multiline; + CHAR* label; + SZ label_size; + int label_needs_free = FALSE; + OFF dest_contents_beg; + OFF dest_contents_end; + OFF title_contents_beg; + OFF title_contents_end; + int title_contents_line_index; + int title_is_multiline; + OFF off; + int line_index = 0; + int tmp_line_index; + MD_REF_DEF* def; + int ret; + + /* Link label. */ + if(!md_is_link_label(ctx, lines, n_lines, lines[0].beg, + &off, &label_contents_line_index, &line_index, + &label_contents_beg, &label_contents_end)) + return FALSE; + label_is_multiline = (label_contents_line_index != line_index); + + /* Colon. */ + if(off >= lines[line_index].end || CH(off) != _T(':')) + return FALSE; + off++; + + /* Optional white space with up to one line break. */ + while(off < lines[line_index].end && ISWHITESPACE(off)) + off++; + if(off >= lines[line_index].end) { + line_index++; + if(line_index >= n_lines) + return FALSE; + off = lines[line_index].beg; + } + + /* Link destination. */ + if(!is_link_dest_fn(ctx, off, lines[line_index].end, + &off, &dest_contents_beg, &dest_contents_end)) + return FALSE; + + /* (Optional) title. Note we interpret it as an title only if nothing + * more follows on its last line. */ + if(md_is_link_title(ctx, lines + line_index, n_lines - line_index, off, + &off, &title_contents_line_index, &tmp_line_index, + &title_contents_beg, &title_contents_end) + && off >= lines[line_index + tmp_line_index].end) + { + title_is_multiline = (tmp_line_index != title_contents_line_index); + title_contents_line_index += line_index; + line_index += tmp_line_index; + } else { + /* Not a title. */ + title_is_multiline = FALSE; + title_contents_beg = off; + title_contents_end = off; + title_contents_line_index = 0; + } + + /* Nothing more can follow on the last line. */ + if(off < lines[line_index].end) + return FALSE; + + /* Construct label. */ + if(!label_is_multiline) { + label = (CHAR*) STR(label_contents_beg); + label_size = label_contents_end - label_contents_beg; + label_needs_free = FALSE; + } else { + MD_CHECK(md_merge_lines_alloc(ctx, label_contents_beg, label_contents_end, + lines + label_contents_line_index, n_lines - label_contents_line_index, + _T(' '), &label, &label_size)); + label_needs_free = TRUE; + } + + /* Store the reference definition. */ + if(ctx->n_ref_defs >= ctx->alloc_ref_defs) { + MD_REF_DEF* new_defs; + + ctx->alloc_ref_defs = (ctx->alloc_ref_defs > 0 ? ctx->alloc_ref_defs * 2 : 16); + new_defs = (MD_REF_DEF*) realloc(ctx->ref_defs, ctx->alloc_ref_defs * sizeof(MD_REF_DEF)); + if(new_defs == NULL) { + MD_LOG("realloc() failed."); + ret = -1; + goto abort; + } + + ctx->ref_defs = new_defs; + } + + def = &ctx->ref_defs[ctx->n_ref_defs]; + memset(def, 0, sizeof(MD_REF_DEF)); + + def->label = label; + def->label_size = label_size; + def->label_needs_free = label_needs_free; + + def->dest_beg = dest_contents_beg; + def->dest_end = dest_contents_end; + + if(title_contents_beg >= title_contents_end) { + def->title = NULL; + def->title_size = 0; + } else if(!title_is_multiline) { + def->title = (CHAR*) STR(title_contents_beg); + def->title_size = title_contents_end - title_contents_beg; + } else { + MD_CHECK(md_merge_lines_alloc(ctx, title_contents_beg, title_contents_end, + lines + title_contents_line_index, n_lines - title_contents_line_index, + _T('\n'), &def->title, &def->title_size)); + def->title_needs_free = TRUE; + } + + /* Success. */ + ctx->n_ref_defs++; + return line_index + 1; + +abort: + /* Failure. */ + if(label_needs_free) + free(label); + return -1; +} + +static inline int +md_is_link_reference_definition(MD_CTX* ctx, const MD_LINE* lines, int n_lines) +{ + int ret; + ret = md_is_link_reference_definition_helper(ctx, lines, n_lines, md_is_link_destination_A); + if(ret == 0) + ret = md_is_link_reference_definition_helper(ctx, lines, n_lines, md_is_link_destination_B); + return ret; +} + +static int +md_is_link_reference(MD_CTX* ctx, const MD_LINE* lines, int n_lines, + OFF beg, OFF end, MD_LINK_ATTR* attr) +{ + const MD_REF_DEF* def; + const MD_LINE* beg_line; + const MD_LINE* end_line; + CHAR* label; + SZ label_size; + int ret; + + MD_ASSERT(CH(beg) == _T('[') || CH(beg) == _T('!')); + MD_ASSERT(CH(end-1) == _T(']')); + + beg += (CH(beg) == _T('!') ? 2 : 1); + end--; + + /* Find lines corresponding to the beg and end positions. */ + MD_ASSERT(lines[0].beg <= beg); + beg_line = lines; + while(beg >= beg_line->end) + beg_line++; + + MD_ASSERT(end <= lines[n_lines-1].end); + end_line = beg_line; + while(end >= end_line->end) + end_line++; + + if(beg_line != end_line) { + MD_CHECK(md_merge_lines_alloc(ctx, beg, end, beg_line, + n_lines - (beg_line - lines), _T(' '), &label, &label_size)); + } else { + label = (CHAR*) STR(beg); + label_size = end - beg; + } + + def = md_lookup_ref_def(ctx, label, label_size); + if(def != NULL) { + attr->dest_beg = def->dest_beg; + attr->dest_end = def->dest_end; + attr->title = def->title; + attr->title_size = def->title_size; + attr->title_needs_free = FALSE; + } + + if(beg_line != end_line) + free(label); + + ret = (def != NULL); + +abort: + return ret; +} + +static int +md_is_inline_link_spec_helper(MD_CTX* ctx, const MD_LINE* lines, int n_lines, + OFF beg, OFF* p_end, MD_LINK_ATTR* attr, + int (*is_link_dest_fn)(MD_CTX*, OFF, OFF, OFF*, OFF*, OFF*)) +{ + int line_index = 0; + int tmp_line_index; + OFF title_contents_beg; + OFF title_contents_end; + int title_contents_line_index; + int title_is_multiline; + OFF off = beg; + int ret = FALSE; + + while(off >= lines[line_index].end) + line_index++; + + MD_ASSERT(CH(off) == _T('(')); + off++; + + /* Optional white space with up to one line break. */ + while(off < lines[line_index].end && ISWHITESPACE(off)) + off++; + if(off >= lines[line_index].end && ISNEWLINE(off)) { + line_index++; + if(line_index >= n_lines) + return FALSE; + off = lines[line_index].beg; + } + + /* Link destination may be omitted, but only when not also having a title. */ + if(off < ctx->size && CH(off) == _T(')')) { + attr->dest_beg = off; + attr->dest_end = off; + attr->title = NULL; + attr->title_size = 0; + attr->title_needs_free = FALSE; + off++; + *p_end = off; + return TRUE; + } + + /* Link destination. */ + if(!is_link_dest_fn(ctx, off, lines[line_index].end, + &off, &attr->dest_beg, &attr->dest_end)) + return FALSE; + + /* (Optional) title. */ + if(md_is_link_title(ctx, lines + line_index, n_lines - line_index, off, + &off, &title_contents_line_index, &tmp_line_index, + &title_contents_beg, &title_contents_end)) + { + title_is_multiline = (tmp_line_index != title_contents_line_index); + title_contents_line_index += line_index; + line_index += tmp_line_index; + } else { + /* Not a title. */ + title_is_multiline = FALSE; + title_contents_beg = off; + title_contents_end = off; + title_contents_line_index = 0; + } + + /* Optional whitespace followed with final ')'. */ + while(off < lines[line_index].end && ISWHITESPACE(off)) + off++; + if(off >= lines[line_index].end && ISNEWLINE(off)) { + line_index++; + if(line_index >= n_lines) + return FALSE; + off = lines[line_index].beg; + } + if(CH(off) != _T(')')) + goto abort; + off++; + + if(title_contents_beg >= title_contents_end) { + attr->title = NULL; + attr->title_size = 0; + attr->title_needs_free = FALSE; + } else if(!title_is_multiline) { + attr->title = (CHAR*) STR(title_contents_beg); + attr->title_size = title_contents_end - title_contents_beg; + attr->title_needs_free = FALSE; + } else { + MD_CHECK(md_merge_lines_alloc(ctx, title_contents_beg, title_contents_end, + lines + title_contents_line_index, n_lines - title_contents_line_index, + _T('\n'), &attr->title, &attr->title_size)); + attr->title_needs_free = TRUE; + } + + *p_end = off; + ret = TRUE; + +abort: + return ret; +} + +static inline int +md_is_inline_link_spec(MD_CTX* ctx, const MD_LINE* lines, int n_lines, + OFF beg, OFF* p_end, MD_LINK_ATTR* attr) +{ + return md_is_inline_link_spec_helper(ctx, lines, n_lines, beg, p_end, attr, md_is_link_destination_A) || + md_is_inline_link_spec_helper(ctx, lines, n_lines, beg, p_end, attr, md_is_link_destination_B); +} + +static void +md_free_ref_defs(MD_CTX* ctx) +{ + int i; + + for(i = 0; i < ctx->n_ref_defs; i++) { + MD_REF_DEF* def = &ctx->ref_defs[i]; + + if(def->label_needs_free) + free(def->label); + if(def->title_needs_free) + free(def->title); + } + + free(ctx->ref_defs); +} + + +/****************************************** + *** Processing Inlines (a.k.a Spans) *** + ******************************************/ + +/* We process inlines in few phases: + * + * (1) We go through the block text and collect all significant characters + * which may start/end a span or some other significant position into + * ctx->marks[]. Core of this is what md_collect_marks() does. + * + * We also do some very brief preliminary context-less analysis, whether + * it might be opener or closer (e.g. of an emphasis span). + * + * This speeds the other steps as we do not need to re-iterate over all + * characters anymore. + * + * (2) We analyze each potential mark types, in order by their precedence. + * + * In each md_analyze_XXX() function, we re-iterate list of the marks, + * skipping already resolved regions (in preceding precedences) and try to + * resolve them. + * + * (2.1) For trivial marks, which are single (e.g. HTML entity), we just mark + * them as resolved. + * + * (2.2) For range-type marks, we analyze whether the mark could be closer + * and, if yes, whether there is some preceding opener it could satisfy. + * + * If not we check whether it could be really an opener and if yes, we + * remember it so subsequent closers may resolve it. + * + * (3) Finally, when all marks were analyzed, we render the block contents + * by calling MD_RENDERER::text() callback, interrupting by ::enter_span() + * or ::close_span() whenever we reach a resolved mark. + */ + + +/* The mark structure. + * + * '\\': Maybe escape sequence. + * '\0': NULL char. + * '*': Maybe (strong) emphasis start/end. + * '_': Maybe (strong) emphasis start/end. + * '~': Maybe strikethrough start/end (needs MD_FLAG_STRIKETHROUGH). + * '`': Maybe code span start/end. + * '&': Maybe start of entity. + * ';': Maybe end of entity. + * '<': Maybe start of raw HTML or autolink. + * '>': Maybe end of raw HTML or autolink. + * '[': Maybe start of link label or link text. + * '!': Equivalent of '[' for image. + * ']': Maybe end of link label or link text. + * '@': Maybe permissive e-mail auto-link (needs MD_FLAG_PERMISSIVEEMAILAUTOLINKS). + * ':': Maybe permissive URL auto-link (needs MD_FLAG_PERMISSIVEURLAUTOLINKS). + * '.': Maybe permissive WWW auto-link (needs MD_FLAG_PERMISSIVEWWWAUTOLINKS). + * 'D': Dummy mark, it reserves a space for splitting a previous mark + * (e.g. emphasis) or to make more space for storing some special data + * related to the preceding mark (e.g. link). + * + * Note that not all instances of these chars in the text imply creation of the + * structure. Only those which have (or may have, after we see more context) + * the special meaning. + * + * (Keep this struct as small as possible to fit as much of them into CPU + * cache line.) + */ +struct MD_MARK_tag { + OFF beg; + OFF end; + + /* For unresolved openers, 'prev' and 'next' form the chain of open openers + * of given type 'ch'. + * + * During resolving, we disconnect from the chain and point to the + * corresponding counterpart so opener points to its closer and vice versa. + */ + int prev; + int next; + CHAR ch; + unsigned char flags; +}; + +/* Mark flags (these apply to ALL mark types). */ +#define MD_MARK_POTENTIAL_OPENER 0x01 /* Maybe opener. */ +#define MD_MARK_POTENTIAL_CLOSER 0x02 /* Maybe closer. */ +#define MD_MARK_OPENER 0x04 /* Definitely opener. */ +#define MD_MARK_CLOSER 0x08 /* Definitely closer. */ +#define MD_MARK_RESOLVED 0x10 /* Resolved in any definite way. */ + +/* Mark flags specific for various mark types (so they can share bits). */ +#define MD_MARK_EMPH_INTRAWORD 0x20 /* Helper for the "rule of 3". */ +#define MD_MARK_EMPH_MODULO3_0 0x40 +#define MD_MARK_EMPH_MODULO3_1 0x80 +#define MD_MARK_EMPH_MODULO3_2 (0x40 | 0x80) +#define MD_MARK_EMPH_MODULO3_MASK (0x40 | 0x80) +#define MD_MARK_AUTOLINK 0x20 /* Distinguisher for '<', '>'. */ +#define MD_MARK_VALIDPERMISSIVEAUTOLINK 0x20 /* For permissive autolinks. */ + + +static MD_MARK* +md_push_mark(MD_CTX* ctx) +{ + if(ctx->n_marks >= ctx->alloc_marks) { + MD_MARK* new_marks; + + ctx->alloc_marks = (ctx->alloc_marks > 0 ? ctx->alloc_marks * 2 : 64); + new_marks = realloc(ctx->marks, ctx->alloc_marks * sizeof(MD_MARK)); + if(new_marks == NULL) { + MD_LOG("realloc() failed."); + return NULL; + } + + ctx->marks = new_marks; + } + + return &ctx->marks[ctx->n_marks++]; +} + +#define PUSH_MARK_() \ + do { \ + mark = md_push_mark(ctx); \ + if(mark == NULL) { \ + ret = -1; \ + goto abort; \ + } \ + } while(0) + +#define PUSH_MARK(ch_, beg_, end_, flags_) \ + do { \ + PUSH_MARK_(); \ + mark->beg = (beg_); \ + mark->end = (end_); \ + mark->prev = -1; \ + mark->next = -1; \ + mark->ch = (char)(ch_); \ + mark->flags = (flags_); \ + } while(0) + + +static void +md_mark_chain_append(MD_CTX* ctx, MD_MARKCHAIN* chain, int mark_index) +{ + if(chain->tail >= 0) + ctx->marks[chain->tail].next = mark_index; + else + chain->head = mark_index; + + ctx->marks[mark_index].prev = chain->tail; + chain->tail = mark_index; +} + +/* Sometimes, we need to store a pointer into the mark. It is quite rare + * so we do not bother to make MD_MARK use union, and it can only happen + * for dummy marks. */ +static inline void +md_mark_store_ptr(MD_CTX* ctx, int mark_index, void* ptr) +{ + MD_MARK* mark = &ctx->marks[mark_index]; + MD_ASSERT(mark->ch == 'D'); + + /* Check only members beg and end are misused for this. */ + MD_ASSERT(sizeof(void*) <= 2 * sizeof(OFF)); + memcpy(mark, &ptr, sizeof(void*)); +} + +static inline void* +md_mark_get_ptr(MD_CTX* ctx, int mark_index) +{ + void* ptr; + MD_MARK* mark = &ctx->marks[mark_index]; + MD_ASSERT(mark->ch == 'D'); + memcpy(&ptr, mark, sizeof(void*)); + return ptr; +} + +static void +md_resolve_range(MD_CTX* ctx, MD_MARKCHAIN* chain, int opener_index, int closer_index) +{ + MD_MARK* opener = &ctx->marks[opener_index]; + MD_MARK* closer = &ctx->marks[closer_index]; + + /* Remove opener from the list of openers. */ + if(chain != NULL) { + if(opener->prev >= 0) + ctx->marks[opener->prev].next = opener->next; + else + chain->head = opener->next; + + if(opener->next >= 0) + ctx->marks[opener->next].prev = opener->prev; + else + chain->tail = opener->prev; + } + + /* Interconnect opener and closer and mark both as resolved. */ + opener->next = closer_index; + opener->flags |= MD_MARK_OPENER | MD_MARK_RESOLVED; + closer->prev = opener_index; + closer->flags |= MD_MARK_CLOSER | MD_MARK_RESOLVED; +} + + +#define MD_ROLLBACK_ALL 0 +#define MD_ROLLBACK_CROSSING 1 + +/* In the range ctx->marks[opener_index] ... [closer_index], undo some or all + * resolvings accordingly to these rules: + * + * (1) All openers BEFORE the range corresponding to any closer inside the + * range are un-resolved and they are re-added to their respective chains + * of unresolved openers. This ensures we can reuse the opener for closers + * AFTER the range. + * + * (2) If 'how' is MD_ROLLBACK_ALL, then ALL resolved marks inside the range + * are discarded. + * + * (3) If 'how' is MD_ROLLBACK_CROSSING, only closers with openers handled + * in (1) are discarded. I.e. pairs of openers and closers which are both + * inside the range are retained as well as any unpaired marks. + */ +static void +md_rollback(MD_CTX* ctx, int opener_index, int closer_index, int how) +{ + int i; + int mark_index; + + /* Cut all unresolved openers at the mark index. */ + for(i = OPENERS_CHAIN_FIRST; i < OPENERS_CHAIN_LAST+1; i++) { + MD_MARKCHAIN* chain = &ctx->mark_chains[i]; + + while(chain->tail >= opener_index) + chain->tail = ctx->marks[chain->tail].prev; + + if(chain->tail >= 0) + ctx->marks[chain->tail].next = -1; + else + chain->head = -1; + } + + /* Go backwards so that un-resolved openers are re-added into their + * respective chains, in the right order. */ + mark_index = closer_index - 1; + while(mark_index > opener_index) { + MD_MARK* mark = &ctx->marks[mark_index]; + int mark_flags = mark->flags; + int discard_flag = (how == MD_ROLLBACK_ALL); + + if(mark->flags & MD_MARK_CLOSER) { + int mark_opener_index = mark->prev; + + /* Undo opener BEFORE the range. */ + if(mark_opener_index < opener_index) { + MD_MARK* mark_opener = &ctx->marks[mark_opener_index]; + MD_MARKCHAIN* chain; + + mark_opener->flags &= ~(MD_MARK_OPENER | MD_MARK_CLOSER | MD_MARK_RESOLVED); + + switch(mark_opener->ch) { + case '*': chain = &ASTERISK_OPENERS; break; + case '_': chain = &UNDERSCORE_OPENERS; break; + case '`': chain = &BACKTICK_OPENERS; break; + case '<': chain = &LOWERTHEN_OPENERS; break; + case '~': chain = &TILDE_OPENERS; break; + default: MD_UNREACHABLE(); break; + } + md_mark_chain_append(ctx, chain, mark_opener_index); + + discard_flag = 1; + } + } + + /* And reset our flags. */ + if(discard_flag) + mark->flags &= ~(MD_MARK_OPENER | MD_MARK_CLOSER | MD_MARK_RESOLVED); + + /* Jump as far as we can over unresolved or non-interesting marks. */ + switch(how) { + case MD_ROLLBACK_CROSSING: + if((mark_flags & MD_MARK_CLOSER) && mark->prev > opener_index) { + /* If we are closer with opener INSIDE the range, there may + * not be any other crosser inside the subrange. */ + mark_index = mark->prev; + break; + } + /* Pass through. */ + default: + mark_index--; + break; + } + } +} + +static void +md_build_mark_char_map(MD_CTX* ctx) +{ + memset(ctx->mark_char_map, 0, sizeof(ctx->mark_char_map)); + + ctx->mark_char_map['\\'] = 1; + ctx->mark_char_map['*'] = 1; + ctx->mark_char_map['_'] = 1; + ctx->mark_char_map['`'] = 1; + ctx->mark_char_map['&'] = 1; + ctx->mark_char_map[';'] = 1; + ctx->mark_char_map['<'] = 1; + ctx->mark_char_map['>'] = 1; + ctx->mark_char_map['['] = 1; + ctx->mark_char_map['!'] = 1; + ctx->mark_char_map[']'] = 1; + ctx->mark_char_map['\0'] = 1; + + if(ctx->parser.flags & MD_FLAG_STRIKETHROUGH) + ctx->mark_char_map['~'] = 1; + + if(ctx->parser.flags & MD_FLAG_PERMISSIVEEMAILAUTOLINKS) + ctx->mark_char_map['@'] = 1; + + if(ctx->parser.flags & MD_FLAG_PERMISSIVEURLAUTOLINKS) + ctx->mark_char_map[':'] = 1; + + if(ctx->parser.flags & MD_FLAG_PERMISSIVEWWWAUTOLINKS) + ctx->mark_char_map['.'] = 1; + + if(ctx->parser.flags & MD_FLAG_TABLES) + ctx->mark_char_map['|'] = 1; + + if(ctx->parser.flags & MD_FLAG_COLLAPSEWHITESPACE) { + int i; + + for(i = 0; i < sizeof(ctx->mark_char_map); i++) { + if(ISWHITESPACE_(i)) + ctx->mark_char_map[i] = 1; + } + } +} + +static int +md_collect_marks(MD_CTX* ctx, const MD_LINE* lines, int n_lines, int table_mode) +{ + int i; + int ret = 0; + MD_MARK* mark; + + for(i = 0; i < n_lines; i++) { + const MD_LINE* line = &lines[i]; + OFF off = line->beg; + OFF line_end = line->end; + + while(TRUE) { + CHAR ch; + +#ifdef MD4C_USE_UTF16 + /* For UTF-16, mark_char_map[] covers only ASCII. */ + #define IS_MARK_CHAR(off) ((CH(off) < SIZEOF_ARRAY(ctx->mark_char_map)) && \ + (ctx->mark_char_map[(unsigned char) CH(off)])) +#else + /* For 8-bit encodings, mark_char_map[] covers all 256 elements. */ + #define IS_MARK_CHAR(off) (ctx->mark_char_map[(unsigned char) CH(off)]) +#endif + + /* Optimization: Fast path (with some loop unrolling). */ + while(off + 4 < line_end && !IS_MARK_CHAR(off+0) && !IS_MARK_CHAR(off+1) + && !IS_MARK_CHAR(off+2) && !IS_MARK_CHAR(off+3)) + off += 4; + while(off < line_end && !IS_MARK_CHAR(off+0)) + off++; + + if(off >= line_end) + break; + + ch = CH(off); + + /* A backslash escape. + * It can go beyond line->end as it may involve escaped new + * line to form a hard break. */ + if(ch == _T('\\') && off+1 < ctx->size && (ISPUNCT(off+1) || ISNEWLINE(off+1))) { + /* Hard-break cannot be on the last line of the block. */ + if(!ISNEWLINE(off+1) || i+1 < n_lines) + PUSH_MARK(ch, off, off+2, MD_MARK_RESOLVED); + + /* If '`' or '>' follows, we need both marks as the backslash + * may be inside a code span or an autolink where escaping is + * disabled. */ + if(CH(off+1) == _T('`') || CH(off+1) == _T('>')) + off++; + else + off += 2; + continue; + } + + /* A potential (string) emphasis start/end. */ + if(ch == _T('*') || ch == _T('_')) { + OFF tmp = off+1; + int left_level; /* What precedes: 0 = whitespace; 1 = punctuation; 2 = other char. */ + int right_level; /* What follows: 0 = whitespace; 1 = punctuation; 2 = other char. */ + + while(tmp < line_end && CH(tmp) == ch) + tmp++; + + if(off == line->beg || ISUNICODEWHITESPACEBEFORE(off)) + left_level = 0; + else if(ISUNICODEPUNCTBEFORE(off)) + left_level = 1; + else + left_level = 2; + + if(tmp == line_end || ISUNICODEWHITESPACE(tmp)) + right_level = 0; + else if(ISUNICODEPUNCT(tmp)) + right_level = 1; + else + right_level = 2; + + /* Intra-word underscore doesn't have special meaning. */ + if(ch == _T('_') && left_level == 2 && right_level == 2) { + left_level = 0; + right_level = 0; + } + + if(left_level != 0 || right_level != 0) { + unsigned flags = 0; + + if(left_level > 0 && left_level >= right_level) + flags |= MD_MARK_POTENTIAL_CLOSER; + if(right_level > 0 && right_level >= left_level) + flags |= MD_MARK_POTENTIAL_OPENER; + if(left_level == 2 && right_level == 2) + flags |= MD_MARK_EMPH_INTRAWORD; + + /* For "the rule of three" we need to remember the original + * size of the mark (modulo three), before we potentially + * split the mark when being later resolved partially by some + * shorter closer. */ + switch((tmp - off) % 3) { + case 0: flags |= MD_MARK_EMPH_MODULO3_0; break; + case 1: flags |= MD_MARK_EMPH_MODULO3_1; break; + case 2: flags |= MD_MARK_EMPH_MODULO3_2; break; + } + + PUSH_MARK(ch, off, tmp, flags); + + /* During resolving, multiple asterisks may have to be + * split into independent span start/ends. Consider e.g. + * "**foo* bar*". Therefore we push also some empty dummy + * marks to have enough space for that. */ + off++; + while(off < tmp) { + PUSH_MARK('D', off, off, 0); + off++; + } + continue; + } + + off = tmp; + continue; + } + + /* A potential code span start/end. */ + if(ch == _T('`')) { + OFF tmp = off+1; + + while(tmp < line_end && CH(tmp) == _T('`')) + tmp++; + + /* We limit code span marks to lower then 256 backticks. This + * solves a pathologic case of too many openers, each of + * different length: Their resolving is then O(n^2). */ + if(tmp - off < 256) + PUSH_MARK(ch, off, tmp, MD_MARK_POTENTIAL_OPENER | MD_MARK_POTENTIAL_CLOSER); + + off = tmp; + continue; + } + + /* A potential entity start. */ + if(ch == _T('&')) { + PUSH_MARK(ch, off, off+1, MD_MARK_POTENTIAL_OPENER); + off++; + continue; + } + + /* A potential entity end. */ + if(ch == _T(';')) { + /* We surely cannot be entity unless the previous mark is '&'. */ + if(ctx->n_marks > 0 && ctx->marks[ctx->n_marks-1].ch == _T('&')) + PUSH_MARK(ch, off, off+1, MD_MARK_POTENTIAL_CLOSER); + + off++; + continue; + } + + /* A potential autolink or raw HTML start/end. */ + if(ch == _T('<') || ch == _T('>')) { + if(!(ctx->parser.flags & MD_FLAG_NOHTMLSPANS)) + PUSH_MARK(ch, off, off+1, (ch == _T('<') ? MD_MARK_POTENTIAL_OPENER : MD_MARK_POTENTIAL_CLOSER)); + + off++; + continue; + } + + /* A potential link or its part. */ + if(ch == _T('[') || (ch == _T('!') && off+1 < line_end && CH(off+1) == _T('['))) { + OFF tmp = (ch == _T('[') ? off+1 : off+2); + PUSH_MARK(ch, off, tmp, MD_MARK_POTENTIAL_OPENER); + off = tmp; + /* Two dummies to make enough place for data we need if it is + * a link. */ + PUSH_MARK('D', off, off, 0); + PUSH_MARK('D', off, off, 0); + continue; + } + if(ch == _T(']')) { + PUSH_MARK(ch, off, off+1, MD_MARK_POTENTIAL_CLOSER); + off++; + continue; + } + + /* A potential permissive e-mail autolink. */ + if(ch == _T('@')) { + if(line->beg + 1 <= off && ISALNUM(off-1) && + off + 3 < line->end && ISALNUM(off+1)) + { + PUSH_MARK(ch, off, off+1, MD_MARK_POTENTIAL_OPENER); + /* Push a dummy as a reserve for a closer. */ + PUSH_MARK('D', off, off, 0); + } + + off++; + continue; + } + + /* A potential permissive URL autolink. */ + if(ch == _T(':')) { + static struct { + const CHAR* scheme; + SZ scheme_size; + const CHAR* suffix; + SZ suffix_size; + } scheme_map[] = { + /* In the order from the most frequently used, arguably. */ + { _T("http"), 4, _T("//"), 2 }, + { _T("https"), 5, _T("//"), 2 }, + { _T("ftp"), 3, _T("//"), 2 } + }; + int scheme_index; + + for(scheme_index = 0; scheme_index < SIZEOF_ARRAY(scheme_map); scheme_index++) { + const CHAR* scheme = scheme_map[scheme_index].scheme; + const SZ scheme_size = scheme_map[scheme_index].scheme_size; + const CHAR* suffix = scheme_map[scheme_index].suffix; + const SZ suffix_size = scheme_map[scheme_index].suffix_size; + + if(line->beg + scheme_size <= off && md_ascii_eq(STR(off-scheme_size), scheme, scheme_size) && + (line->beg + scheme_size == off || ISWHITESPACE(off-scheme_size-1) || ISANYOF(off-scheme_size-1, _T("*_~(["))) && + off + 1 + suffix_size < line->end && md_ascii_eq(STR(off+1), suffix, suffix_size)) + { + PUSH_MARK(ch, off-scheme_size, off+1+suffix_size, MD_MARK_POTENTIAL_OPENER); + /* Push a dummy as a reserve for a closer. */ + PUSH_MARK('D', off, off, 0); + off += 1 + suffix_size; + continue; + } + } + + off++; + continue; + } + + /* A potential permissive WWW autolink. */ + if(ch == _T('.')) { + if(line->beg + 3 <= off && md_ascii_eq(STR(off-3), _T("www"), 3) && + (line->beg + 3 == off || ISWHITESPACE(off-4) || ISANYOF(off-4, _T("*_~(["))) && + off + 1 < line_end) + { + PUSH_MARK(ch, off-3, off+1, MD_MARK_POTENTIAL_OPENER); + /* Push a dummy as a reserve for a closer. */ + PUSH_MARK('D', off, off, 0); + off++; + continue; + } + + off++; + continue; + } + + /* A potential table cell boundary. */ + if(table_mode && ch == _T('|')) { + PUSH_MARK(ch, off, off+1, 0); + off++; + continue; + } + + /* A potential strikethrough start/end. */ + if(ch == _T('~')) { + OFF tmp = off+1; + + while(tmp < line_end && CH(tmp) == _T('~')) + tmp++; + + PUSH_MARK(ch, off, tmp, MD_MARK_POTENTIAL_OPENER | MD_MARK_POTENTIAL_CLOSER); + off = tmp; + } + + /* Turn non-trivial whitespace into single space. */ + if(ISWHITESPACE_(ch)) { + OFF tmp = off+1; + + while(tmp < line_end && ISWHITESPACE(tmp)) + tmp++; + + if(tmp - off > 1 || ch != _T(' ')) + PUSH_MARK(ch, off, tmp, MD_MARK_RESOLVED); + + off = tmp; + continue; + } + + /* NULL character. */ + if(ch == _T('\0')) { + PUSH_MARK(ch, off, off+1, MD_MARK_RESOLVED); + off++; + continue; + } + + off++; + } + } + + /* Add a dummy mark at the end of the mark vector to simplify + * process_inlines(). */ + PUSH_MARK(127, ctx->size, ctx->size, MD_MARK_RESOLVED); + +abort: + return ret; +} + + +/* Analyze whether the back-tick is really start/end mark of a code span. + * If yes, reset all marks inside of it and setup flags of both marks. */ +static void +md_analyze_backtick(MD_CTX* ctx, int mark_index) +{ + MD_MARK* mark = &ctx->marks[mark_index]; + int opener_index = BACKTICK_OPENERS.tail; + + /* Try to find unresolved opener of the same length. If we find it, + * we form a code span. */ + while(opener_index >= 0) { + MD_MARK* opener = &ctx->marks[opener_index]; + + if(opener->end - opener->beg == mark->end - mark->beg) { + /* Rollback anything found inside it. + * (e.g. the code span contains some back-ticks or other special + * chars we misinterpreted.) */ + md_rollback(ctx, opener_index, mark_index, MD_ROLLBACK_ALL); + + /* Resolve the span. */ + md_resolve_range(ctx, &BACKTICK_OPENERS, opener_index, mark_index); + + /* Append any space or new line inside the span into the mark + * itself to swallow it. */ + while(CH(opener->end) == _T(' ') || ISNEWLINE(opener->end)) + opener->end++; + if(mark->beg > opener->end) { + while(CH(mark->beg-1) == _T(' ') || ISNEWLINE(mark->beg-1)) + mark->beg--; + } + + /* Done. */ + return; + } + + opener_index = ctx->marks[opener_index].prev; + } + + /* We didn't find any matching opener, so we ourselves may be the opener + * of some upcoming closer. We also have to handle specially if there is + * a backslash mark before it as that can cancel the first backtick. */ + if(mark_index > 0 && (mark-1)->beg == mark->beg - 1 && (mark-1)->ch == '\\') { + if(mark->end - mark->beg == 1) { + /* Single escaped backtick. */ + return; + } + + /* Remove the escaped backtick from the opener. */ + mark->beg++; + } + + if(mark->flags & MD_MARK_POTENTIAL_OPENER) + md_mark_chain_append(ctx, &BACKTICK_OPENERS, mark_index); +} + +static int +md_is_autolink_uri(MD_CTX* ctx, OFF beg, OFF end) +{ + OFF off = beg; + + /* Check for scheme. */ + if(off >= end || !ISASCII(off)) + return FALSE; + off++; + while(1) { + if(off >= end) + return FALSE; + if(off - beg > 32) + return FALSE; + if(CH(off) == _T(':') && off - beg >= 2) + break; + if(!ISALNUM(off) && CH(off) != _T('+') && CH(off) != _T('-') && CH(off) != _T('.')) + return FALSE; + off++; + } + + /* Check the path after the scheme. */ + while(off < end) { + if(ISWHITESPACE(off) || ISCNTRL(off) || CH(off) == _T('<') || CH(off) == _T('>')) + return FALSE; + off++; + } + + return TRUE; +} + +static int +md_is_autolink_email(MD_CTX* ctx, OFF beg, OFF end) +{ + OFF off = beg; + int label_len; + + /* The code should correspond to this regexp: + /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+ + @[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])? + (?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/ + */ + + /* Username (before '@'). */ + while(off < end && (ISALNUM(off) || ISANYOF(off, _T(".!#$%&'*+/=?^_`{|}~-")))) + off++; + if(off <= beg) + return FALSE; + + /* '@' */ + if(off >= end || CH(off) != _T('@')) + return FALSE; + off++; + + /* Labels delimited with '.'; each label is sequence of 1 - 62 alnum + * characters or '-', but '-' is not allowed as first or last char. */ + label_len = 0; + while(off < end) { + if(ISALNUM(off)) + label_len++; + else if(CH(off) == _T('-') && label_len > 0) + label_len++; + else if(CH(off) == _T('.') && label_len > 0 && CH(off-1) != _T('-')) + label_len = 0; + else + return FALSE; + + if(label_len > 63) + return FALSE; + + off++; + } + + if(label_len <= 0 || CH(off-1) == _T('-')) + return FALSE; + + return TRUE; +} + +static int +md_is_autolink(MD_CTX* ctx, OFF beg, OFF end, int* p_missing_mailto) +{ + MD_ASSERT(CH(beg) == _T('<')); + MD_ASSERT(CH(end-1) == _T('>')); + + beg++; + end--; + + if(md_is_autolink_uri(ctx, beg, end)) + return TRUE; + + if(md_is_autolink_email(ctx, beg, end)) { + *p_missing_mailto = 1; + return TRUE; + } + + return FALSE; +} + +static void +md_analyze_lt_gt(MD_CTX* ctx, int mark_index, const MD_LINE* lines, int n_lines) +{ + MD_MARK* mark = &ctx->marks[mark_index]; + int opener_index; + + /* If it is an opener ('<'), remember it. */ + if(mark->flags & MD_MARK_POTENTIAL_OPENER) { + md_mark_chain_append(ctx, &LOWERTHEN_OPENERS, mark_index); + return; + } + + /* Otherwise we are potential closer and we try to resolve with since all + * the chained unresolved openers. */ + opener_index = LOWERTHEN_OPENERS.head; + while(opener_index >= 0) { + MD_MARK* opener = &ctx->marks[opener_index]; + OFF detected_end; + int is_autolink = 0; + int is_missing_mailto = 0; + int is_raw_html = 0; + + is_autolink = (md_is_autolink(ctx, opener->beg, mark->end, &is_missing_mailto)); + + if(is_autolink) { + if(is_missing_mailto) + opener->ch = _T('@'); + } else { + /* Identify the line where the opening mark lives. */ + int line_index = 0; + while(1) { + if(opener->beg < lines[line_index].end) + break; + line_index++; + } + + is_raw_html = (md_is_html_any(ctx, lines + line_index, + n_lines - line_index, opener->beg, mark->end, &detected_end)); + } + + /* Check whether the range forms a valid raw HTML. */ + if(is_autolink || is_raw_html) { + md_rollback(ctx, opener_index, mark_index, MD_ROLLBACK_ALL); + md_resolve_range(ctx, &LOWERTHEN_OPENERS, opener_index, mark_index); + + if(is_raw_html) { + /* If this fails, it means we have missed some earlier opportunity + * to resolve the opener of raw HTML. */ + MD_ASSERT(detected_end == mark->end); + + /* Make these marks zero width so the '<' and '>' are part of its + * contents. */ + opener->end = opener->beg; + mark->beg = mark->end; + + opener->flags &= ~MD_MARK_AUTOLINK; + mark->flags &= ~MD_MARK_AUTOLINK; + } else { + opener->flags |= MD_MARK_AUTOLINK; + mark->flags |= MD_MARK_AUTOLINK; + } + + /* And we are done. */ + return; + } + + opener_index = opener->next; + } +} + +static void +md_analyze_bracket(MD_CTX* ctx, int mark_index) +{ + /* We cannot really resolve links here as for that we would need + * more context. E.g. a following pair of brackets (reference link), + * or enclosing pair of brackets (if the inner is the link, the outer + * one cannot be.) + * + * Therefore we here only construct a list of resolved '[' ']' pairs + * ordered by position of the closer. This allows ur to analyze what is + * or is not link in the right order, from inside to outside in case + * of nested brackets. + * + * The resolving itself is deferred into md_resolve_links(). + */ + + MD_MARK* mark = &ctx->marks[mark_index]; + + if(mark->flags & MD_MARK_POTENTIAL_OPENER) { + md_mark_chain_append(ctx, &BRACKET_OPENERS, mark_index); + return; + } + + if(BRACKET_OPENERS.tail >= 0) { + /* Pop the opener from the chain. */ + int opener_index = BRACKET_OPENERS.tail; + MD_MARK* opener = &ctx->marks[opener_index]; + if(opener->prev >= 0) + ctx->marks[opener->prev].next = -1; + else + BRACKET_OPENERS.head = -1; + BRACKET_OPENERS.tail = opener->prev; + + /* Interconnect the opener and closer. */ + opener->next = mark_index; + mark->prev = opener_index; + + /* Add the pair into chain of potential links for md_resolve_links(). + * Note we misuse opener->prev for this as opener->next points to its + * closer. */ + if(ctx->unresolved_link_tail >= 0) + ctx->marks[ctx->unresolved_link_tail].prev = opener_index; + else + ctx->unresolved_link_head = opener_index; + ctx->unresolved_link_tail = opener_index; + opener->prev = -1; + } +} + +/* Forward declaration. */ +static void md_analyze_link_contents(MD_CTX* ctx, const MD_LINE* lines, int n_lines, + int mark_beg, int mark_end); + +static int +md_resolve_links(MD_CTX* ctx, const MD_LINE* lines, int n_lines) +{ + int opener_index = ctx->unresolved_link_head; + OFF last_link_beg = 0; + OFF last_link_end = 0; + OFF last_img_beg = 0; + OFF last_img_end = 0; + + while(opener_index >= 0) { + MD_MARK* opener = &ctx->marks[opener_index]; + int closer_index = opener->next; + MD_MARK* closer = &ctx->marks[closer_index]; + int next_index = opener->prev; + MD_MARK* next_opener; + MD_MARK* next_closer; + MD_LINK_ATTR attr; + int is_link = FALSE; + + if(next_index >= 0) { + next_opener = &ctx->marks[next_index]; + next_closer = &ctx->marks[next_opener->next]; + } else { + next_opener = NULL; + next_closer = NULL; + } + + /* If nested ("[ [ ] ]"), we need to make sure that: + * - The outer does not end inside of (...) belonging to the inner. + * - The outer cannot be link if the inner is link (i.e. not image). + * + * (Note we here analyze from inner to outer as the marks are ordered + * by closer->beg.) + */ + if((opener->beg < last_link_beg && closer->end < last_link_end) || + (opener->beg < last_img_beg && closer->end < last_img_end) || + (opener->beg < last_link_end && opener->ch == '[')) + { + opener_index = next_index; + continue; + } + + if(next_opener != NULL && next_opener->beg == closer->end) { + if(next_closer->beg > closer->end + 1) { + /* Might be full reference link. */ + is_link = md_is_link_reference(ctx, lines, n_lines, next_opener->beg, next_closer->end, &attr); + } else { + /* Might be shortcut reference link. */ + is_link = md_is_link_reference(ctx, lines, n_lines, opener->beg, closer->end, &attr); + } + + if(is_link < 0) + return -1; + + if(is_link) { + /* Eat the 2nd "[...]". */ + closer->end = next_closer->end; + } + } else { + if(closer->end < ctx->size && CH(closer->end) == _T('(')) { + /* Might be inline link. */ + OFF inline_link_end = -1; + + is_link = md_is_inline_link_spec(ctx, lines, n_lines, closer->end, &inline_link_end, &attr); + if(is_link < 0) + return -1; + + /* Check the closing ')' is not inside an already resolved range + * (i.e. a range with a higher priority), e.g. a code span. */ + if(is_link) { + int i = closer_index + 1; + + while(i < ctx->n_marks) { + MD_MARK* mark = &ctx->marks[i]; + + if(mark->beg >= inline_link_end) + break; + if((mark->flags & (MD_MARK_OPENER | MD_MARK_RESOLVED)) == (MD_MARK_OPENER | MD_MARK_RESOLVED)) { + if(ctx->marks[mark->next].beg >= inline_link_end) { + /* Cancel the link status. */ + if(attr.title_needs_free) + free(attr.title); + is_link = FALSE; + break; + } + + i = mark->next + 1; + } else { + i++; + } + } + } + + if(is_link) { + /* Eat the "(...)" */ + closer->end = inline_link_end; + } + } + + if(!is_link) { + /* Might be collapsed reference link. */ + is_link = md_is_link_reference(ctx, lines, n_lines, opener->beg, closer->end, &attr); + if(is_link < 0) + return -1; + } + } + + if(is_link) { + /* Resolve the brackets as a link. */ + opener->flags |= MD_MARK_OPENER | MD_MARK_RESOLVED; + closer->flags |= MD_MARK_CLOSER | MD_MARK_RESOLVED; + + /* If it is a link, we store the destination and title in the two + * dummy marks after the opener. */ + MD_ASSERT(ctx->marks[opener_index+1].ch == 'D'); + ctx->marks[opener_index+1].beg = attr.dest_beg; + ctx->marks[opener_index+1].end = attr.dest_end; + + MD_ASSERT(ctx->marks[opener_index+2].ch == 'D'); + md_mark_store_ptr(ctx, opener_index+2, attr.title); + if(attr.title_needs_free) + md_mark_chain_append(ctx, &PTR_CHAIN, opener_index+2); + ctx->marks[opener_index+2].prev = attr.title_size; + + if(opener->ch == '[') { + last_link_beg = opener->beg; + last_link_end = closer->end; + } else { + last_img_beg = opener->beg; + last_img_end = closer->end; + } + + md_analyze_link_contents(ctx, lines, n_lines, opener_index+1, closer_index); + } + + opener_index = next_index; + } + + return 0; +} + +/* Analyze whether the mark '&' starts a HTML entity. + * If so, update its flags as well as flags of corresponding closer ';'. */ +static void +md_analyze_entity(MD_CTX* ctx, int mark_index) +{ + MD_MARK* opener = &ctx->marks[mark_index]; + MD_MARK* closer; + OFF off; + + /* Cannot be entity if there is no closer as the next mark. + * (Any other mark between would mean strange character which cannot be + * part of the entity. + * + * So we can do all the work on '&' and do not call this later for the + * closing mark ';'. + */ + if(mark_index + 1 >= ctx->n_marks) + return; + closer = &ctx->marks[mark_index+1]; + if(closer->ch != ';') + return; + + if(md_is_entity(ctx, opener->beg, closer->end, &off)) { + MD_ASSERT(off == closer->end); + + md_resolve_range(ctx, NULL, mark_index, mark_index+1); + opener->end = closer->end; + } +} + +static void +md_analyze_table_cell_boundary(MD_CTX* ctx, int mark_index) +{ + MD_MARK* mark = &ctx->marks[mark_index]; + mark->flags |= MD_MARK_RESOLVED; + + md_mark_chain_append(ctx, &TABLECELLBOUNDARIES, mark_index); + ctx->n_table_cell_boundaries++; +} + +/* Split a longer mark into two. The new mark takes the given count of + * characters. May only be called if an adequate number of dummy 'D' marks + * follows. + */ +static int +md_split_simple_pairing_mark(MD_CTX* ctx, int mark_index, SZ n) +{ + MD_MARK* mark = &ctx->marks[mark_index]; + int new_mark_index = mark_index + (mark->end - mark->beg - n); + MD_MARK* dummy = &ctx->marks[new_mark_index]; + + MD_ASSERT(mark->end - mark->beg > n); + MD_ASSERT(dummy->ch == 'D'); + + memcpy(dummy, mark, sizeof(MD_MARK)); + mark->end -= n; + dummy->beg = mark->end; + + return new_mark_index; +} + +static void +md_analyze_simple_pairing_mark(MD_CTX* ctx, MD_MARKCHAIN* chain, int mark_index, + int apply_rule_of_three) +{ + MD_MARK* mark = &ctx->marks[mark_index]; + + /* If we can be a closer, try to resolve with the preceding opener. */ + if((mark->flags & MD_MARK_POTENTIAL_CLOSER) && chain->tail >= 0) { + int opener_index = chain->tail; + MD_MARK* opener = &ctx->marks[opener_index]; + SZ opener_size = opener->end - opener->beg; + SZ closer_size = mark->end - mark->beg; + + /* Apply the "rule of three". */ + if(apply_rule_of_three) { + while((mark->flags & MD_MARK_EMPH_INTRAWORD) || (opener->flags & MD_MARK_EMPH_INTRAWORD)) { + SZ opener_orig_size_modulo3; + + switch(opener->flags & MD_MARK_EMPH_MODULO3_MASK) { + case MD_MARK_EMPH_MODULO3_0: opener_orig_size_modulo3 = 0; break; + case MD_MARK_EMPH_MODULO3_1: opener_orig_size_modulo3 = 1; break; + case MD_MARK_EMPH_MODULO3_2: opener_orig_size_modulo3 = 2; break; + default: MD_UNREACHABLE(); break; + } + + if((opener_orig_size_modulo3 + closer_size) % 3 != 0) { + /* This opener is suitable. */ + break; + } + + if(opener->prev >= 0) { + /* Try previous opener. */ + opener_index = opener->prev; + opener = &ctx->marks[opener_index]; + opener_size = opener->end - opener->beg; + closer_size = mark->end - mark->beg; + } else { + /* No suitable opener found. */ + goto cannot_resolve; + } + } + } + + if(opener_size > closer_size) { + opener_index = md_split_simple_pairing_mark(ctx, opener_index, closer_size); + md_mark_chain_append(ctx, chain, opener_index); + } else if(opener_size < closer_size) { + md_split_simple_pairing_mark(ctx, mark_index, closer_size - opener_size); + } + + md_rollback(ctx, opener_index, mark_index, MD_ROLLBACK_CROSSING); + md_resolve_range(ctx, chain, opener_index, mark_index); + return; + } + +cannot_resolve: + /* If not resolved, and we can be an opener, remember the mark for + * the future. */ + if(mark->flags & MD_MARK_POTENTIAL_OPENER) + md_mark_chain_append(ctx, chain, mark_index); +} + +static inline void +md_analyze_asterisk(MD_CTX* ctx, int mark_index) +{ + md_analyze_simple_pairing_mark(ctx, &ASTERISK_OPENERS, mark_index, 1); +} + +static inline void +md_analyze_underscore(MD_CTX* ctx, int mark_index) +{ + md_analyze_simple_pairing_mark(ctx, &UNDERSCORE_OPENERS, mark_index, 1); +} + +static void +md_analyze_tilde(MD_CTX* ctx, int mark_index) +{ + /* We attempt to be Github Flavored Markdown compatible here. GFM says + * that length of the tilde sequence is not important at all. Note that + * implies the TILDE_OPENERS chain can have at most one item. */ + + if(TILDE_OPENERS.head >= 0) { + /* The chain already contains an opener, so we may resolve the span. */ + int opener_index = TILDE_OPENERS.head; + + md_rollback(ctx, opener_index, mark_index, MD_ROLLBACK_CROSSING); + md_resolve_range(ctx, &TILDE_OPENERS, opener_index, mark_index); + } else { + /* We can only be opener. */ + md_mark_chain_append(ctx, &TILDE_OPENERS, mark_index); + } +} + +static void +md_analyze_permissive_url_autolink(MD_CTX* ctx, int mark_index) +{ + MD_MARK* opener = &ctx->marks[mark_index]; + int closer_index = mark_index + 1; + MD_MARK* closer = &ctx->marks[closer_index]; + MD_MARK* next_resolved_mark; + OFF off = opener->end; + int seen_dot = FALSE; + int seen_underscore_or_hyphen[2] = { FALSE, FALSE }; + + /* Check for domain. */ + while(off < ctx->size) { + if(ISALNUM(off)) { + off++; + } else if(CH(off) == _T('.')) { + seen_dot = TRUE; + seen_underscore_or_hyphen[0] = seen_underscore_or_hyphen[1]; + seen_underscore_or_hyphen[1] = FALSE; + off++; + } else if(ISANYOF2(off, _T('-'), _T('_'))) { + seen_underscore_or_hyphen[1] = TRUE; + off++; + } else { + break; + } + } + + if(off <= opener->end || !seen_dot || seen_underscore_or_hyphen[0] || seen_underscore_or_hyphen[1]) + return; + + /* Check for path. */ + next_resolved_mark = closer + 1; + while(next_resolved_mark->ch == 'D' || !(next_resolved_mark->flags & MD_MARK_RESOLVED)) + next_resolved_mark++; + while(off < next_resolved_mark->beg && CH(off) != _T('<') && !ISWHITESPACE(off) && !ISNEWLINE(off)) + off++; + + /* Path validation. */ + if(ISANYOF(off-1, _T("?!.,:*_~)"))) { + if(CH(off-1) != _T(')')) { + off--; + } else { + int parenthesis_balance = 0; + OFF tmp; + + for(tmp = opener->end; tmp < off; tmp++) { + if(CH(tmp) == _T('(')) + parenthesis_balance++; + else if(CH(tmp) == _T(')')) + parenthesis_balance--; + } + + if(parenthesis_balance < 0) + off--; + } + } + + /* Ok. Lets call it auto-link. Adapt opener and create closer to zero + * length so all the contents becomes the link text. */ + MD_ASSERT(closer->ch == 'D'); + opener->end = opener->beg; + closer->ch = opener->ch; + closer->beg = off; + closer->end = off; + md_resolve_range(ctx, NULL, mark_index, closer_index); +} + +/* The permissive autolinks do not have to be enclosed in '<' '>' but we + * instead impose stricter rules what is understood as an e-mail address + * here. Actually any non-alphanumeric characters with exception of '.' + * are prohibited both in username and after '@'. */ +static void +md_analyze_permissive_email_autolink(MD_CTX* ctx, int mark_index) +{ + MD_MARK* opener = &ctx->marks[mark_index]; + int closer_index; + MD_MARK* closer; + OFF beg = opener->beg; + OFF end = opener->end; + int dot_count = 0; + + MD_ASSERT(CH(beg) == _T('@')); + + /* Scan for name before '@'. */ + while(beg > 0 && (ISALNUM(beg-1) || ISANYOF(beg-1, _T(".-_+")))) + beg--; + + /* Scan for domain after '@'. */ + while(end < ctx->size && (ISALNUM(end) || ISANYOF(end, _T(".-_")))) { + if(CH(end) == _T('.')) + dot_count++; + end++; + } + if(CH(end-1) == _T('.')) { /* Final '.' not part of it. */ + dot_count--; + end--; + } + else if(ISANYOF2(end-1, _T('-'), _T('_'))) /* These are forbidden at the end. */ + return; + if(CH(end-1) == _T('@') || dot_count == 0) + return; + + /* Ok. Lets call it auto-link. Adapt opener and create closer to zero + * length so all the contents becomes the link text. */ + closer_index = mark_index + 1; + closer = &ctx->marks[closer_index]; + MD_ASSERT(closer->ch == 'D'); + + opener->beg = beg; + opener->end = beg; + closer->ch = opener->ch; + closer->beg = end; + closer->end = end; + md_resolve_range(ctx, NULL, mark_index, closer_index); +} + +static inline void +md_analyze_marks(MD_CTX* ctx, const MD_LINE* lines, int n_lines, + int mark_beg, int mark_end, const CHAR* mark_chars) +{ + int i = mark_beg; + + while(i < mark_end) { + MD_MARK* mark = &ctx->marks[i]; + + /* Skip resolved spans. */ + if(mark->flags & MD_MARK_RESOLVED) { + if(mark->flags & MD_MARK_OPENER) { + MD_ASSERT(i < mark->next); + i = mark->next + 1; + } else { + i++; + } + continue; + } + + /* Skip marks we do not want to deal with. */ + if(!ISANYOF_(mark->ch, mark_chars)) { + i++; + continue; + } + + /* Analyze the mark. */ + switch(mark->ch) { + case '`': md_analyze_backtick(ctx, i); break; + case '<': /* Pass through. */ + case '>': md_analyze_lt_gt(ctx, i, lines, n_lines); break; + case '[': /* Pass through. */ + case '!': /* Pass through. */ + case ']': md_analyze_bracket(ctx, i); break; + case '&': md_analyze_entity(ctx, i); break; + case '|': md_analyze_table_cell_boundary(ctx, i); break; + case '*': md_analyze_asterisk(ctx, i); break; + case '_': md_analyze_underscore(ctx, i); break; + case '~': md_analyze_tilde(ctx, i); break; + case '.': /* Pass through. */ + case ':': md_analyze_permissive_url_autolink(ctx, i); break; + case '@': md_analyze_permissive_email_autolink(ctx, i); break; + } + + i++; + } +} + +/* Analyze marks (build ctx->marks). */ +static int +md_analyze_inlines(MD_CTX* ctx, const MD_LINE* lines, int n_lines, int table_mode) +{ + int ret; + + /* Reset the previously collected stack of marks. */ + ctx->n_marks = 0; + + /* Collect all marks. */ + MD_CHECK(md_collect_marks(ctx, lines, n_lines, table_mode)); + + /* We analyze marks in few groups to handle their precedence. */ + /* (1) Entities; code spans; autolinks; raw HTML. */ + md_analyze_marks(ctx, lines, n_lines, 0, ctx->n_marks, _T("&`<>")); + BACKTICK_OPENERS.head = -1; + BACKTICK_OPENERS.tail = -1; + LOWERTHEN_OPENERS.head = -1; + LOWERTHEN_OPENERS.tail = -1; + + if(table_mode) { + /* (2) Analyze table cell boundaries. + * Note we reset TABLECELLBOUNDARIES chain prior to the call md_analyze_marks(), + * not after, because caller may need it. */ + MD_ASSERT(n_lines == 1); + TABLECELLBOUNDARIES.head = -1; + TABLECELLBOUNDARIES.tail = -1; + ctx->n_table_cell_boundaries = 0; + md_analyze_marks(ctx, lines, n_lines, 0, ctx->n_marks, _T("|")); + return ret; + } + + /* (3) Links. */ + md_analyze_marks(ctx, lines, n_lines, 0, ctx->n_marks, _T("[]!")); + MD_CHECK(md_resolve_links(ctx, lines, n_lines)); + BRACKET_OPENERS.head = -1; + BRACKET_OPENERS.tail = -1; + ctx->unresolved_link_head = -1; + ctx->unresolved_link_tail = -1; + + /* (4) Emphasis and strong emphasis; permissive autolinks. */ + md_analyze_link_contents(ctx, lines, n_lines, 0, ctx->n_marks); + +abort: + return ret; +} + +static void +md_analyze_link_contents(MD_CTX* ctx, const MD_LINE* lines, int n_lines, + int mark_beg, int mark_end) +{ + md_analyze_marks(ctx, lines, n_lines, mark_beg, mark_end, _T("*_~@:.")); + ASTERISK_OPENERS.head = -1; + ASTERISK_OPENERS.tail = -1; + UNDERSCORE_OPENERS.head = -1; + UNDERSCORE_OPENERS.tail = -1; + TILDE_OPENERS.head = -1; + TILDE_OPENERS.tail = -1; +} + +static int +md_enter_leave_span_a(MD_CTX* ctx, int enter, MD_SPANTYPE type, + const CHAR* dest, SZ dest_size, int prohibit_escapes_in_dest, + const CHAR* title, SZ title_size) +{ + MD_ATTRIBUTE_BUILD href_build = { 0 }; + MD_ATTRIBUTE_BUILD title_build = { 0 }; + MD_SPAN_A_DETAIL det; + int ret = 0; + + /* Note we here rely on fact that MD_SPAN_A_DETAIL and + * MD_SPAN_IMG_DETAIL are binary-compatible. */ + memset(&det, 0, sizeof(MD_SPAN_A_DETAIL)); + MD_CHECK(md_build_attribute(ctx, dest, dest_size, + (prohibit_escapes_in_dest ? MD_BUILD_ATTR_NO_ESCAPES : 0), + &det.href, &href_build)); + MD_CHECK(md_build_attribute(ctx, title, title_size, 0, &det.title, &title_build)); + + if(enter) + MD_ENTER_SPAN(type, &det); + else + MD_LEAVE_SPAN(type, &det); + +abort: + md_free_attribute(ctx, &href_build); + md_free_attribute(ctx, &title_build); + return ret; +} + +/* Render the output, accordingly to the analyzed ctx->marks. */ +static int +md_process_inlines(MD_CTX* ctx, const MD_LINE* lines, int n_lines) +{ + MD_TEXTTYPE text_type; + const MD_LINE* line = lines; + MD_MARK* prev_mark = NULL; + MD_MARK* mark; + OFF off = lines[0].beg; + OFF end = lines[n_lines-1].end; + int enforce_hardbreak = 0; + int ret = 0; + + /* Find first resolved mark. Note there is always at least one resolved + * mark, the dummy last one after the end of the latest line we actually + * never really reach. This saves us of a lot of special checks and cases + * in this function. */ + mark = ctx->marks; + while(!(mark->flags & MD_MARK_RESOLVED)) + mark++; + + text_type = MD_TEXT_NORMAL; + + while(1) { + /* Process the text up to the next mark or end-of-line. */ + OFF tmp = (line->end < mark->beg ? line->end : mark->beg); + if(tmp > off) { + MD_TEXT(text_type, STR(off), tmp - off); + off = tmp; + } + + /* If reached the mark, process it and move to next one. */ + if(off >= mark->beg) { + switch(mark->ch) { + case '\\': /* Backslash escape. */ + if(ISNEWLINE(mark->beg+1)) + enforce_hardbreak = 1; + else + MD_TEXT(text_type, STR(mark->beg+1), 1); + break; + + case ' ': /* Non-trivial space. */ + MD_TEXT(text_type, _T(" "), 1); + break; + + case '`': /* Code span. */ + if(mark->flags & MD_MARK_OPENER) { + MD_ENTER_SPAN(MD_SPAN_CODE, NULL); + text_type = MD_TEXT_CODE; + } else { + MD_LEAVE_SPAN(MD_SPAN_CODE, NULL); + text_type = MD_TEXT_NORMAL; + } + break; + + case '_': + case '*': /* Emphasis, strong emphasis. */ + if(mark->flags & MD_MARK_OPENER) { + if((mark->end - off) % 2) { + MD_ENTER_SPAN(MD_SPAN_EM, NULL); + off++; + } + while(off + 1 < mark->end) { + MD_ENTER_SPAN(MD_SPAN_STRONG, NULL); + off += 2; + } + } else { + while(off + 1 < mark->end) { + MD_LEAVE_SPAN(MD_SPAN_STRONG, NULL); + off += 2; + } + if((mark->end - off) % 2) { + MD_LEAVE_SPAN(MD_SPAN_EM, NULL); + off++; + } + } + break; + + case '~': + if(mark->flags & MD_MARK_OPENER) + MD_ENTER_SPAN(MD_SPAN_DEL, NULL); + else + MD_LEAVE_SPAN(MD_SPAN_DEL, NULL); + break; + + case '[': /* Link, image. */ + case '!': + case ']': + { + const MD_MARK* opener = (mark->ch != ']' ? mark : &ctx->marks[mark->prev]); + const MD_MARK* dest_mark = opener+1; + const MD_MARK* title_mark = opener+2; + + MD_ASSERT(dest_mark->ch == 'D'); + MD_ASSERT(title_mark->ch == 'D'); + + MD_CHECK(md_enter_leave_span_a(ctx, (mark->ch != ']'), + (opener->ch == '!' ? MD_SPAN_IMG : MD_SPAN_A), + STR(dest_mark->beg), dest_mark->end - dest_mark->beg, FALSE, + md_mark_get_ptr(ctx, title_mark - ctx->marks), title_mark->prev)); + + /* link/image closer may span multiple lines. */ + if(mark->ch == ']') { + while(mark->end > line->end) + line++; + } + + break; + } + + case '<': + case '>': /* Autolink or raw HTML. */ + if(!(mark->flags & MD_MARK_AUTOLINK)) { + /* Raw HTML. */ + if(mark->flags & MD_MARK_OPENER) + text_type = MD_TEXT_HTML; + else + text_type = MD_TEXT_NORMAL; + break; + } + /* Pass through, if auto-link. */ + + case '@': /* Permissive e-mail autolink. */ + case ':': /* Permissive URL autolink. */ + case '.': /* Permissive WWW autolink. */ + { + MD_MARK* opener = ((mark->flags & MD_MARK_OPENER) ? mark : &ctx->marks[mark->prev]); + MD_MARK* closer = &ctx->marks[opener->next]; + const CHAR* dest = STR(opener->end); + SZ dest_size = closer->beg - opener->end; + + /* For permissive auto-links we do not know closer mark + * position at the time of md_collect_marks(), therefore + * it can be out-of-order in ctx->marks[]. + * + * With this flag, we make sure that we output the closer + * only if we processed the opener. */ + if(mark->flags & MD_MARK_OPENER) + closer->flags |= MD_MARK_VALIDPERMISSIVEAUTOLINK; + + if(opener->ch == '@' || opener->ch == '.') { + dest_size += 7; + MD_TEMP_BUFFER(dest_size * sizeof(CHAR)); + memcpy(ctx->buffer, + (opener->ch == '@' ? _T("mailto:") : _T("http://")), + 7 * sizeof(CHAR)); + memcpy(ctx->buffer + 7, dest, (dest_size-7) * sizeof(CHAR)); + dest = ctx->buffer; + } + + if(closer->flags & MD_MARK_VALIDPERMISSIVEAUTOLINK) + MD_CHECK(md_enter_leave_span_a(ctx, (mark->flags & MD_MARK_OPENER), + MD_SPAN_A, dest, dest_size, TRUE, NULL, 0)); + break; + } + + case '&': /* Entity. */ + MD_TEXT(MD_TEXT_ENTITY, STR(mark->beg), mark->end - mark->beg); + break; + + case '\0': + MD_TEXT(MD_TEXT_NULLCHAR, _T(""), 1); + break; + + case 127: + goto abort; + } + + off = mark->end; + + /* Move to next resolved mark. */ + prev_mark = mark; + mark++; + while(!(mark->flags & MD_MARK_RESOLVED) || mark->beg < off) + mark++; + } + + /* If reached end of line, move to next one. */ + if(off >= line->end) { + /* If it is the last line, we are done. */ + if(off >= end) + break; + + if(text_type == MD_TEXT_CODE) { + /* Inside code spans, new lines are transformed into single + * spaces. */ + MD_ASSERT(prev_mark != NULL); + MD_ASSERT(prev_mark->ch == '`' && (prev_mark->flags & MD_MARK_OPENER)); + MD_ASSERT(mark->ch == '`' && (mark->flags & MD_MARK_CLOSER)); + + if(prev_mark->end < off && off < mark->beg) + MD_TEXT(MD_TEXT_CODE, _T(" "), 1); + } else if(text_type == MD_TEXT_HTML) { + /* Inside raw HTML, we output the new line verbatim, including + * any trailing spaces. */ + OFF tmp = off; + + while(tmp < end && ISBLANK(tmp)) + tmp++; + if(tmp > off) + MD_TEXT(MD_TEXT_HTML, STR(off), tmp - off); + MD_TEXT(MD_TEXT_HTML, _T("\n"), 1); + } else { + /* Output soft or hard line break. */ + MD_TEXTTYPE break_type = MD_TEXT_SOFTBR; + + if(text_type == MD_TEXT_NORMAL) { + if(enforce_hardbreak) + break_type = MD_TEXT_BR; + else if((CH(line->end) == _T(' ') && CH(line->end+1) == _T(' '))) + break_type = MD_TEXT_BR; + } + + MD_TEXT(break_type, _T("\n"), 1); + } + + /* Move to the next line. */ + line++; + off = line->beg; + + enforce_hardbreak = 0; + } + } + +abort: + return ret; +} + + +/*************************** + *** Processing Tables *** + ***************************/ + +static void +md_analyze_table_alignment(MD_CTX* ctx, OFF beg, OFF end, MD_ALIGN* align, int n_align) +{ + static const MD_ALIGN align_map[] = { MD_ALIGN_DEFAULT, MD_ALIGN_LEFT, MD_ALIGN_RIGHT, MD_ALIGN_CENTER }; + OFF off = beg; + + while(n_align > 0) { + int index = 0; /* index into align_map[] */ + + while(CH(off) != _T('-')) + off++; + if(off > beg && CH(off-1) == _T(':')) + index |= 1; + while(off < end && CH(off) == _T('-')) + off++; + if(off < end && CH(off) == _T(':')) + index |= 2; + + *align = align_map[index]; + align++; + n_align--; + } + +} + +/* Forward declaration. */ +static int md_process_normal_block_contents(MD_CTX* ctx, const MD_LINE* lines, int n_lines); + +static int +md_process_table_cell(MD_CTX* ctx, MD_BLOCKTYPE cell_type, MD_ALIGN align, OFF beg, OFF end) +{ + MD_LINE line; + MD_BLOCK_TD_DETAIL det; + int ret = 0; + + while(beg < end && ISWHITESPACE(beg)) + beg++; + while(end > beg && ISWHITESPACE(end-1)) + end--; + + det.align = align; + line.beg = beg; + line.end = end; + + MD_ENTER_BLOCK(cell_type, &det); + MD_CHECK(md_process_normal_block_contents(ctx, &line, 1)); + MD_LEAVE_BLOCK(cell_type, &det); + +abort: + return ret; +} + +static int +md_process_table_row(MD_CTX* ctx, MD_BLOCKTYPE cell_type, OFF beg, OFF end, + const MD_ALIGN* align, int col_count) +{ + MD_LINE line = { beg, end }; + OFF* pipe_offs = NULL; + int i, j, n; + int ret = 0; + + /* Break the line into table cells by identifying pipe characters who + * form the cell boundary. */ + MD_CHECK(md_analyze_inlines(ctx, &line, 1, TRUE)); + + /* We have to remember the cell boundaries in local buffer because + * ctx->marks[] shall be reused during cell contents processing. */ + n = ctx->n_table_cell_boundaries; + pipe_offs = (OFF*) malloc(n * sizeof(OFF)); + if(pipe_offs == NULL) { + MD_LOG("malloc() failed."); + ret = -1; + goto abort; + } + for(i = TABLECELLBOUNDARIES.head, j = 0; i >= 0; i = ctx->marks[i].next) { + MD_MARK* mark = &ctx->marks[i]; + pipe_offs[j++] = mark->beg; + } + + /* Process cells. */ + MD_ENTER_BLOCK(MD_BLOCK_TR, NULL); + j = 0; + if(beg < pipe_offs[0] && j < col_count) + MD_CHECK(md_process_table_cell(ctx, cell_type, align[j++], beg, pipe_offs[0])); + for(i = 0; i < n-1 && j < col_count; i++) + MD_CHECK(md_process_table_cell(ctx, cell_type, align[j++], pipe_offs[i]+1, pipe_offs[i+1])); + if(pipe_offs[n-1] < end-1 && j < col_count) + MD_CHECK(md_process_table_cell(ctx, cell_type, align[j++], pipe_offs[n-1]+1, end)); + /* Make sure we call enough table cells even if the current table contains + * too few of them. */ + while(j < col_count) + MD_CHECK(md_process_table_cell(ctx, cell_type, align[j++], 0, 0)); + + MD_LEAVE_BLOCK(MD_BLOCK_TR, NULL); + +abort: + free(pipe_offs); + + /* Free any temporary memory blocks stored within some dummy marks. */ + for(i = PTR_CHAIN.head; i >= 0; i = ctx->marks[i].next) + free(md_mark_get_ptr(ctx, i)); + PTR_CHAIN.head = -1; + PTR_CHAIN.tail = -1; + + return ret; +} + +static int +md_process_table_block_contents(MD_CTX* ctx, int col_count, const MD_LINE* lines, int n_lines) +{ + MD_ALIGN* align; + int i; + int ret = 0; + + /* At least two lines have to be present: The column headers and the line + * with the underlines. */ + MD_ASSERT(n_lines >= 2); + + align = malloc(col_count * sizeof(MD_ALIGN)); + if(align == NULL) { + MD_LOG("malloc() failed."); + ret = -1; + goto abort; + } + + md_analyze_table_alignment(ctx, lines[1].beg, lines[1].end, align, col_count); + + MD_ENTER_BLOCK(MD_BLOCK_THEAD, NULL); + MD_CHECK(md_process_table_row(ctx, MD_BLOCK_TH, + lines[0].beg, lines[0].end, align, col_count)); + MD_LEAVE_BLOCK(MD_BLOCK_THEAD, NULL); + + MD_ENTER_BLOCK(MD_BLOCK_TBODY, NULL); + for(i = 2; i < n_lines; i++) { + MD_CHECK(md_process_table_row(ctx, MD_BLOCK_TD, + lines[i].beg, lines[i].end, align, col_count)); + } + MD_LEAVE_BLOCK(MD_BLOCK_TBODY, NULL); + +abort: + free(align); + return ret; +} + +static int +md_is_table_row(MD_CTX* ctx, OFF beg, OFF* p_end) +{ + MD_LINE line = { beg, beg }; + int i; + int ret = FALSE; + + /* Find end of line. */ + while(line.end < ctx->size && !ISNEWLINE(line.end)) + line.end++; + + MD_CHECK(md_analyze_inlines(ctx, &line, 1, TRUE)); + + if(TABLECELLBOUNDARIES.head >= 0) { + if(p_end != NULL) + *p_end = line.end; + ret = TRUE; + } + +abort: + /* Free any temporary memory blocks stored within some dummy marks. */ + for(i = PTR_CHAIN.head; i >= 0; i = ctx->marks[i].next) + free(md_mark_get_ptr(ctx, i)); + PTR_CHAIN.head = -1; + PTR_CHAIN.tail = -1; + + return ret; +} + + +/************************** + *** Processing Block *** + **************************/ + +#define MD_BLOCK_CONTAINER_OPENER 0x01 +#define MD_BLOCK_CONTAINER_CLOSER 0x02 +#define MD_BLOCK_CONTAINER (MD_BLOCK_CONTAINER_OPENER | MD_BLOCK_CONTAINER_CLOSER) +#define MD_BLOCK_LOOSE_LIST 0x04 + +struct MD_BLOCK_tag { + MD_BLOCKTYPE type : 8; + unsigned flags : 8; + + /* MD_BLOCK_H: Header level (1 - 6) + * MD_BLOCK_CODE: Non-zero if fenced, zero if indented. + * MD_BLOCK_LI: Task mark character (0 if not task list item, 'x', 'X' or ' '). + * MD_BLOCK_TABLE: Column count (as determined by the table underline). + */ + unsigned data : 16; + + /* Leaf blocks: Count of lines (MD_LINE or MD_VERBATIMLINE) on the block. + * MD_BLOCK_LI: Task mark offset in the input doc. + * MD_BLOCK_OL: Start item number. + */ + unsigned n_lines; +}; + +struct MD_CONTAINER_tag { + CHAR ch; + unsigned is_loose : 8; + unsigned is_task : 8; + unsigned start; + unsigned mark_indent; + unsigned contents_indent; + OFF block_byte_off; + OFF task_mark_off; +}; + + +static int +md_process_normal_block_contents(MD_CTX* ctx, const MD_LINE* lines, int n_lines) +{ + int i; + int ret; + + MD_CHECK(md_analyze_inlines(ctx, lines, n_lines, FALSE)); + MD_CHECK(md_process_inlines(ctx, lines, n_lines)); + +abort: + /* Free any temporary memory blocks stored within some dummy marks. */ + for(i = PTR_CHAIN.head; i >= 0; i = ctx->marks[i].next) + free(md_mark_get_ptr(ctx, i)); + PTR_CHAIN.head = -1; + PTR_CHAIN.tail = -1; + + return ret; +} + +static int +md_process_verbatim_block_contents(MD_CTX* ctx, MD_TEXTTYPE text_type, const MD_VERBATIMLINE* lines, int n_lines) +{ + static const CHAR indent_chunk_str[] = _T(" "); + static const SZ indent_chunk_size = SIZEOF_ARRAY(indent_chunk_str) - 1; + + int i; + int ret = 0; + + for(i = 0; i < n_lines; i++) { + const MD_VERBATIMLINE* line = &lines[i]; + int indent = line->indent; + + MD_ASSERT(indent >= 0); + + /* Output code indentation. */ + while(indent > SIZEOF_ARRAY(indent_chunk_str)) { + MD_TEXT(text_type, indent_chunk_str, indent_chunk_size); + indent -= SIZEOF_ARRAY(indent_chunk_str); + } + if(indent > 0) + MD_TEXT(text_type, indent_chunk_str, indent); + + /* Output the code line itself. */ + MD_TEXT_INSECURE(text_type, STR(line->beg), line->end - line->beg); + + /* Enforce end-of-line. */ + MD_TEXT(text_type, _T("\n"), 1); + } + +abort: + return ret; +} + +static int +md_process_code_block_contents(MD_CTX* ctx, int is_fenced, const MD_VERBATIMLINE* lines, int n_lines) +{ + if(is_fenced) { + /* Skip the first line in case of fenced code: It is the fence. + * (Only the starting fence is present due to logic in md_analyze_line().) */ + lines++; + n_lines--; + } else { + /* Ignore blank lines at start/end of indented code block. */ + while(n_lines > 0 && lines[0].beg == lines[0].end) { + lines++; + n_lines--; + } + while(n_lines > 0 && lines[n_lines-1].beg == lines[n_lines-1].end) { + n_lines--; + } + } + + if(n_lines == 0) + return 0; + + return md_process_verbatim_block_contents(ctx, MD_TEXT_CODE, lines, n_lines); +} + +static int +md_setup_fenced_code_detail(MD_CTX* ctx, const MD_BLOCK* block, MD_BLOCK_CODE_DETAIL* det, + MD_ATTRIBUTE_BUILD* info_build, MD_ATTRIBUTE_BUILD* lang_build) +{ + const MD_VERBATIMLINE* fence_line = (const MD_VERBATIMLINE*)(block + 1); + OFF beg = fence_line->beg; + OFF end = fence_line->end; + OFF lang_end; + CHAR fence_ch = CH(fence_line->beg); + int ret = 0; + + /* Skip the fence itself. */ + while(beg < ctx->size && CH(beg) == fence_ch) + beg++; + /* Trim initial spaces. */ + while(beg < ctx->size && CH(beg) == _T(' ')) + beg++; + + /* Trim trailing spaces. */ + while(end > beg && CH(end-1) == _T(' ')) + end--; + + /* Build info string attribute. */ + MD_CHECK(md_build_attribute(ctx, STR(beg), end - beg, 0, &det->info, info_build)); + + /* Build info string attribute. */ + lang_end = beg; + while(lang_end < end && !ISWHITESPACE(lang_end)) + lang_end++; + MD_CHECK(md_build_attribute(ctx, STR(beg), lang_end - beg, 0, &det->lang, lang_build)); + +abort: + return ret; +} + +static int +md_process_leaf_block(MD_CTX* ctx, const MD_BLOCK* block) +{ + union { + MD_BLOCK_H_DETAIL header; + MD_BLOCK_CODE_DETAIL code; + } det; + MD_ATTRIBUTE_BUILD info_build; + MD_ATTRIBUTE_BUILD lang_build; + int is_in_tight_list; + int clean_fence_code_detail = FALSE; + int ret = 0; + + memset(&det, 0, sizeof(det)); + + if(ctx->n_containers == 0) + is_in_tight_list = FALSE; + else + is_in_tight_list = !ctx->containers[ctx->n_containers-1].is_loose; + + switch(block->type) { + case MD_BLOCK_H: + det.header.level = block->data; + break; + + case MD_BLOCK_CODE: + /* For fenced code block, we may need to set the info string. */ + if(block->data != 0) { + memset(&det.code, 0, sizeof(MD_BLOCK_CODE_DETAIL)); + clean_fence_code_detail = TRUE; + MD_CHECK(md_setup_fenced_code_detail(ctx, block, &det.code, &info_build, &lang_build)); + } + break; + + default: + /* Noop. */ + break; + } + + if(!is_in_tight_list || block->type != MD_BLOCK_P) + MD_ENTER_BLOCK(block->type, (void*) &det); + + /* Process the block contents accordingly to is type. */ + switch(block->type) { + case MD_BLOCK_HR: + /* noop */ + break; + + case MD_BLOCK_CODE: + MD_CHECK(md_process_code_block_contents(ctx, (block->data != 0), + (const MD_VERBATIMLINE*)(block + 1), block->n_lines)); + break; + + case MD_BLOCK_HTML: + MD_CHECK(md_process_verbatim_block_contents(ctx, MD_TEXT_HTML, + (const MD_VERBATIMLINE*)(block + 1), block->n_lines)); + break; + + case MD_BLOCK_TABLE: + MD_CHECK(md_process_table_block_contents(ctx, block->data, + (const MD_LINE*)(block + 1), block->n_lines)); + break; + + default: + MD_CHECK(md_process_normal_block_contents(ctx, + (const MD_LINE*)(block + 1), block->n_lines)); + break; + } + + if(!is_in_tight_list || block->type != MD_BLOCK_P) + MD_LEAVE_BLOCK(block->type, (void*) &det); + +abort: + if(clean_fence_code_detail) { + md_free_attribute(ctx, &info_build); + md_free_attribute(ctx, &lang_build); + } + return ret; +} + +static int +md_process_all_blocks(MD_CTX* ctx) +{ + int byte_off = 0; + int ret = 0; + + /* ctx->containers now is not needed for detection of lists and list items + * so we reuse it for tracking what lists are loose or tight. We rely + * on the fact the vector is large enough to hold the deepest nesting + * level of lists. */ + ctx->n_containers = 0; + + while(byte_off < ctx->n_block_bytes) { + MD_BLOCK* block = (MD_BLOCK*)((char*)ctx->block_bytes + byte_off); + union { + MD_BLOCK_UL_DETAIL ul; + MD_BLOCK_OL_DETAIL ol; + MD_BLOCK_LI_DETAIL li; + } det; + + switch(block->type) { + case MD_BLOCK_UL: + det.ul.is_tight = (block->flags & MD_BLOCK_LOOSE_LIST) ? FALSE : TRUE; + det.ul.mark = (CHAR) block->data; + break; + + case MD_BLOCK_OL: + det.ol.start = block->n_lines; + det.ol.is_tight = (block->flags & MD_BLOCK_LOOSE_LIST) ? FALSE : TRUE; + det.ol.mark_delimiter = (CHAR) block->data; + break; + + case MD_BLOCK_LI: + det.li.is_task = (block->data != 0); + det.li.task_mark = (CHAR) block->data; + det.li.task_mark_offset = (OFF) block->n_lines; + break; + + default: + /* noop */ + break; + } + + if(block->flags & MD_BLOCK_CONTAINER) { + if(block->flags & MD_BLOCK_CONTAINER_CLOSER) { + MD_LEAVE_BLOCK(block->type, &det); + + if(block->type == MD_BLOCK_UL || block->type == MD_BLOCK_OL || block->type == MD_BLOCK_QUOTE) + ctx->n_containers--; + } + + if(block->flags & MD_BLOCK_CONTAINER_OPENER) { + MD_ENTER_BLOCK(block->type, &det); + + if(block->type == MD_BLOCK_UL || block->type == MD_BLOCK_OL) { + ctx->containers[ctx->n_containers].is_loose = (block->flags & MD_BLOCK_LOOSE_LIST); + ctx->n_containers++; + } else if(block->type == MD_BLOCK_QUOTE) { + /* This causes that any text in a block quote, even if + * nested inside a tight list item, is wrapped with + *

...

. */ + ctx->containers[ctx->n_containers].is_loose = TRUE; + ctx->n_containers++; + } + } + } else { + MD_CHECK(md_process_leaf_block(ctx, block)); + + if(block->type == MD_BLOCK_CODE || block->type == MD_BLOCK_HTML) + byte_off += block->n_lines * sizeof(MD_VERBATIMLINE); + else + byte_off += block->n_lines * sizeof(MD_LINE); + } + + byte_off += sizeof(MD_BLOCK); + } + + ctx->n_block_bytes = 0; + +abort: + return ret; +} + + +/************************************ + *** Grouping Lines into Blocks *** + ************************************/ + +static void* +md_push_block_bytes(MD_CTX* ctx, int n_bytes) +{ + void* ptr; + + if(ctx->n_block_bytes + n_bytes > ctx->alloc_block_bytes) { + void* new_block_bytes; + + ctx->alloc_block_bytes = (ctx->alloc_block_bytes > 0 ? ctx->alloc_block_bytes * 2 : 512); + new_block_bytes = realloc(ctx->block_bytes, ctx->alloc_block_bytes); + if(new_block_bytes == NULL) { + MD_LOG("realloc() failed."); + return NULL; + } + + /* Fix the ->current_block after the reallocation. */ + if(ctx->current_block != NULL) { + OFF off_current_block = (char*) ctx->current_block - (char*) ctx->block_bytes; + ctx->current_block = (MD_BLOCK*) ((char*) new_block_bytes + off_current_block); + } + + ctx->block_bytes = new_block_bytes; + } + + ptr = (char*)ctx->block_bytes + ctx->n_block_bytes; + ctx->n_block_bytes += n_bytes; + return ptr; +} + +static int +md_start_new_block(MD_CTX* ctx, const MD_LINE_ANALYSIS* line) +{ + MD_BLOCK* block; + + MD_ASSERT(ctx->current_block == NULL); + + block = (MD_BLOCK*) md_push_block_bytes(ctx, sizeof(MD_BLOCK)); + if(block == NULL) + return -1; + + switch(line->type) { + case MD_LINE_HR: + block->type = MD_BLOCK_HR; + break; + + case MD_LINE_ATXHEADER: + case MD_LINE_SETEXTHEADER: + block->type = MD_BLOCK_H; + break; + + case MD_LINE_FENCEDCODE: + case MD_LINE_INDENTEDCODE: + block->type = MD_BLOCK_CODE; + break; + + case MD_LINE_TEXT: + block->type = MD_BLOCK_P; + break; + + case MD_LINE_HTML: + block->type = MD_BLOCK_HTML; + break; + + case MD_LINE_BLANK: + case MD_LINE_SETEXTUNDERLINE: + case MD_LINE_TABLEUNDERLINE: + default: + MD_UNREACHABLE(); + break; + } + + block->flags = 0; + block->data = line->data; + block->n_lines = 0; + + ctx->current_block = block; + return 0; +} + +/* Eat from start of current (textual) block any reference definitions and + * remember them so we can resolve any links referring to them. + * + * (Reference definitions can only be at start of it as they cannot break + * a paragraph.) + */ +static int +md_consume_link_reference_definitions(MD_CTX* ctx) +{ + MD_LINE* lines = (MD_LINE*) (ctx->current_block + 1); + int n_lines = ctx->current_block->n_lines; + int n = 0; + + /* Compute how many lines at the start of the block form one or more + * reference definitions. */ + while(n < n_lines) { + int n_link_ref_lines; + + n_link_ref_lines = md_is_link_reference_definition(ctx, + lines + n, n_lines - n); + /* Not a reference definition? */ + if(n_link_ref_lines == 0) + break; + + /* We fail if it is the ref. def. but it could not be stored due + * a memory allocation error. */ + if(n_link_ref_lines < 0) + return -1; + + n += n_link_ref_lines; + } + + /* If there was at least one reference definition, we need to remove + * its lines from the block, or perhaps even the whole block. */ + if(n > 0) { + if(n == n_lines) { + /* Remove complete block. */ + ctx->n_block_bytes -= n * sizeof(MD_LINE); + ctx->n_block_bytes -= sizeof(MD_BLOCK); + } else { + /* Remove just some initial lines from the block. */ + memmove(lines, lines + n, (n_lines - n) * sizeof(MD_LINE)); + ctx->current_block->n_lines -= n; + ctx->n_block_bytes -= n * sizeof(MD_LINE); + } + } + + return 0; +} + +static int +md_end_current_block(MD_CTX* ctx) +{ + int ret = 0; + + if(ctx->current_block == NULL) + return ret; + + /* Check whether there is a reference definition. (We do this here instead + * of in md_analyze_line() because reference definition can take multiple + * lines.) */ + if(ctx->current_block->type == MD_BLOCK_P) { + MD_LINE* lines = (MD_LINE*) (ctx->current_block + 1); + if(CH(lines[0].beg) == _T('[')) + MD_CHECK(md_consume_link_reference_definitions(ctx)); + } + + /* Mark we are not building any block anymore. */ + ctx->current_block = NULL; + +abort: + return ret; +} + +static int +md_add_line_into_current_block(MD_CTX* ctx, const MD_LINE_ANALYSIS* analysis) +{ + MD_ASSERT(ctx->current_block != NULL); + + if(ctx->current_block->type == MD_BLOCK_CODE || ctx->current_block->type == MD_BLOCK_HTML) { + MD_VERBATIMLINE* line; + + line = (MD_VERBATIMLINE*) md_push_block_bytes(ctx, sizeof(MD_VERBATIMLINE)); + if(line == NULL) + return -1; + + line->indent = analysis->indent; + line->beg = analysis->beg; + line->end = analysis->end; + } else { + MD_LINE* line; + + line = (MD_LINE*) md_push_block_bytes(ctx, sizeof(MD_LINE)); + if(line == NULL) + return -1; + + line->beg = analysis->beg; + line->end = analysis->end; + } + ctx->current_block->n_lines++; + + return 0; +} + +static int +md_push_container_bytes(MD_CTX* ctx, MD_BLOCKTYPE type, unsigned start, + unsigned data, unsigned flags) +{ + MD_BLOCK* block; + int ret = 0; + + MD_CHECK(md_end_current_block(ctx)); + + block = (MD_BLOCK*) md_push_block_bytes(ctx, sizeof(MD_BLOCK)); + if(block == NULL) + return -1; + + block->type = type; + block->flags = flags; + block->data = data; + block->n_lines = start; + +abort: + return ret; +} + + + +/*********************** + *** Line Analysis *** + ***********************/ + +static int +md_is_hr_line(MD_CTX* ctx, OFF beg, OFF* p_end) +{ + OFF off = beg + 1; + int n = 1; + + while(off < ctx->size && (CH(off) == CH(beg) || CH(off) == _T(' ') || CH(off) == _T('\t'))) { + if(CH(off) == CH(beg)) + n++; + off++; + } + + if(n < 3) + return FALSE; + + /* Nothing else can be present on the line. */ + if(off < ctx->size && !ISNEWLINE(off)) + return FALSE; + + *p_end = off; + return TRUE; +} + +static int +md_is_atxheader_line(MD_CTX* ctx, OFF beg, OFF* p_beg, OFF* p_end, unsigned* p_level) +{ + int n; + OFF off = beg + 1; + + while(off < ctx->size && CH(off) == _T('#') && off - beg < 7) + off++; + n = off - beg; + + if(n > 6) + return FALSE; + *p_level = n; + + if(!(ctx->parser.flags & MD_FLAG_PERMISSIVEATXHEADERS) && off < ctx->size && + CH(off) != _T(' ') && CH(off) != _T('\t') && !ISNEWLINE(off)) + return FALSE; + + while(off < ctx->size && CH(off) == _T(' ')) + off++; + *p_beg = off; + *p_end = off; + return TRUE; +} + +static int +md_is_setext_underline(MD_CTX* ctx, OFF beg, OFF* p_end, unsigned* p_level) +{ + OFF off = beg + 1; + + while(off < ctx->size && CH(off) == CH(beg)) + off++; + + while(off < ctx->size && CH(off) == _T(' ')) + off++; + + /* Optionally, space(s) can follow. */ + while(off < ctx->size && CH(off) == _T(' ')) + off++; + + /* But nothing more is allowed on the line. */ + if(off < ctx->size && !ISNEWLINE(off)) + return FALSE; + + *p_level = (CH(beg) == _T('=') ? 1 : 2); + *p_end = off; + return TRUE; +} + +static int +md_is_table_underline(MD_CTX* ctx, OFF beg, OFF* p_end, unsigned* p_col_count) +{ + OFF off = beg; + int found_pipe = FALSE; + unsigned col_count = 0; + + if(off < ctx->size && CH(off) == _T('|')) { + found_pipe = TRUE; + off++; + while(off < ctx->size && ISWHITESPACE(off)) + off++; + } + + while(1) { + OFF cell_beg; + int delimited = FALSE; + + /* Cell underline ("-----", ":----", "----:" or ":----:") */ + cell_beg = off; + if(off < ctx->size && CH(off) == _T(':')) + off++; + while(off < ctx->size && CH(off) == _T('-')) + off++; + if(off < ctx->size && CH(off) == _T(':')) + off++; + if(off - cell_beg < 3) + return FALSE; + + col_count++; + + /* Pipe delimiter (optional at the end of line). */ + while(off < ctx->size && ISWHITESPACE(off)) + off++; + if(off < ctx->size && CH(off) == _T('|')) { + delimited = TRUE; + found_pipe = TRUE; + off++; + while(off < ctx->size && ISWHITESPACE(off)) + off++; + } + + /* Success, if we reach end of line. */ + if(off >= ctx->size || ISNEWLINE(off)) + break; + + if(!delimited) + return FALSE; + } + + if(!found_pipe) + return FALSE; + + *p_end = off; + *p_col_count = col_count; + return TRUE; +} + +static int +md_is_opening_code_fence(MD_CTX* ctx, OFF beg, OFF* p_end) +{ + OFF off = beg; + + while(off < ctx->size && CH(off) == CH(beg)) + off++; + + /* Fence must have at least three characters. */ + if(off - beg < 3) + return FALSE; + + ctx->code_fence_length = off - beg; + + /* Optionally, space(s) can follow. */ + while(off < ctx->size && CH(off) == _T(' ')) + off++; + + /* Optionally, an info string can follow. It must not contain '`'. */ + while(off < ctx->size && CH(off) != _T('`') && !ISNEWLINE(off)) + off++; + if(off < ctx->size && !ISNEWLINE(off)) + return FALSE; + + *p_end = off; + return TRUE; +} + +static int +md_is_closing_code_fence(MD_CTX* ctx, CHAR ch, OFF beg, OFF* p_end) +{ + OFF off = beg; + int ret = FALSE; + + /* Closing fence must have at least the same length and use same char as + * opening one. */ + while(off < ctx->size && CH(off) == ch) + off++; + if(off - beg < ctx->code_fence_length) + goto out; + + /* Optionally, space(s) can follow */ + while(off < ctx->size && CH(off) == _T(' ')) + off++; + + /* But nothing more is allowed on the line. */ + if(off < ctx->size && !ISNEWLINE(off)) + goto out; + + ret = TRUE; + +out: + /* Note we set *p_end even on failure: If we are not closing fence, caller + * would eat the line anyway without any parsing. */ + *p_end = off; + return ret; +} + +/* Returns type of the raw HTML block, or FALSE if it is not HTML block. + * (Refer to CommonMark specification for details about the types.) + */ +static int +md_is_html_block_start_condition(MD_CTX* ctx, OFF beg) +{ + typedef struct TAG_tag TAG; + struct TAG_tag { + const CHAR* name; + unsigned len : 8; + }; + + /* Type 6 is started by a long list of allowed tags. We use two-level + * tree to speed-up the search. */ +#ifdef X + #undef X +#endif +#define X(name) { _T(name), sizeof(name)-1 } +#define Xend { NULL, 0 } + static const TAG t1[] = { X("script"), X("pre"), X("style"), Xend }; + + static const TAG a6[] = { X("address"), X("article"), X("aside"), Xend }; + static const TAG b6[] = { X("base"), X("basefont"), X("blockquote"), X("body"), Xend }; + static const TAG c6[] = { X("caption"), X("center"), X("col"), X("colgroup"), Xend }; + static const TAG d6[] = { X("dd"), X("details"), X("dialog"), X("dir"), + X("div"), X("dl"), X("dt"), Xend }; + static const TAG f6[] = { X("fieldset"), X("figcaption"), X("figure"), X("footer"), + X("form"), X("frame"), X("frameset"), Xend }; + static const TAG h6[] = { X("h1"), X("head"), X("header"), X("hr"), X("html"), Xend }; + static const TAG i6[] = { X("iframe"), Xend }; + static const TAG l6[] = { X("legend"), X("li"), X("link"), Xend }; + static const TAG m6[] = { X("main"), X("menu"), X("menuitem"), X("meta"), Xend }; + static const TAG n6[] = { X("nav"), X("noframes"), Xend }; + static const TAG o6[] = { X("ol"), X("optgroup"), X("option"), Xend }; + static const TAG p6[] = { X("p"), X("param"), Xend }; + static const TAG s6[] = { X("section"), X("source"), X("summary"), Xend }; + static const TAG t6[] = { X("table"), X("tbody"), X("td"), X("tfoot"), X("th"), + X("thead"), X("title"), X("tr"), X("track"), Xend }; + static const TAG u6[] = { X("ul"), Xend }; + static const TAG xx[] = { Xend }; +#undef X + + static const TAG* map6[26] = { + a6, b6, c6, d6, xx, f6, xx, h6, i6, xx, xx, l6, m6, + n6, o6, p6, xx, xx, s6, t6, u6, xx, xx, xx, xx, xx + }; + OFF off = beg + 1; + int i; + + /* Check for type 1: size) { + if(md_ascii_case_eq(STR(off), t1[i].name, t1[i].len)) + return 1; + } + } + + /* Check for type 2: "), 3, p_end) ? 2 : FALSE); + + case 3: + return (md_line_contains(ctx, beg, _T("?>"), 2, p_end) ? 3 : FALSE); + + case 4: + return (md_line_contains(ctx, beg, _T(">"), 1, p_end) ? 4 : FALSE); + + case 5: + return (md_line_contains(ctx, beg, _T("]]>"), 3, p_end) ? 5 : FALSE); + + case 6: /* Pass through */ + case 7: + *p_end = beg; + return (ISNEWLINE(beg) ? ctx->html_block_type : FALSE); + + default: + MD_UNREACHABLE(); + } +} + + +static int +md_is_container_compatible(const MD_CONTAINER* pivot, const MD_CONTAINER* container) +{ + /* Block quote has no "items" like lists. */ + if(container->ch == _T('>')) + return FALSE; + + if(container->ch != pivot->ch) + return FALSE; + if(container->mark_indent > pivot->contents_indent) + return FALSE; + + return TRUE; +} + +static int +md_push_container(MD_CTX* ctx, const MD_CONTAINER* container) +{ + if(ctx->n_containers >= ctx->alloc_containers) { + MD_CONTAINER* new_containers; + + ctx->alloc_containers = (ctx->alloc_containers > 0 ? ctx->alloc_containers * 2 : 16); + new_containers = realloc(ctx->containers, ctx->alloc_containers * sizeof(MD_CONTAINER)); + if(new_containers == NULL) { + MD_LOG("realloc() failed."); + return -1; + } + + ctx->containers = new_containers; + } + + memcpy(&ctx->containers[ctx->n_containers++], container, sizeof(MD_CONTAINER)); + return 0; +} + +static int +md_enter_child_containers(MD_CTX* ctx, int n_children, unsigned data) +{ + int i; + int ret = 0; + + for(i = ctx->n_containers - n_children; i < ctx->n_containers; i++) { + MD_CONTAINER* c = &ctx->containers[i]; + int is_ordered_list = FALSE; + + switch(c->ch) { + case _T(')'): + case _T('.'): + is_ordered_list = TRUE; + /* Pass through */ + + case _T('-'): + case _T('+'): + case _T('*'): + /* Remember offset in ctx->block_bytes so we can revisit the + * block if we detect it is a loose list. */ + md_end_current_block(ctx); + c->block_byte_off = ctx->n_block_bytes; + + MD_CHECK(md_push_container_bytes(ctx, + (is_ordered_list ? MD_BLOCK_OL : MD_BLOCK_UL), + c->start, data, MD_BLOCK_CONTAINER_OPENER)); + MD_CHECK(md_push_container_bytes(ctx, MD_BLOCK_LI, + c->task_mark_off, + (c->is_task ? CH(c->task_mark_off) : 0), + MD_BLOCK_CONTAINER_OPENER)); + break; + + case _T('>'): + MD_CHECK(md_push_container_bytes(ctx, MD_BLOCK_QUOTE, 0, 0, MD_BLOCK_CONTAINER_OPENER)); + break; + + default: + MD_UNREACHABLE(); + break; + } + } + +abort: + return ret; +} + +static int +md_leave_child_containers(MD_CTX* ctx, int n_keep) +{ + int ret = 0; + + while(ctx->n_containers > n_keep) { + MD_CONTAINER* c = &ctx->containers[ctx->n_containers-1]; + int is_ordered_list = FALSE; + + switch(c->ch) { + case _T(')'): + case _T('.'): + is_ordered_list = TRUE; + /* Pass through */ + + case _T('-'): + case _T('+'): + case _T('*'): + MD_CHECK(md_push_container_bytes(ctx, MD_BLOCK_LI, + c->task_mark_off, (c->is_task ? CH(c->task_mark_off) : 0), + MD_BLOCK_CONTAINER_CLOSER)); + MD_CHECK(md_push_container_bytes(ctx, + (is_ordered_list ? MD_BLOCK_OL : MD_BLOCK_UL), 0, + c->ch, MD_BLOCK_CONTAINER_CLOSER)); + break; + + case _T('>'): + MD_CHECK(md_push_container_bytes(ctx, MD_BLOCK_QUOTE, 0, + 0, MD_BLOCK_CONTAINER_CLOSER)); + break; + + default: + MD_UNREACHABLE(); + break; + } + + ctx->n_containers--; + } + +abort: + return ret; +} + +static int +md_is_container_mark(MD_CTX* ctx, unsigned indent, OFF beg, OFF* p_end, MD_CONTAINER* p_container) +{ + OFF off = beg; + OFF max_end; + + /* Check for block quote mark. */ + if(off < ctx->size && CH(off) == _T('>')) { + off++; + p_container->ch = _T('>'); + p_container->is_loose = FALSE; + p_container->is_task = FALSE; + p_container->mark_indent = indent; + p_container->contents_indent = indent + 1; + *p_end = off; + return TRUE; + } + + /* Check for list item bullet mark. */ + if(off+1 < ctx->size && ISANYOF(off, _T("-+*")) && (ISBLANK(off+1) || ISNEWLINE(off+1))) { + p_container->ch = CH(off); + p_container->is_loose = FALSE; + p_container->is_task = FALSE; + p_container->mark_indent = indent; + p_container->contents_indent = indent + 1; + *p_end = off + 1; + return TRUE; + } + + /* Check for ordered list item marks. */ + max_end = off + 9; + if(max_end > ctx->size) + max_end = ctx->size; + p_container->start = 0; + while(off < max_end && ISDIGIT(off)) { + p_container->start = p_container->start * 10 + CH(off) - _T('0'); + off++; + } + if(off+1 < ctx->size && (CH(off) == _T('.') || CH(off) == _T(')')) && (ISBLANK(off+1) || ISNEWLINE(off+1))) { + p_container->ch = CH(off); + p_container->is_loose = FALSE; + p_container->is_task = FALSE; + p_container->mark_indent = indent; + p_container->contents_indent = indent + off - beg + 1; + *p_end = off + 1; + return TRUE; + } + + return FALSE; +} + +static unsigned +md_line_indentation(MD_CTX* ctx, unsigned total_indent, OFF beg, OFF* p_end) +{ + OFF off = beg; + unsigned indent = total_indent; + + while(off < ctx->size && ISBLANK(off)) { + if(CH(off) == _T('\t')) + indent = (indent + 4) & ~3; + else + indent++; + off++; + } + + *p_end = off; + return indent - total_indent; +} + +static const MD_LINE_ANALYSIS md_dummy_blank_line = { MD_LINE_BLANK, 0 }; + +/* Analyze type of the line and find some its properties. This serves as a + * main input for determining type and boundaries of a block. */ +static int +md_analyze_line(MD_CTX* ctx, OFF beg, OFF* p_end, + const MD_LINE_ANALYSIS* pivot_line, MD_LINE_ANALYSIS* line) +{ + unsigned total_indent = 0; + int n_parents = 0; + int n_brothers = 0; + int n_children = 0; + MD_CONTAINER container = { 0 }; + int prev_line_has_list_loosening_effect = ctx->last_line_has_list_loosening_effect; + OFF off = beg; + int ret = 0; + + line->indent = md_line_indentation(ctx, total_indent, off, &off); + total_indent += line->indent; + line->beg = off; + + /* Given the indentation and block quote marks '>', determine how many of + * the current containers are our parents. */ + while(n_parents < ctx->n_containers) { + MD_CONTAINER* c = &ctx->containers[n_parents]; + + if(c->ch == _T('>') && line->indent < ctx->code_indent_offset && + off < ctx->size && CH(off) == _T('>')) + { + /* Block quote mark. */ + off++; + total_indent++; + line->indent = md_line_indentation(ctx, total_indent, off, &off); + total_indent += line->indent; + + /* The optional 1st space after '>' is part of the block quote mark. */ + if(line->indent > 0) + line->indent--; + + line->beg = off; + } else if(c->ch != _T('>') && line->indent >= c->contents_indent) { + /* List. */ + line->indent -= c->contents_indent; + } else { + break; + } + + n_parents++; + } + +redo: + /* Check whether we are fenced code continuation. */ + if(pivot_line->type == MD_LINE_FENCEDCODE) { + line->beg = off; + + /* We are another MD_LINE_FENCEDCODE unless we are closing fence + * which we transform into MD_LINE_BLANK. */ + if(line->indent < ctx->code_indent_offset) { + if(md_is_closing_code_fence(ctx, CH(pivot_line->beg), off, &off)) { + line->type = MD_LINE_BLANK; + ctx->last_line_has_list_loosening_effect = FALSE; + goto done; + } + } + + if(off >= ctx->size || ISNEWLINE(off)) { + /* Blank line does not need any real indentation to be nested inside + * a list. */ + if(n_brothers + n_children == 0) { + while(n_parents < ctx->n_containers && ctx->containers[n_parents].ch != _T('>')) + n_parents++; + } + } + + /* Change indentation accordingly to the initial code fence. */ + if(n_parents == ctx->n_containers) { + if(line->indent > pivot_line->indent) + line->indent -= pivot_line->indent; + else + line->indent = 0; + + line->type = MD_LINE_FENCEDCODE; + goto done; + } + } + + /* Check whether we are HTML block continuation. */ + if(pivot_line->type == MD_LINE_HTML && ctx->html_block_type > 0) { + int html_block_type; + + html_block_type = md_is_html_block_end_condition(ctx, off, &off); + if(html_block_type > 0) { + MD_ASSERT(html_block_type == ctx->html_block_type); + + /* Make sure this is the last line of the block. */ + ctx->html_block_type = 0; + + /* Some end conditions serve as blank lines at the same time. */ + if(html_block_type == 6 || html_block_type == 7) { + line->type = MD_LINE_BLANK; + line->indent = 0; + goto done; + } + } + + if(n_parents == ctx->n_containers) { + line->type = MD_LINE_HTML; + goto done; + } + } + + /* Check for blank line. */ + if(off >= ctx->size || ISNEWLINE(off)) { + /* Blank line does not need any real indentation to be nested inside + * a list. */ + if(n_brothers + n_children == 0) { + while(n_parents < ctx->n_containers && ctx->containers[n_parents].ch != _T('>')) + n_parents++; + } + + if(pivot_line->type == MD_LINE_INDENTEDCODE && n_parents == ctx->n_containers) { + line->type = MD_LINE_INDENTEDCODE; + if(line->indent > ctx->code_indent_offset) + line->indent -= ctx->code_indent_offset; + else + line->indent = 0; + ctx->last_line_has_list_loosening_effect = FALSE; + } else { + line->type = MD_LINE_BLANK; + ctx->last_line_has_list_loosening_effect = (n_parents > 0 && + n_brothers + n_children == 0 && + ctx->containers[n_parents-1].ch != _T('>')); + +#if 1 + /* See https://github.com/mity/md4c/issues/6 + * + * This ugly checking tests we are in (yet empty) list item but not + * its very first line (with the list item mark). + * + * If we are such blank line, then any following non-blank line + * which would be part of this list item actually ends the list + * because "a list item can begin with at most one blank line." + */ + if(n_parents > 0 && ctx->containers[n_parents-1].ch != _T('>') && + n_brothers + n_children == 0 && ctx->current_block == NULL && + ctx->n_block_bytes > sizeof(MD_BLOCK)) + { + MD_BLOCK* top_block = (MD_BLOCK*) ((char*)ctx->block_bytes + ctx->n_block_bytes - sizeof(MD_BLOCK)); + if(top_block->type == MD_BLOCK_LI) + ctx->last_list_item_starts_with_two_blank_lines = TRUE; + } +#endif + } + goto done_on_eol; + } else { +#if 1 + /* This is 2nd half of the hack. If the flag is set (that is there + * were 2nd blank line at the start of the list item) and we would also + * belonging to such list item, then interrupt the list. */ + ctx->last_line_has_list_loosening_effect = FALSE; + if(ctx->last_list_item_starts_with_two_blank_lines) { + if(n_parents > 0 && ctx->containers[n_parents-1].ch != _T('>') && + n_brothers + n_children == 0 && ctx->current_block == NULL && + ctx->n_block_bytes > sizeof(MD_BLOCK)) + { + MD_BLOCK* top_block = (MD_BLOCK*) ((char*)ctx->block_bytes + ctx->n_block_bytes - sizeof(MD_BLOCK)); + if(top_block->type == MD_BLOCK_LI) + n_parents--; + } + + ctx->last_list_item_starts_with_two_blank_lines = FALSE; + } +#endif + } + + /* Check whether we are Setext underline. */ + if(line->indent < ctx->code_indent_offset && pivot_line->type == MD_LINE_TEXT + && (CH(off) == _T('=') || CH(off) == _T('-')) + && (n_parents == ctx->n_containers)) + { + unsigned level; + + if(md_is_setext_underline(ctx, off, &off, &level)) { + line->type = MD_LINE_SETEXTUNDERLINE; + line->data = level; + goto done; + } + } + + /* Check for thematic break line. */ + if(line->indent < ctx->code_indent_offset && ISANYOF(off, _T("-_*"))) { + if(md_is_hr_line(ctx, off, &off)) { + line->type = MD_LINE_HR; + goto done; + } + } + + /* Check for "brother" container. I.e. whether we are another list item + * in already started list. */ + if(n_parents < ctx->n_containers && n_brothers + n_children == 0) { + OFF tmp; + + if(md_is_container_mark(ctx, line->indent, off, &tmp, &container) && + md_is_container_compatible(&ctx->containers[n_parents], &container)) + { + pivot_line = &md_dummy_blank_line; + + off = tmp; + + total_indent += container.contents_indent - container.mark_indent; + line->indent = md_line_indentation(ctx, total_indent, off, &off); + total_indent += line->indent; + line->beg = off; + + /* Some of the following whitespace actually still belongs to the mark. */ + if(off >= ctx->size || ISNEWLINE(off)) { + container.contents_indent++; + } else if(line->indent <= ctx->code_indent_offset) { + container.contents_indent += line->indent; + line->indent = 0; + } else { + container.contents_indent += 1; + line->indent--; + } + + ctx->containers[n_parents].mark_indent = container.mark_indent; + ctx->containers[n_parents].contents_indent = container.contents_indent; + + n_brothers++; + goto redo; + } + } + + /* Check for indented code. + * Note indented code block cannot interrupt a paragraph. */ + if(line->indent >= ctx->code_indent_offset && + (pivot_line->type == MD_LINE_BLANK || pivot_line->type == MD_LINE_INDENTEDCODE)) + { + line->type = MD_LINE_INDENTEDCODE; + MD_ASSERT(line->indent >= ctx->code_indent_offset); + line->indent -= ctx->code_indent_offset; + line->data = 0; + goto done; + } + + /* Check for start of a new container block. */ + if(line->indent < ctx->code_indent_offset && + md_is_container_mark(ctx, line->indent, off, &off, &container)) + { + if(pivot_line->type == MD_LINE_TEXT && n_parents == ctx->n_containers && + (off >= ctx->size || ISNEWLINE(off))) + { + /* Noop. List mark followed by a blank line cannot interrupt a paragraph. */ + } else if(pivot_line->type == MD_LINE_TEXT && n_parents == ctx->n_containers && + (container.ch == _T('.') || container.ch == _T(')')) && container.start != 1) + { + /* Noop. Ordered list cannot interrupt a paragraph unless the start index is 1. */ + } else { + total_indent += container.contents_indent - container.mark_indent; + line->indent = md_line_indentation(ctx, total_indent, off, &off); + total_indent += line->indent; + + line->beg = off; + line->data = container.ch; + + /* Some of the following whitespace actually still belongs to the mark. */ + if(off >= ctx->size || ISNEWLINE(off)) { + container.contents_indent++; + } else if(line->indent <= ctx->code_indent_offset) { + container.contents_indent += line->indent; + line->indent = 0; + } else { + container.contents_indent += 1; + line->indent--; + } + + if(n_brothers + n_children == 0) + pivot_line = &md_dummy_blank_line; + + if(n_children == 0) + MD_CHECK(md_leave_child_containers(ctx, n_parents + n_brothers)); + + n_children++; + MD_CHECK(md_push_container(ctx, &container)); + goto redo; + } + } + + /* Check whether we are table continuation. */ + if(pivot_line->type == MD_LINE_TABLE && md_is_table_row(ctx, off, &off) && + n_parents == ctx->n_containers) + { + line->type = MD_LINE_TABLE; + goto done; + } + + /* Check for ATX header. */ + if(line->indent < ctx->code_indent_offset && CH(off) == _T('#')) { + unsigned level; + + if(md_is_atxheader_line(ctx, off, &line->beg, &off, &level)) { + line->type = MD_LINE_ATXHEADER; + line->data = level; + goto done; + } + } + + /* Check whether we are starting code fence. */ + if(CH(off) == _T('`') || CH(off) == _T('~')) { + if(md_is_opening_code_fence(ctx, off, &off)) { + line->type = MD_LINE_FENCEDCODE; + line->data = 1; + goto done; + } + } + + /* Check for start of raw HTML block. */ + if(CH(off) == _T('<') && !(ctx->parser.flags & MD_FLAG_NOHTMLBLOCKS)) + { + ctx->html_block_type = md_is_html_block_start_condition(ctx, off); + + /* HTML block type 7 cannot interrupt paragraph. */ + if(ctx->html_block_type == 7 && pivot_line->type == MD_LINE_TEXT) + ctx->html_block_type = 0; + + if(ctx->html_block_type > 0) { + /* The line itself also may immediately close the block. */ + if(md_is_html_block_end_condition(ctx, off, &off) == ctx->html_block_type) { + /* Make sure this is the last line of the block. */ + ctx->html_block_type = 0; + } + + line->type = MD_LINE_HTML; + goto done; + } + } + + /* Check for table underline. */ + if((ctx->parser.flags & MD_FLAG_TABLES) && pivot_line->type == MD_LINE_TEXT && + (CH(off) == _T('|') || CH(off) == _T('-') || CH(off) == _T(':')) && + n_parents == ctx->n_containers) + { + unsigned col_count; + + if(ctx->current_block != NULL && ctx->current_block->n_lines == 1 && + md_is_table_underline(ctx, off, &off, &col_count) && + md_is_table_row(ctx, pivot_line->beg, NULL)) + { + line->data = col_count; + line->type = MD_LINE_TABLEUNDERLINE; + goto done; + } + } + + /* By default, we are normal text line. */ + line->type = MD_LINE_TEXT; + if(pivot_line->type == MD_LINE_TEXT && n_brothers + n_children == 0) { + /* Lazy continuation. */ + n_parents = ctx->n_containers; + } + + /* Check for task mark. */ + if((ctx->parser.flags & MD_FLAG_TASKLISTS) && n_brothers + n_children > 0 && + ISANYOF_(ctx->containers[ctx->n_containers-1].ch, _T("-+*.)"))) + { + OFF tmp = off; + + while(tmp < ctx->size && tmp < off + 3 && ISBLANK(tmp)) + tmp++; + if(tmp + 2 < ctx->size && CH(tmp) == _T('[') && + ISANYOF(tmp+1, _T("xX ")) && CH(tmp+2) == _T(']') && + (tmp + 3 == ctx->size || ISBLANK(tmp+3) || ISNEWLINE(tmp+3))) + { + MD_CONTAINER* task_container = (n_children > 0 ? &ctx->containers[ctx->n_containers-1] : &container); + task_container->is_task = TRUE; + task_container->task_mark_off = tmp + 1; + off = tmp + 3; + while(ISWHITESPACE(off)) + off++; + line->beg = off; + } + } + +done: + /* Scan for end of the line. + * + * Note this is bottleneck of this function as we itereate over (almost) + * all line contents after some initial line indentation. To optimize, we + * try to eat multiple chars in every loop iteration. + * + * (Measured ~6% performance boost of md2html with this optimization for + * normal kind of input.) + */ + while(off + 4 < ctx->size && !ISNEWLINE(off+0) && !ISNEWLINE(off+1) + && !ISNEWLINE(off+2) && !ISNEWLINE(off+3)) + off += 4; + while(off < ctx->size && !ISNEWLINE(off)) + off++; + +done_on_eol: + /* Set end of the line. */ + line->end = off; + + /* But for ATX header, we should exclude the optional trailing mark. */ + if(line->type == MD_LINE_ATXHEADER) { + OFF tmp = line->end; + while(tmp > line->beg && CH(tmp-1) == _T(' ')) + tmp--; + while(tmp > line->beg && CH(tmp-1) == _T('#')) + tmp--; + if(tmp == line->beg || CH(tmp-1) == _T(' ') || (ctx->parser.flags & MD_FLAG_PERMISSIVEATXHEADERS)) + line->end = tmp; + } + + /* Trim trailing spaces. */ + if(line->type != MD_LINE_INDENTEDCODE && line->type != MD_LINE_FENCEDCODE) { + while(line->end > line->beg && CH(line->end-1) == _T(' ')) + line->end--; + } + + /* Eat also the new line. */ + if(off < ctx->size && CH(off) == _T('\r')) + off++; + if(off < ctx->size && CH(off) == _T('\n')) + off++; + + *p_end = off; + + /* If we belong to a list after seeing a blank line, the list is loose. */ + if(prev_line_has_list_loosening_effect && line->type != MD_LINE_BLANK && n_parents + n_brothers > 0) { + MD_CONTAINER* c = &ctx->containers[n_parents + n_brothers - 1]; + if(c->ch != _T('>')) { + MD_BLOCK* block = (MD_BLOCK*) (((char*)ctx->block_bytes) + c->block_byte_off); + block->flags |= MD_BLOCK_LOOSE_LIST; + } + } + + /* Leave any containers we are not part of anymore. */ + if(n_children == 0 && n_parents + n_brothers < ctx->n_containers) + MD_CHECK(md_leave_child_containers(ctx, n_parents + n_brothers)); + + /* Enter any container we found a mark for. */ + if(n_brothers > 0) { + MD_ASSERT(n_brothers == 1); + MD_CHECK(md_push_container_bytes(ctx, MD_BLOCK_LI, + ctx->containers[n_parents].task_mark_off, + (ctx->containers[n_parents].is_task ? CH(ctx->containers[n_parents].task_mark_off) : 0), + MD_BLOCK_CONTAINER_CLOSER)); + MD_CHECK(md_push_container_bytes(ctx, MD_BLOCK_LI, + container.task_mark_off, + (container.is_task ? CH(container.task_mark_off) : 0), + MD_BLOCK_CONTAINER_OPENER)); + ctx->containers[n_parents].is_task = container.is_task; + ctx->containers[n_parents].task_mark_off = container.task_mark_off; + } + + if(n_children > 0) + MD_CHECK(md_enter_child_containers(ctx, n_children, line->data)); + +abort: + return ret; +} + +static int +md_process_line(MD_CTX* ctx, const MD_LINE_ANALYSIS** p_pivot_line, const MD_LINE_ANALYSIS* line) +{ + const MD_LINE_ANALYSIS* pivot_line = *p_pivot_line; + int ret = 0; + + /* Blank line ends current leaf block. */ + if(line->type == MD_LINE_BLANK) { + MD_CHECK(md_end_current_block(ctx)); + *p_pivot_line = &md_dummy_blank_line; + return 0; + } + + /* Some line types form block on their own. */ + if(line->type == MD_LINE_HR || line->type == MD_LINE_ATXHEADER) { + MD_CHECK(md_end_current_block(ctx)); + + /* Add our single-line block. */ + MD_CHECK(md_start_new_block(ctx, line)); + MD_CHECK(md_add_line_into_current_block(ctx, line)); + MD_CHECK(md_end_current_block(ctx)); + *p_pivot_line = &md_dummy_blank_line; + return 0; + } + + /* MD_LINE_SETEXTUNDERLINE changes meaning of the current block and ends it. */ + if(line->type == MD_LINE_SETEXTUNDERLINE) { + MD_ASSERT(ctx->current_block != NULL); + ctx->current_block->type = MD_BLOCK_H; + ctx->current_block->data = line->data; + MD_CHECK(md_end_current_block(ctx)); + *p_pivot_line = &md_dummy_blank_line; + return 0; + } + + /* MD_LINE_TABLEUNDERLINE changes meaning of the current block. */ + if(line->type == MD_LINE_TABLEUNDERLINE) { + MD_ASSERT(ctx->current_block != NULL); + MD_ASSERT(ctx->current_block->n_lines == 1); + ctx->current_block->type = MD_BLOCK_TABLE; + ctx->current_block->data = line->data; + MD_ASSERT(pivot_line != &md_dummy_blank_line); + ((MD_LINE_ANALYSIS*)pivot_line)->type = MD_LINE_TABLE; + MD_CHECK(md_add_line_into_current_block(ctx, line)); + return 0; + } + + /* The current block also ends if the line has different type. */ + if(line->type != pivot_line->type) + MD_CHECK(md_end_current_block(ctx)); + + /* The current line may start a new block. */ + if(ctx->current_block == NULL) { + MD_CHECK(md_start_new_block(ctx, line)); + *p_pivot_line = line; + } + + /* In all other cases the line is just a continuation of the current block. */ + MD_CHECK(md_add_line_into_current_block(ctx, line)); + +abort: + return ret; +} + +static int +md_process_doc(MD_CTX *ctx) +{ + const MD_LINE_ANALYSIS* pivot_line = &md_dummy_blank_line; + MD_LINE_ANALYSIS line_buf[2]; + MD_LINE_ANALYSIS* line = &line_buf[0]; + OFF off = 0; + int ret = 0; + + MD_ENTER_BLOCK(MD_BLOCK_DOC, NULL); + + while(off < ctx->size) { + if(line == pivot_line) + line = (line == &line_buf[0] ? &line_buf[1] : &line_buf[0]); + + MD_CHECK(md_analyze_line(ctx, off, &off, pivot_line, line)); + MD_CHECK(md_process_line(ctx, &pivot_line, line)); + } + + md_end_current_block(ctx); + + MD_CHECK(md_build_ref_def_hashtable(ctx)); + + /* Process all blocks. */ + MD_CHECK(md_leave_child_containers(ctx, 0)); + MD_CHECK(md_process_all_blocks(ctx)); + + MD_LEAVE_BLOCK(MD_BLOCK_DOC, NULL); + +abort: + +#if 0 + /* Output some memory consumption statistics. */ + { + char buffer[256]; + sprintf(buffer, "Alloced %u bytes for block buffer.", + (unsigned)(ctx->alloc_block_bytes)); + MD_LOG(buffer); + + sprintf(buffer, "Alloced %u bytes for containers buffer.", + (unsigned)(ctx->alloc_containers * sizeof(MD_CONTAINER))); + MD_LOG(buffer); + + sprintf(buffer, "Alloced %u bytes for marks buffer.", + (unsigned)(ctx->alloc_marks * sizeof(MD_MARK))); + MD_LOG(buffer); + + sprintf(buffer, "Alloced %u bytes for aux. buffer.", + (unsigned)(ctx->alloc_buffer * sizeof(MD_CHAR))); + MD_LOG(buffer); + } +#endif + + return ret; +} + + +/******************** + *** Public API *** + ********************/ + +int +md_parse(const MD_CHAR* text, MD_SIZE size, const MD_PARSER* parser, void* userdata) +{ + MD_CTX ctx; + int i; + int ret; + + if(parser->abi_version != 0) { + if(parser->debug_log != NULL) + parser->debug_log("Unsupported abi_version.", userdata); + return -1; + } + + /* Setup context structure. */ + memset(&ctx, 0, sizeof(MD_CTX)); + ctx.text = text; + ctx.size = size; + memcpy(&ctx.parser, parser, sizeof(MD_PARSER)); + ctx.userdata = userdata; + ctx.code_indent_offset = (ctx.parser.flags & MD_FLAG_NOINDENTEDCODEBLOCKS) ? (OFF)(-1) : 4; + md_build_mark_char_map(&ctx); + + /* Reset all unresolved opener mark chains. */ + for(i = 0; i < SIZEOF_ARRAY(ctx.mark_chains); i++) { + ctx.mark_chains[i].head = -1; + ctx.mark_chains[i].tail = -1; + } + ctx.unresolved_link_head = -1; + ctx.unresolved_link_tail = -1; + + /* All the work. */ + ret = md_process_doc(&ctx); + + /* Clean-up. */ + md_free_ref_defs(&ctx); + md_free_ref_def_hashtable(&ctx); + free(ctx.buffer); + free(ctx.marks); + free(ctx.block_bytes); + free(ctx.containers); + + return ret; +} diff --git a/src/3rdparty/md4c/md4c.h b/src/3rdparty/md4c/md4c.h new file mode 100644 index 0000000000..10cba67e95 --- /dev/null +++ b/src/3rdparty/md4c/md4c.h @@ -0,0 +1,359 @@ +/* + * MD4C: Markdown parser for C + * (http://github.com/mity/md4c) + * + * Copyright (c) 2016-2019 Martin Mitas + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef MD4C_MARKDOWN_H +#define MD4C_MARKDOWN_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Magic to support UTF-16. */ +#if defined MD4C_USE_UTF16 + #ifdef _WIN32 + #include + typedef WCHAR MD_CHAR; + #else + #error MD4C_USE_UTF16 is only supported on Windows. + #endif +#else + typedef char MD_CHAR; +#endif + +typedef unsigned MD_SIZE; +typedef unsigned MD_OFFSET; + + +/* Block represents a part of document hierarchy structure like a paragraph + * or list item. + */ +typedef enum MD_BLOCKTYPE { + /* ... */ + MD_BLOCK_DOC = 0, + + /*
...
*/ + MD_BLOCK_QUOTE, + + /*
    ...
+ * Detail: Structure MD_BLOCK_UL_DETAIL. */ + MD_BLOCK_UL, + + /*
    ...
+ * Detail: Structure MD_BLOCK_OL_DETAIL. */ + MD_BLOCK_OL, + + /*
  • ...
  • + * Detail: Structure MD_BLOCK_LI_DETAIL. */ + MD_BLOCK_LI, + + /*
    */ + MD_BLOCK_HR, + + /*

    ...

    (for levels up to 6) + * Detail: Structure MD_BLOCK_H_DETAIL. */ + MD_BLOCK_H, + + /*
    ...
    + * Note the text lines within code blocks are terminated with '\n' + * instead of explicit MD_TEXT_BR. */ + MD_BLOCK_CODE, + + /* Raw HTML block. This itself does not correspond to any particular HTML + * tag. The contents of it _is_ raw HTML source intended to be put + * in verbatim form to the HTML output. */ + MD_BLOCK_HTML, + + /*

    ...

    */ + MD_BLOCK_P, + + /* ...
    and its contents. + * Detail: Structure MD_BLOCK_TD_DETAIL (used with MD_BLOCK_TH and MD_BLOCK_TD) + * Note all of these are used only if extension MD_FLAG_TABLES is enabled. */ + MD_BLOCK_TABLE, + MD_BLOCK_THEAD, + MD_BLOCK_TBODY, + MD_BLOCK_TR, + MD_BLOCK_TH, + MD_BLOCK_TD +} MD_BLOCKTYPE; + +/* Span represents an in-line piece of a document which should be rendered with + * the same font, color and other attributes. A sequence of spans forms a block + * like paragraph or list item. */ +typedef enum MD_SPANTYPE { + /* ... */ + MD_SPAN_EM, + + /* ... */ + MD_SPAN_STRONG, + + /* ... + * Detail: Structure MD_SPAN_A_DETAIL. */ + MD_SPAN_A, + + /* ... + * Detail: Structure MD_SPAN_IMG_DETAIL. + * Note: Image text can contain nested spans and even nested images. + * If rendered into ALT attribute of HTML tag, it's responsibility + * of the renderer to deal with it. + */ + MD_SPAN_IMG, + + /* ... */ + MD_SPAN_CODE, + + /* ... + * Note: Recognized only when MD_FLAG_STRIKETHROUGH is enabled. + */ + MD_SPAN_DEL +} MD_SPANTYPE; + +/* Text is the actual textual contents of span. */ +typedef enum MD_TEXTTYPE { + /* Normal text. */ + MD_TEXT_NORMAL = 0, + + /* NULL character. CommonMark requires replacing NULL character with + * the replacement char U+FFFD, so this allows caller to do that easily. */ + MD_TEXT_NULLCHAR, + + /* Line breaks. + * Note these are not sent from blocks with verbatim output (MD_BLOCK_CODE + * or MD_BLOCK_HTML). In such cases, '\n' is part of the text itself. */ + MD_TEXT_BR, /*
    (hard break) */ + MD_TEXT_SOFTBR, /* '\n' in source text where it is not semantically meaningful (soft break) */ + + /* Entity. + * (a) Named entity, e.g.   + * (Note MD4C does not have a list of known entities. + * Anything matching the regexp /&[A-Za-z][A-Za-z0-9]{1,47};/ is + * treated as a named entity.) + * (b) Numerical entity, e.g. Ӓ + * (c) Hexadecimal entity, e.g. ካ + * + * As MD4C is mostly encoding agnostic, application gets the verbatim + * entity text into the MD_RENDERER::text_callback(). */ + MD_TEXT_ENTITY, + + /* Text in a code block (inside MD_BLOCK_CODE) or inlined code (`code`). + * If it is inside MD_BLOCK_CODE, it includes spaces for indentation and + * '\n' for new lines. MD_TEXT_BR and MD_TEXT_SOFTBR are not sent for this + * kind of text. */ + MD_TEXT_CODE, + + /* Text is a raw HTML. If it is contents of a raw HTML block (i.e. not + * an inline raw HTML), then MD_TEXT_BR and MD_TEXT_SOFTBR are not used. + * The text contains verbatim '\n' for the new lines. */ + MD_TEXT_HTML +} MD_TEXTTYPE; + + +/* Alignment enumeration. */ +typedef enum MD_ALIGN { + MD_ALIGN_DEFAULT = 0, /* When unspecified. */ + MD_ALIGN_LEFT, + MD_ALIGN_CENTER, + MD_ALIGN_RIGHT +} MD_ALIGN; + + +/* String attribute. + * + * This wraps strings which are outside of a normal text flow and which are + * propagated within various detailed structures, but which still may contain + * string portions of different types like e.g. entities. + * + * So, for example, lets consider an image has a title attribute string + * set to "foo " bar". (Note the string size is 14.) + * + * Then the attribute MD_SPAN_IMG_DETAIL::title shall provide the following: + * -- [0]: "foo " (substr_types[0] == MD_TEXT_NORMAL; substr_offsets[0] == 0) + * -- [1]: """ (substr_types[1] == MD_TEXT_ENTITY; substr_offsets[1] == 4) + * -- [2]: " bar" (substr_types[2] == MD_TEXT_NORMAL; substr_offsets[2] == 10) + * -- [3]: (n/a) (n/a ; substr_offsets[3] == 14) + * + * Note that these conditions are guaranteed: + * -- substr_offsets[0] == 0 + * -- substr_offsets[LAST+1] == size + * -- Only MD_TEXT_NORMAL, MD_TEXT_ENTITY, MD_TEXT_NULLCHAR substrings can appear. + */ +typedef struct MD_ATTRIBUTE { + const MD_CHAR* text; + MD_SIZE size; + const MD_TEXTTYPE* substr_types; + const MD_OFFSET* substr_offsets; +} MD_ATTRIBUTE; + + +/* Detailed info for MD_BLOCK_UL. */ +typedef struct MD_BLOCK_UL_DETAIL { + int is_tight; /* Non-zero if tight list, zero if loose. */ + MD_CHAR mark; /* Item bullet character in MarkDown source of the list, e.g. '-', '+', '*'. */ +} MD_BLOCK_UL_DETAIL; + +/* Detailed info for MD_BLOCK_OL. */ +typedef struct MD_BLOCK_OL_DETAIL { + unsigned start; /* Start index of the ordered list. */ + int is_tight; /* Non-zero if tight list, zero if loose. */ + MD_CHAR mark_delimiter; /* Character delimiting the item marks in MarkDown source, e.g. '.' or ')' */ +} MD_BLOCK_OL_DETAIL; + +/* Detailed info for MD_BLOCK_LI. */ +typedef struct MD_BLOCK_LI_DETAIL { + int is_task; /* Can be non-zero only with MD_FLAG_TASKLISTS */ + MD_CHAR task_mark; /* If is_task, then one of 'x', 'X' or ' '. Undefined otherwise. */ + MD_OFFSET task_mark_offset; /* If is_task, then offset in the input of the char between '[' and ']'. */ +} MD_BLOCK_LI_DETAIL; + +/* Detailed info for MD_BLOCK_H. */ +typedef struct MD_BLOCK_H_DETAIL { + unsigned level; /* Header level (1 - 6) */ +} MD_BLOCK_H_DETAIL; + +/* Detailed info for MD_BLOCK_CODE. */ +typedef struct MD_BLOCK_CODE_DETAIL { + MD_ATTRIBUTE info; + MD_ATTRIBUTE lang; +} MD_BLOCK_CODE_DETAIL; + +/* Detailed info for MD_BLOCK_TH and MD_BLOCK_TD. */ +typedef struct MD_BLOCK_TD_DETAIL { + MD_ALIGN align; +} MD_BLOCK_TD_DETAIL; + +/* Detailed info for MD_SPAN_A. */ +typedef struct MD_SPAN_A_DETAIL { + MD_ATTRIBUTE href; + MD_ATTRIBUTE title; +} MD_SPAN_A_DETAIL; + +/* Detailed info for MD_SPAN_IMG. */ +typedef struct MD_SPAN_IMG_DETAIL { + MD_ATTRIBUTE src; + MD_ATTRIBUTE title; +} MD_SPAN_IMG_DETAIL; + + +/* Flags specifying extensions/deviations from CommonMark specification. + * + * By default (when MD_RENDERER::flags == 0), we follow CommonMark specification. + * The following flags may allow some extensions or deviations from it. + */ +#define MD_FLAG_COLLAPSEWHITESPACE 0x0001 /* In MD_TEXT_NORMAL, collapse non-trivial whitespace into single ' ' */ +#define MD_FLAG_PERMISSIVEATXHEADERS 0x0002 /* Do not require space in ATX headers ( ###header ) */ +#define MD_FLAG_PERMISSIVEURLAUTOLINKS 0x0004 /* Recognize URLs as autolinks even without '<', '>' */ +#define MD_FLAG_PERMISSIVEEMAILAUTOLINKS 0x0008 /* Recognize e-mails as autolinks even without '<', '>' and 'mailto:' */ +#define MD_FLAG_NOINDENTEDCODEBLOCKS 0x0010 /* Disable indented code blocks. (Only fenced code works.) */ +#define MD_FLAG_NOHTMLBLOCKS 0x0020 /* Disable raw HTML blocks. */ +#define MD_FLAG_NOHTMLSPANS 0x0040 /* Disable raw HTML (inline). */ +#define MD_FLAG_TABLES 0x0100 /* Enable tables extension. */ +#define MD_FLAG_STRIKETHROUGH 0x0200 /* Enable strikethrough extension. */ +#define MD_FLAG_PERMISSIVEWWWAUTOLINKS 0x0400 /* Enable WWW autolinks (even without any scheme prefix, if they begin with 'www.') */ +#define MD_FLAG_TASKLISTS 0x0800 /* Enable task list extension. */ + +#define MD_FLAG_PERMISSIVEAUTOLINKS (MD_FLAG_PERMISSIVEEMAILAUTOLINKS | MD_FLAG_PERMISSIVEURLAUTOLINKS | MD_FLAG_PERMISSIVEWWWAUTOLINKS) +#define MD_FLAG_NOHTML (MD_FLAG_NOHTMLBLOCKS | MD_FLAG_NOHTMLSPANS) + +/* Convenient sets of flags corresponding to well-known Markdown dialects. + * + * Note we may only support subset of features of the referred dialect. + * The constant just enables those extensions which bring us as close as + * possible given what features we implement. + * + * ABI compatibility note: Meaning of these can change in time as new + * extensions, bringing the dialect closer to the original, are implemented. + */ +#define MD_DIALECT_COMMONMARK 0 +#define MD_DIALECT_GITHUB (MD_FLAG_PERMISSIVEAUTOLINKS | MD_FLAG_TABLES | MD_FLAG_STRIKETHROUGH | MD_FLAG_TASKLISTS) + +/* Renderer structure. + */ +typedef struct MD_PARSER { + /* Reserved. Set to zero. + */ + unsigned abi_version; + + /* Dialect options. Bitmask of MD_FLAG_xxxx values. + */ + unsigned flags; + + /* Caller-provided rendering callbacks. + * + * For some block/span types, more detailed information is provided in a + * type-specific structure pointed by the argument 'detail'. + * + * The last argument of all callbacks, 'userdata', is just propagated from + * md_parse() and is available for any use by the application. + * + * Note any strings provided to the callbacks as their arguments or as + * members of any detail structure are generally not zero-terminated. + * Application has take the respective size information into account. + * + * Callbacks may abort further parsing of the document by returning non-zero. + */ + int (*enter_block)(MD_BLOCKTYPE /*type*/, void* /*detail*/, void* /*userdata*/); + int (*leave_block)(MD_BLOCKTYPE /*type*/, void* /*detail*/, void* /*userdata*/); + + int (*enter_span)(MD_SPANTYPE /*type*/, void* /*detail*/, void* /*userdata*/); + int (*leave_span)(MD_SPANTYPE /*type*/, void* /*detail*/, void* /*userdata*/); + + int (*text)(MD_TEXTTYPE /*type*/, const MD_CHAR* /*text*/, MD_SIZE /*size*/, void* /*userdata*/); + + /* Debug callback. Optional (may be NULL). + * + * If provided and something goes wrong, this function gets called. + * This is intended for debugging and problem diagnosis for developers; + * it is not intended to provide any errors suitable for displaying to an + * end user. + */ + void (*debug_log)(const char* /*msg*/, void* /*userdata*/); + + /* Reserved. Set to NULL. + */ + void (*syntax)(void); +} MD_PARSER; + + +/* For backward compatibility. Do not use in new code. */ +typedef MD_PARSER MD_RENDERER; + + +/* Parse the Markdown document stored in the string 'text' of size 'size'. + * The renderer provides callbacks to be called during the parsing so the + * caller can render the document on the screen or convert the Markdown + * to another format. + * + * Zero is returned on success. If a runtime error occurs (e.g. a memory + * fails), -1 is returned. If the processing is aborted due any callback + * returning non-zero, md_parse() the return value of the callback is returned. + */ +int md_parse(const MD_CHAR* text, MD_SIZE size, const MD_PARSER* parser, void* userdata); + + +#ifdef __cplusplus + } /* extern "C" { */ +#endif + +#endif /* MD4C_MARKDOWN_H */ diff --git a/src/3rdparty/md4c/qt_attribution.json b/src/3rdparty/md4c/qt_attribution.json new file mode 100644 index 0000000000..9180ed69b5 --- /dev/null +++ b/src/3rdparty/md4c/qt_attribution.json @@ -0,0 +1,15 @@ +{ + "Id": "md4c", + "Name": "MD4C", + "QDocModule": "qtgui", + "QtUsage": "Optionally used in QTextDocument if configured with textmarkdownreader.", + + "Description": "A CommonMark-compliant Markdown parser.", + "Homepage": "https://github.com/mity/md4c", + "License": "MIT License", + "LicenseId": "MIT", + "LicenseFile": "LICENSE.md", + "Version": "0.3.0", + "DownloadLocation": "https://github.com/mity/md4c/releases/tag/release-0.3.0-rc", + "Copyright": "Copyright © 2016-2019 Martin Mitáš" +} -- cgit v1.2.3 From 860bf13dbd2e9ad0a87b75defcab2cc3c9c771f3 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Wed, 17 Apr 2019 14:29:57 +0200 Subject: Fix compilation errors and warnings on INTEGRITY in md4c 3rdparty Change-Id: Ic27801f790b533f0a16099501fbe8a3ffe941d02 Reviewed-by: Shawn Rutledge --- src/3rdparty/md4c/md4c.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/3rdparty/md4c/md4c.c b/src/3rdparty/md4c/md4c.c index 4c0ad5c0fc..13c7bd3433 100644 --- a/src/3rdparty/md4c/md4c.c +++ b/src/3rdparty/md4c/md4c.c @@ -25,6 +25,7 @@ #include "md4c.h" +#include #include #include #include @@ -3375,7 +3376,7 @@ md_resolve_links(MD_CTX* ctx, const MD_LINE* lines, int n_lines) } else { if(closer->end < ctx->size && CH(closer->end) == _T('(')) { /* Might be inline link. */ - OFF inline_link_end = -1; + OFF inline_link_end = UINT_MAX; is_link = md_is_inline_link_spec(ctx, lines, n_lines, closer->end, &inline_link_end, &attr); if(is_link < 0) @@ -4152,11 +4153,14 @@ static int md_process_table_row(MD_CTX* ctx, MD_BLOCKTYPE cell_type, OFF beg, OFF end, const MD_ALIGN* align, int col_count) { - MD_LINE line = { beg, end }; + MD_LINE line; OFF* pipe_offs = NULL; int i, j, n; int ret = 0; + line.beg = beg; + line.end = end; + /* Break the line into table cells by identifying pipe characters who * form the cell boundary. */ MD_CHECK(md_analyze_inlines(ctx, &line, 1, TRUE)); @@ -4243,10 +4247,13 @@ abort: static int md_is_table_row(MD_CTX* ctx, OFF beg, OFF* p_end) { - MD_LINE line = { beg, beg }; + MD_LINE line; int i; int ret = FALSE; + line.beg = beg; + line.end = beg; + /* Find end of line. */ while(line.end < ctx->size && !ISNEWLINE(line.end)) line.end++; @@ -5186,6 +5193,7 @@ md_is_html_block_end_condition(MD_CTX* ctx, OFF beg, OFF* p_end) default: MD_UNREACHABLE(); } + return FALSE; } -- cgit v1.2.3 From 65314b6ce88cdbb28a22be0cab9856ec9bc9604b Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Mon, 18 Dec 2017 08:55:18 +0100 Subject: Add QTextMarkdownImporter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This provides the ability to read from a Markdown string or file into a QTextDocument, such that the formatting will be recognized and can be rendered. - Add QTextDocument::setMarkdown(QString) - Add QTextEdit::setMarkdown(QString) - Add TextFormat::MarkdownText - QWidgetTextControl::setContent() calls QTextDocument::setMarkdown() if that's the format Fixes: QTBUG-72349 Change-Id: Ief2ad71bf840666c64145d58e9ca71d05fad5659 Reviewed-by: Lisandro Damián Nicanor Pérez Meyer Reviewed-by: Gatis Paeglis --- src/corelib/global/qnamespace.h | 3 +- src/gui/configure.json | 34 +++ src/gui/text/qtextdocument.cpp | 30 +- src/gui/text/qtextdocument.h | 15 +- src/gui/text/qtextformat.h | 12 + src/gui/text/qtextmarkdownimporter.cpp | 435 +++++++++++++++++++++++++++ src/gui/text/qtextmarkdownimporter_p.h | 127 ++++++++ src/gui/text/text.pri | 12 + src/widgets/widgets/qtextedit.cpp | 9 +- src/widgets/widgets/qtextedit.h | 5 +- src/widgets/widgets/qwidgettextcontrol.cpp | 15 +- src/widgets/widgets/qwidgettextcontrol_p.h | 5 +- src/widgets/widgets/qwidgettextcontrol_p_p.h | 2 +- 13 files changed, 696 insertions(+), 8 deletions(-) create mode 100644 src/gui/text/qtextmarkdownimporter.cpp create mode 100644 src/gui/text/qtextmarkdownimporter_p.h (limited to 'src') diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index 90dd36113f..06aef81afc 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -1198,7 +1198,8 @@ public: enum TextFormat { PlainText, RichText, - AutoText + AutoText, + MarkdownText }; enum AspectRatioMode { diff --git a/src/gui/configure.json b/src/gui/configure.json index 7a1796041e..a4ea4375d1 100644 --- a/src/gui/configure.json +++ b/src/gui/configure.json @@ -28,6 +28,7 @@ "lgmon": "boolean", "libinput": "boolean", "libjpeg": { "type": "enum", "values": [ "no", "qt", "system" ] }, + "libmd4c": { "type": "enum", "values": [ "no", "qt", "system" ] }, "libpng": { "type": "enum", "values": [ "no", "qt", "system" ] }, "linuxfb": "boolean", "mtdev": "boolean", @@ -376,6 +377,17 @@ "-ljpeg" ] }, + "libmd4c": { + "label": "libmd4c", + "test": { + "main": "md_parse(\"hello\", 5, nullptr, nullptr);" + }, + "headers": "md4c.h", + "sources": [ + { "type": "pkgConfig", "args": "md4c" }, + { "libs": "-lmd4c" } + ] + }, "libpng": { "label": "libpng", "test": { @@ -1583,6 +1595,22 @@ "section": "Kernel", "output": [ "publicFeature", "feature" ] }, + "textmarkdownreader": { + "label": "MarkdownReader", + "disable": "input.libmd4c == 'no'", + "enable": "input.libmd4c == 'system' || input.libmd4c == 'qt' || input.libmd4c == 'yes'", + "purpose": "Provides a Markdown (CommonMark and GitHub) reader", + "section": "Kernel", + "output": [ "publicFeature" ] + }, + "system-textmarkdownreader": { + "label": " Using system libmd4c", + "disable": "input.libmd4c == 'qt'", + "enable": "input.libmd4c == 'system'", + "section": "Kernel", + "condition": "libs.libmd4c", + "output": [ "publicFeature" ] + }, "textodfwriter": { "label": "OdfWriter", "purpose": "Provides an ODF writer.", @@ -1861,6 +1889,12 @@ QMAKE_LIBDIR_OPENGL[_ES2] and QMAKE_LIBS_OPENGL[_ES2] in the mkspec for your pla "gif", "ico", "jpeg", "system-jpeg", "png", "system-png" ] }, + { + "section": "Text formats", + "entries": [ + "texthtmlparser", "cssparser", "textodfwriter", "textmarkdownreader", "system-textmarkdownreader" + ] + }, "egl", "openvg", { diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp index fd3473b32e..87c8f1ba8a 100644 --- a/src/gui/text/qtextdocument.cpp +++ b/src/gui/text/qtextdocument.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtGui module of the Qt Toolkit. @@ -70,6 +70,9 @@ #include #include "qpagedpaintdevice.h" #include "private/qpagedpaintdevice_p.h" +#if QT_CONFIG(textmarkdownreader) +#include +#endif #include @@ -3285,6 +3288,31 @@ QString QTextDocument::toHtml(const QByteArray &encoding) const } #endif // QT_NO_TEXTHTMLPARSER +/*! + Replaces the entire contents of the document with the given + Markdown-formatted text in the \a markdown string, with the given + \a features supported. By default, all supported GitHub-style + Markdown features are included; pass \c MarkdownDialectCommonMark + for a more basic parse. + + The Markdown formatting is respected as much as possible; for example, + "*bold* text" will produce text where the first word has a font weight that + gives it an emphasized appearance. + + Parsing of HTML included in the \a markdown string is handled in the same + way as in \l setHtml; however, Markdown formatting inside HTML blocks is + not supported. The \c MarkdownNoHTML feature flag can be set to disable + HTML parsing. + + The undo/redo history is reset when this function is called. +*/ +#if QT_CONFIG(textmarkdownreader) +void QTextDocument::setMarkdown(const QString &markdown, QTextDocument::MarkdownFeatures features) +{ + QTextMarkdownImporter(static_cast(int(features))).import(this, markdown); +} +#endif + /*! Returns a vector of text formats for all the formats used in the document. */ diff --git a/src/gui/text/qtextdocument.h b/src/gui/text/qtextdocument.h index c9b22e053b..ade67999ad 100644 --- a/src/gui/text/qtextdocument.h +++ b/src/gui/text/qtextdocument.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtGui module of the Qt Toolkit. @@ -151,6 +151,19 @@ public: void setHtml(const QString &html); #endif +#if QT_CONFIG(textmarkdownreader) + // Must be in sync with QTextMarkdownImporter::Features, should be in sync with #define MD_FLAG_* in md4c + enum MarkdownFeature { + MarkdownNoHTML = 0x0020 | 0x0040, + MarkdownDialectCommonMark = 0, + MarkdownDialectGitHub = 0x0004 | 0x0008 | 0x0400 | 0x0100 | 0x0200 | 0x0800 + }; + Q_DECLARE_FLAGS(MarkdownFeatures, MarkdownFeature) + Q_FLAG(MarkdownFeatures) + + void setMarkdown(const QString &markdown, MarkdownFeatures features = MarkdownDialectGitHub); +#endif + QString toRawText() const; QString toPlainText() const; void setPlainText(const QString &text); diff --git a/src/gui/text/qtextformat.h b/src/gui/text/qtextformat.h index 80d8e82694..1eb52a379c 100644 --- a/src/gui/text/qtextformat.h +++ b/src/gui/text/qtextformat.h @@ -176,6 +176,7 @@ public: BlockNonBreakableLines = 0x1050, BlockTrailingHorizontalRulerWidth = 0x1060, HeadingLevel = 0x1070, + BlockMarker = 0x1080, // character properties FirstFontProperty = 0x1FE0, @@ -605,6 +606,12 @@ public: LineDistanceHeight = 4 }; + enum MarkerType { + NoMarker = 0, + Unchecked = 1, + Checked = 2 + }; + QTextBlockFormat(); bool isValid() const { return isBlockFormat(); } @@ -668,6 +675,11 @@ public: void setTabPositions(const QList &tabs); QList tabPositions() const; + inline void setMarker(MarkerType marker) + { setProperty(BlockMarker, int(marker)); } + inline MarkerType marker() const + { return MarkerType(intProperty(BlockMarker)); } + protected: explicit QTextBlockFormat(const QTextFormat &fmt); friend class QTextFormat; diff --git a/src/gui/text/qtextmarkdownimporter.cpp b/src/gui/text/qtextmarkdownimporter.cpp new file mode 100644 index 0000000000..6c053ac81a --- /dev/null +++ b/src/gui/text/qtextmarkdownimporter.cpp @@ -0,0 +1,435 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qtextmarkdownimporter_p.h" +#include "qtextdocumentfragment_p.h" +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +Q_LOGGING_CATEGORY(lcMD, "qt.text.markdown") + +// -------------------------------------------------------- +// MD4C callback function wrappers + +static int CbEnterBlock(MD_BLOCKTYPE type, void *detail, void *userdata) +{ + QTextMarkdownImporter *mdi = static_cast(userdata); + return mdi->cbEnterBlock(type, detail); +} + +static int CbLeaveBlock(MD_BLOCKTYPE type, void *detail, void *userdata) +{ + QTextMarkdownImporter *mdi = static_cast(userdata); + return mdi->cbLeaveBlock(type, detail); +} + +static int CbEnterSpan(MD_SPANTYPE type, void *detail, void *userdata) +{ + QTextMarkdownImporter *mdi = static_cast(userdata); + return mdi->cbEnterSpan(type, detail); +} + +static int CbLeaveSpan(MD_SPANTYPE type, void *detail, void *userdata) +{ + QTextMarkdownImporter *mdi = static_cast(userdata); + return mdi->cbLeaveSpan(type, detail); +} + +static int CbText(MD_TEXTTYPE type, const MD_CHAR *text, MD_SIZE size, void *userdata) +{ + QTextMarkdownImporter *mdi = static_cast(userdata); + return mdi->cbText(type, text, size); +} + +static void CbDebugLog(const char *msg, void *userdata) +{ + Q_UNUSED(userdata) + qCDebug(lcMD) << msg; +} + +// MD4C callback function wrappers +// -------------------------------------------------------- + +static Qt::Alignment MdAlignment(MD_ALIGN a, Qt::Alignment defaultAlignment = Qt::AlignLeft | Qt::AlignVCenter) +{ + switch (a) { + case MD_ALIGN_LEFT: + return Qt::AlignLeft | Qt::AlignVCenter; + case MD_ALIGN_CENTER: + return Qt::AlignHCenter | Qt::AlignVCenter; + case MD_ALIGN_RIGHT: + return Qt::AlignRight | Qt::AlignVCenter; + default: // including MD_ALIGN_DEFAULT + return defaultAlignment; + } +} + +QTextMarkdownImporter::QTextMarkdownImporter(QTextMarkdownImporter::Features features) + : m_monoFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)) + , m_features(features) +{ +} + +void QTextMarkdownImporter::import(QTextDocument *doc, const QString &markdown) +{ + MD_PARSER callbacks = { + 0, // abi_version + m_features, + &CbEnterBlock, + &CbLeaveBlock, + &CbEnterSpan, + &CbLeaveSpan, + &CbText, + &CbDebugLog, + nullptr // syntax + }; + m_doc = doc; + m_cursor = new QTextCursor(doc); + doc->clear(); + qCDebug(lcMD) << "default font" << doc->defaultFont() << "mono font" << m_monoFont; + QByteArray md = markdown.toUtf8(); + md_parse(md.constData(), md.size(), &callbacks, this); + delete m_cursor; + m_cursor = nullptr; +} + +int QTextMarkdownImporter::cbEnterBlock(MD_BLOCKTYPE type, void *det) +{ + m_blockType = type; + switch (type) { + case MD_BLOCK_P: { + QTextBlockFormat blockFmt; + int margin = m_doc->defaultFont().pointSize() / 2; + blockFmt.setTopMargin(margin); + blockFmt.setBottomMargin(margin); + m_cursor->insertBlock(blockFmt, QTextCharFormat()); + } break; + case MD_BLOCK_CODE: { + QTextBlockFormat blockFmt; + QTextCharFormat charFmt; + charFmt.setFont(m_monoFont); + m_cursor->insertBlock(blockFmt, charFmt); + } break; + case MD_BLOCK_H: { + MD_BLOCK_H_DETAIL *detail = static_cast(det); + QTextBlockFormat blockFmt; + QTextCharFormat charFmt; + int sizeAdjustment = 4 - detail->level; // H1 to H6: +3 to -2 + charFmt.setProperty(QTextFormat::FontSizeAdjustment, sizeAdjustment); + charFmt.setFontWeight(QFont::Bold); + blockFmt.setHeadingLevel(detail->level); + m_cursor->insertBlock(blockFmt, charFmt); + } break; + case MD_BLOCK_LI: { + MD_BLOCK_LI_DETAIL *detail = static_cast(det); + QTextBlockFormat bfmt = m_cursor->blockFormat(); + bfmt.setMarker(detail->is_task ? + (detail->task_mark == ' ' ? QTextBlockFormat::Unchecked : QTextBlockFormat::Checked) : + QTextBlockFormat::NoMarker); + if (!m_emptyList) { + m_cursor->insertBlock(bfmt, QTextCharFormat()); + m_listStack.top()->add(m_cursor->block()); + } + m_cursor->setBlockFormat(bfmt); + m_emptyList = false; // Avoid insertBlock for the first item (because insertList already did that) + } break; + case MD_BLOCK_UL: { + MD_BLOCK_UL_DETAIL *detail = static_cast(det); + QTextListFormat fmt; + fmt.setIndent(m_listStack.count() + 1); + switch (detail->mark) { + case '*': + fmt.setStyle(QTextListFormat::ListCircle); + break; + case '+': + fmt.setStyle(QTextListFormat::ListSquare); + break; + default: // including '-' + fmt.setStyle(QTextListFormat::ListDisc); + break; + } + m_listStack.push(m_cursor->insertList(fmt)); + m_emptyList = true; + } break; + case MD_BLOCK_OL: { + MD_BLOCK_OL_DETAIL *detail = static_cast(det); + QTextListFormat fmt; + fmt.setIndent(m_listStack.count() + 1); + fmt.setNumberSuffix(QChar::fromLatin1(detail->mark_delimiter)); + fmt.setStyle(QTextListFormat::ListDecimal); + m_listStack.push(m_cursor->insertList(fmt)); + m_emptyList = true; + } break; + case MD_BLOCK_TD: { + MD_BLOCK_TD_DETAIL *detail = static_cast(det); + ++m_tableCol; + // absolute movement (and storage of m_tableCol) shouldn't be necessary, but + // movePosition(QTextCursor::NextCell) doesn't work + QTextTableCell cell = m_currentTable->cellAt(m_tableRowCount - 1, m_tableCol); + if (!cell.isValid()) { + qWarning("malformed table in Markdown input"); + return 1; + } + *m_cursor = cell.firstCursorPosition(); + QTextBlockFormat blockFmt = m_cursor->blockFormat(); + blockFmt.setAlignment(MdAlignment(detail->align)); + m_cursor->setBlockFormat(blockFmt); + qCDebug(lcMD) << "TD; align" << detail->align << MdAlignment(detail->align) << "col" << m_tableCol; + } break; + case MD_BLOCK_TH: { + ++m_tableColumnCount; + ++m_tableCol; + if (m_currentTable->columns() < m_tableColumnCount) + m_currentTable->appendColumns(1); + auto cell = m_currentTable->cellAt(m_tableRowCount - 1, m_tableCol); + if (!cell.isValid()) { + qWarning("malformed table in Markdown input"); + return 1; + } + auto fmt = cell.format(); + fmt.setFontWeight(QFont::Bold); + cell.setFormat(fmt); + } break; + case MD_BLOCK_TR: { + ++m_tableRowCount; + m_nonEmptyTableCells.clear(); + if (m_currentTable->rows() < m_tableRowCount) + m_currentTable->appendRows(1); + m_tableCol = -1; + qCDebug(lcMD) << "TR" << m_currentTable->rows(); + } break; + case MD_BLOCK_TABLE: + m_tableColumnCount = 0; + m_tableRowCount = 0; + m_currentTable = m_cursor->insertTable(1, 1); // we don't know the dimensions yet + break; + case MD_BLOCK_HR: { + QTextBlockFormat blockFmt = m_cursor->blockFormat(); + blockFmt.setProperty(QTextFormat::BlockTrailingHorizontalRulerWidth, 1); + m_cursor->insertBlock(blockFmt, QTextCharFormat()); + } break; + default: + break; // nothing to do for now + } + return 0; // no error +} + +int QTextMarkdownImporter::cbLeaveBlock(MD_BLOCKTYPE type, void *detail) +{ + Q_UNUSED(detail) + switch (type) { + case MD_BLOCK_UL: + case MD_BLOCK_OL: + m_listStack.pop(); + break; + case MD_BLOCK_TR: { + // https://github.com/mity/md4c/issues/29 + // MD4C doesn't tell us explicitly which cells are merged, so merge empty cells + // with previous non-empty ones + int mergeEnd = -1; + int mergeBegin = -1; + for (int col = m_tableCol; col >= 0; --col) { + if (m_nonEmptyTableCells.contains(col)) { + if (mergeEnd >= 0 && mergeBegin >= 0) { + qCDebug(lcMD) << "merging cells" << mergeBegin << "to" << mergeEnd << "inclusive, on row" << m_currentTable->rows() - 1; + m_currentTable->mergeCells(m_currentTable->rows() - 1, mergeBegin - 1, 1, mergeEnd - mergeBegin + 2); + } + mergeEnd = -1; + mergeBegin = -1; + } else { + if (mergeEnd < 0) + mergeEnd = col; + else + mergeBegin = col; + } + } + } break; + case MD_BLOCK_QUOTE: { + QTextBlockFormat blockFmt = m_cursor->blockFormat(); + blockFmt.setIndent(1); + m_cursor->setBlockFormat(blockFmt); + } break; + case MD_BLOCK_TABLE: + qCDebug(lcMD) << "table ended with" << m_currentTable->columns() << "cols and" << m_currentTable->rows() << "rows"; + m_currentTable = nullptr; + m_cursor->movePosition(QTextCursor::End); + break; + default: + break; + } + return 0; // no error +} + +int QTextMarkdownImporter::cbEnterSpan(MD_SPANTYPE type, void *det) +{ + QTextCharFormat charFmt; + switch (type) { + case MD_SPAN_EM: + charFmt.setFontItalic(true); + break; + case MD_SPAN_STRONG: + charFmt.setFontWeight(QFont::Bold); + break; + case MD_SPAN_A: { + MD_SPAN_A_DETAIL *detail = static_cast(det); + QString url = QString::fromLatin1(detail->href.text, detail->href.size); + QString title = QString::fromLatin1(detail->title.text, detail->title.size); + charFmt.setAnchorHref(url); + charFmt.setAnchorName(title); + charFmt.setForeground(m_palette.link()); + qCDebug(lcMD) << "anchor" << url << title; + } break; + case MD_SPAN_IMG: { + m_imageSpan = true; + MD_SPAN_IMG_DETAIL *detail = static_cast(det); + QString src = QString::fromUtf8(detail->src.text, detail->src.size); + QString title = QString::fromUtf8(detail->title.text, detail->title.size); + QTextImageFormat img; + img.setName(src); + qCDebug(lcMD) << "image" << src << "title" << title << "relative to" << m_doc->baseUrl(); + m_cursor->insertImage(img); + break; + } + case MD_SPAN_CODE: + charFmt.setFont(m_monoFont); + break; + case MD_SPAN_DEL: + charFmt.setFontStrikeOut(true); + break; + } + m_spanFormatStack.push(charFmt); + m_cursor->setCharFormat(charFmt); + return 0; // no error +} + +int QTextMarkdownImporter::cbLeaveSpan(MD_SPANTYPE type, void *detail) +{ + Q_UNUSED(detail) + QTextCharFormat charFmt; + if (!m_spanFormatStack.isEmpty()) { + m_spanFormatStack.pop(); + if (!m_spanFormatStack.isEmpty()) + charFmt = m_spanFormatStack.top(); + } + m_cursor->setCharFormat(charFmt); + if (type == MD_SPAN_IMG) + m_imageSpan = false; + return 0; // no error +} + +int QTextMarkdownImporter::cbText(MD_TEXTTYPE type, const MD_CHAR *text, MD_SIZE size) +{ + if (m_imageSpan) + return 0; // it's the alt-text + static const QRegularExpression openingBracket(QStringLiteral("<[a-zA-Z]")); + static const QRegularExpression closingBracket(QStringLiteral("(/>|insertHtml(s); + s = QString(); + break; + case MD_TEXT_HTML: + // count how many tags are opened and how many are closed + { + int startIdx = 0; + while ((startIdx = s.indexOf(openingBracket, startIdx)) >= 0) { + ++m_htmlTagDepth; + startIdx += 2; + } + startIdx = 0; + while ((startIdx = s.indexOf(closingBracket, startIdx)) >= 0) { + --m_htmlTagDepth; + startIdx += 2; + } + } + m_htmlAccumulator += s; + s = QString(); + if (!m_htmlTagDepth) { // all open tags are now closed + qCDebug(lcMD) << "HTML" << m_htmlAccumulator; + m_cursor->insertHtml(m_htmlAccumulator); + if (m_spanFormatStack.isEmpty()) + m_cursor->setCharFormat(QTextCharFormat()); + else + m_cursor->setCharFormat(m_spanFormatStack.top()); + m_htmlAccumulator = QString(); + } + break; + } + + switch (m_blockType) { + case MD_BLOCK_TD: + m_nonEmptyTableCells.append(m_tableCol); + break; + default: + break; + } + + if (!s.isEmpty()) + m_cursor->insertText(s); + return 0; // no error +} + +QT_END_NAMESPACE diff --git a/src/gui/text/qtextmarkdownimporter_p.h b/src/gui/text/qtextmarkdownimporter_p.h new file mode 100644 index 0000000000..b73e744434 --- /dev/null +++ b/src/gui/text/qtextmarkdownimporter_p.h @@ -0,0 +1,127 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTEXTMARKDOWNIMPORTER_H +#define QTEXTMARKDOWNIMPORTER_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include +#include + +#include "../../3rdparty/md4c/md4c.h" + +QT_BEGIN_NAMESPACE + +class QTextCursor; +class QTextDocument; +class QTextTable; + +class Q_GUI_EXPORT QTextMarkdownImporter +{ +public: + enum Feature { + FeatureCollapseWhitespace = MD_FLAG_COLLAPSEWHITESPACE, + FeaturePermissiveATXHeaders = MD_FLAG_PERMISSIVEATXHEADERS, + FeaturePermissiveURLAutoLinks = MD_FLAG_PERMISSIVEURLAUTOLINKS, + FeaturePermissiveMailAutoLinks = MD_FLAG_PERMISSIVEEMAILAUTOLINKS, + FeatureNoIndentedCodeBlocks = MD_FLAG_NOINDENTEDCODEBLOCKS, + FeatureNoHTMLBlocks = MD_FLAG_NOHTMLBLOCKS, + FeatureNoHTMLSpans = MD_FLAG_NOHTMLSPANS, + FeatureTables = MD_FLAG_TABLES, + FeatureStrikeThrough = MD_FLAG_STRIKETHROUGH, + FeaturePermissiveWWWAutoLinks = MD_FLAG_PERMISSIVEWWWAUTOLINKS, + FeatureTasklists = MD_FLAG_TASKLISTS, + // composite flags + FeaturePermissiveAutoLinks = MD_FLAG_PERMISSIVEAUTOLINKS, + FeatureNoHTML = MD_FLAG_NOHTML, + DialectCommonMark = MD_DIALECT_COMMONMARK, + DialectGitHub = MD_DIALECT_GITHUB + }; + Q_DECLARE_FLAGS(Features, Feature) + + QTextMarkdownImporter(Features features); + + void import(QTextDocument *doc, const QString &markdown); + +public: + // MD4C callbacks + int cbEnterBlock(MD_BLOCKTYPE type, void* detail); + int cbLeaveBlock(MD_BLOCKTYPE type, void* detail); + int cbEnterSpan(MD_SPANTYPE type, void* detail); + int cbLeaveSpan(MD_SPANTYPE type, void* detail); + int cbText(MD_TEXTTYPE type, const MD_CHAR* text, MD_SIZE size); + +private: + QTextDocument *m_doc = nullptr; + QTextCursor *m_cursor = nullptr; + QTextTable *m_currentTable = nullptr; // because m_cursor->currentTable() doesn't work + QString m_htmlAccumulator; + QVector m_nonEmptyTableCells; // in the current row + QStack m_listStack; + QStack m_spanFormatStack; + QFont m_monoFont; + QPalette m_palette; + int m_htmlTagDepth = 0; + int m_tableColumnCount = 0; + int m_tableRowCount = 0; + int m_tableCol = -1; // because relative cell movements (e.g. m_cursor->movePosition(QTextCursor::NextCell)) don't work + Features m_features; + MD_BLOCKTYPE m_blockType = MD_BLOCK_DOC; + bool m_emptyList = false; // true when the last thing we did was insertList + bool m_imageSpan = false; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QTextMarkdownImporter::Features) + +QT_END_NAMESPACE + +#endif // QTEXTMARKDOWNIMPORTER_H diff --git a/src/gui/text/text.pri b/src/gui/text/text.pri index abe20abe02..b35a231747 100644 --- a/src/gui/text/text.pri +++ b/src/gui/text/text.pri @@ -97,6 +97,18 @@ qtConfig(textodfwriter) { text/qzip.cpp } +qtConfig(textmarkdownreader) { + qtConfig(system-textmarkdownreader) { + QMAKE_USE += libmd4c + } else { + include($$PWD/../../3rdparty/md4c.pri) + } + HEADERS += \ + text/qtextmarkdownimporter_p.h + SOURCES += \ + text/qtextmarkdownimporter.cpp +} + qtConfig(cssparser) { HEADERS += \ text/qcssparser_p.h diff --git a/src/widgets/widgets/qtextedit.cpp b/src/widgets/widgets/qtextedit.cpp index 920133d493..4a06f58b4a 100644 --- a/src/widgets/widgets/qtextedit.cpp +++ b/src/widgets/widgets/qtextedit.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtWidgets module of the Qt Toolkit. @@ -1202,6 +1202,13 @@ QString QTextEdit::toHtml() const } #endif +#if QT_CONFIG(textmarkdownreader) +void QTextEdit::setMarkdown(const QString &text) +{ + Q_D(const QTextEdit); + d->control->setMarkdown(text); +} +#endif /*! \reimp */ diff --git a/src/widgets/widgets/qtextedit.h b/src/widgets/widgets/qtextedit.h index 3aa23aaace..f20bd936c4 100644 --- a/src/widgets/widgets/qtextedit.h +++ b/src/widgets/widgets/qtextedit.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtWidgets module of the Qt Toolkit. @@ -237,6 +237,9 @@ public Q_SLOTS: void setPlainText(const QString &text); #ifndef QT_NO_TEXTHTMLPARSER void setHtml(const QString &text); +#endif +#if QT_CONFIG(textmarkdownreader) + void setMarkdown(const QString &text); #endif void setText(const QString &text); diff --git a/src/widgets/widgets/qwidgettextcontrol.cpp b/src/widgets/widgets/qwidgettextcontrol.cpp index 711c4bfd2a..5744d43cbf 100644 --- a/src/widgets/widgets/qwidgettextcontrol.cpp +++ b/src/widgets/widgets/qwidgettextcontrol.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtWidgets module of the Qt Toolkit. @@ -491,6 +491,11 @@ void QWidgetTextControlPrivate::setContent(Qt::TextFormat format, const QString formatCursor.select(QTextCursor::Document); formatCursor.setCharFormat(charFormatForInsertion); formatCursor.endEditBlock(); +#if QT_CONFIG(textmarkdownreader) + } else if (format == Qt::MarkdownText) { + doc->setMarkdown(text); + doc->setUndoRedoEnabled(false); +#endif } else { #ifndef QT_NO_TEXTHTMLPARSER doc->setHtml(text); @@ -1194,6 +1199,14 @@ void QWidgetTextControl::setPlainText(const QString &text) d->setContent(Qt::PlainText, text); } +#if QT_CONFIG(textmarkdownreader) +void QWidgetTextControl::setMarkdown(const QString &text) +{ + Q_D(QWidgetTextControl); + d->setContent(Qt::MarkdownText, text); +} +#endif + void QWidgetTextControl::setHtml(const QString &text) { Q_D(QWidgetTextControl); diff --git a/src/widgets/widgets/qwidgettextcontrol_p.h b/src/widgets/widgets/qwidgettextcontrol_p.h index 9c80d53728..4c9e47dfc9 100644 --- a/src/widgets/widgets/qwidgettextcontrol_p.h +++ b/src/widgets/widgets/qwidgettextcontrol_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtWidgets module of the Qt Toolkit. @@ -194,6 +194,9 @@ public: public Q_SLOTS: void setPlainText(const QString &text); +#if QT_CONFIG(textmarkdownreader) + void setMarkdown(const QString &text); +#endif void setHtml(const QString &text); #ifndef QT_NO_CLIPBOARD diff --git a/src/widgets/widgets/qwidgettextcontrol_p_p.h b/src/widgets/widgets/qwidgettextcontrol_p_p.h index 6a1ee564cd..6ccdfafe2b 100644 --- a/src/widgets/widgets/qwidgettextcontrol_p_p.h +++ b/src/widgets/widgets/qwidgettextcontrol_p_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtWidgets module of the Qt Toolkit. -- cgit v1.2.3 From 642ef0c7311e18b9b4414af6ec3a2d8210bb6880 Mon Sep 17 00:00:00 2001 From: Konstantin Shegunov Date: Wed, 3 Apr 2019 13:00:01 +0300 Subject: Clear SSL key data as soon as possible when move-assigning Move-assign uses qSwap to exchange the private pointer and thus can extend the lifetime of sensitive data. The move assignment operator is changed so it releases the private data as soon as possible. [ChangeLog][QtNetwork][QSslKey] Key data is cleared as soon as possible when move-assigning. Change-Id: Iebd029bf657acfe000417ce648e3b3829948c0e5 Reviewed-by: Samuel Gaist --- src/network/ssl/qsslkey.h | 5 ++--- src/network/ssl/qsslkey_p.cpp | 18 ++++++++++++++++++ src/network/ssl/qsslkey_qt.cpp | 5 ++++- 3 files changed, 24 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/network/ssl/qsslkey.h b/src/network/ssl/qsslkey.h index a865f20a51..74be406539 100644 --- a/src/network/ssl/qsslkey.h +++ b/src/network/ssl/qsslkey.h @@ -71,9 +71,8 @@ public: const QByteArray &passPhrase = QByteArray()); explicit QSslKey(Qt::HANDLE handle, QSsl::KeyType type = QSsl::PrivateKey); QSslKey(const QSslKey &other); -#ifdef Q_COMPILER_RVALUE_REFS - QSslKey &operator=(QSslKey &&other) noexcept { swap(other); return *this; } -#endif + QSslKey(QSslKey &&other) noexcept; + QSslKey &operator=(QSslKey &&other) noexcept; QSslKey &operator=(const QSslKey &other); ~QSslKey(); diff --git a/src/network/ssl/qsslkey_p.cpp b/src/network/ssl/qsslkey_p.cpp index b29b38beab..7d14aacebf 100644 --- a/src/network/ssl/qsslkey_p.cpp +++ b/src/network/ssl/qsslkey_p.cpp @@ -385,6 +385,24 @@ QSslKey::QSslKey(const QSslKey &other) : d(other.d) { } +QSslKey::QSslKey(QSslKey &&other) noexcept + : d(nullptr) +{ + qSwap(d, other.d); +} + +QSslKey &QSslKey::operator=(QSslKey &&other) noexcept +{ + if (this == &other) + return *this; + + // If no one else is referencing the key data we want to make sure + // before we swap the d-ptr that it is not left in memory. + d.reset(); + qSwap(d, other.d); + return *this; +} + /*! Destroys the QSslKey object. */ diff --git a/src/network/ssl/qsslkey_qt.cpp b/src/network/ssl/qsslkey_qt.cpp index 2662418a05..43969c3d28 100644 --- a/src/network/ssl/qsslkey_qt.cpp +++ b/src/network/ssl/qsslkey_qt.cpp @@ -48,6 +48,8 @@ #include +#include + QT_USE_NAMESPACE static const quint8 bits_table[256] = { @@ -186,8 +188,9 @@ static QByteArray deriveKey(QSslKeyPrivate::Cipher cipher, const QByteArray &pas void QSslKeyPrivate::clear(bool deep) { - Q_UNUSED(deep); isNull = true; + if (deep) + std::memset(derData.data(), 0, derData.size()); derData.clear(); keyLength = -1; } -- cgit v1.2.3 From e2906ea5c4b97ca9bb4ebf9710207097c44cc8ce Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Thu, 27 Sep 2018 00:19:49 +0200 Subject: QRegExp include cleanup QRegExp includes can be found in several files where there's not even a use of the class. This patch aims to avoid needless includes as well as follow the "include only what you use" moto. This patch removes a QRegExp include from the QStringList header which means that there is likely going to be code breaking since QStringList is used in many places and would get QRegExp in. [ChangeLog][Potentially Source-Incompatible Changes] qstringlist.h no longer includes qregexp.h. Change-Id: I32847532f16e419d4cb735ddc11a26551127e923 Reviewed-by: Thiago Macieira --- src/corelib/io/qdiriterator.cpp | 1 + src/corelib/itemmodels/qabstractitemmodel.cpp | 1 + src/corelib/kernel/qmetatype.cpp | 1 + src/corelib/kernel/qvariant.cpp | 1 + src/corelib/tools/qdatetimeparser.cpp | 1 - src/corelib/tools/qstringlist.cpp | 1 + src/gui/image/qpicture.cpp | 1 + src/gui/image/qxbmhandler.cpp | 1 + src/gui/image/qxpmhandler.cpp | 1 + src/gui/kernel/qkeysequence.cpp | 3 --- src/gui/kernel/qsimpledrag.cpp | 1 - src/network/access/qnetworkcookie.cpp | 1 + .../fontdatabases/windows/qwindowsfontdatabase_ft.cpp | 4 ++++ src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm | 1 - src/plugins/platforms/cocoa/qcocoamenuitem.mm | 1 + src/plugins/sqldrivers/sqlite2/qsql_sqlite2.cpp | 1 - src/sql/kernel/qsqlresult.cpp | 1 - src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp | 1 - src/tools/rcc/rcc.cpp | 1 + src/tools/tracegen/etw.cpp | 1 - src/tools/tracegen/lttng.cpp | 1 - src/widgets/dialogs/qcolordialog.cpp | 5 +++++ 22 files changed, 20 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/corelib/io/qdiriterator.cpp b/src/corelib/io/qdiriterator.cpp index 648593b020..69d61bf5a8 100644 --- a/src/corelib/io/qdiriterator.cpp +++ b/src/corelib/io/qdiriterator.cpp @@ -93,6 +93,7 @@ #include "qdir_p.h" #include "qabstractfileengine_p.h" +#include #include #include #include diff --git a/src/corelib/itemmodels/qabstractitemmodel.cpp b/src/corelib/itemmodels/qabstractitemmodel.cpp index 18f0f6f55f..664e16540b 100644 --- a/src/corelib/itemmodels/qabstractitemmodel.cpp +++ b/src/corelib/itemmodels/qabstractitemmodel.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp index 19bda7e8d6..855d36794d 100644 --- a/src/corelib/kernel/qmetatype.cpp +++ b/src/corelib/kernel/qmetatype.cpp @@ -51,6 +51,7 @@ #include "quuid.h" #include "qvariant.h" #include "qdatastream.h" +#include "qregexp.h" #include "qmetatypeswitcher_p.h" #if QT_CONFIG(regularexpression) diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index cd4e233af0..4af2073365 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -55,6 +55,7 @@ #include "qstringlist.h" #include "qurl.h" #include "qlocale.h" +#include "qregexp.h" #include "quuid.h" #if QT_CONFIG(itemmodel) #include "qabstractitemmodel.h" diff --git a/src/corelib/tools/qdatetimeparser.cpp b/src/corelib/tools/qdatetimeparser.cpp index e8470f6cde..5d1704daeb 100644 --- a/src/corelib/tools/qdatetimeparser.cpp +++ b/src/corelib/tools/qdatetimeparser.cpp @@ -47,7 +47,6 @@ #if QT_CONFIG(timezone) #include "qtimezone.h" #endif -#include "qregexp.h" #include "qdebug.h" //#define QDATETIMEPARSER_DEBUG diff --git a/src/corelib/tools/qstringlist.cpp b/src/corelib/tools/qstringlist.cpp index 49247d66b8..f6da7b1428 100644 --- a/src/corelib/tools/qstringlist.cpp +++ b/src/corelib/tools/qstringlist.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include +#include #include #if QT_CONFIG(regularexpression) # include diff --git a/src/gui/image/qpicture.cpp b/src/gui/image/qpicture.cpp index 56b82abcfa..350fda19ac 100644 --- a/src/gui/image/qpicture.cpp +++ b/src/gui/image/qpicture.cpp @@ -54,6 +54,7 @@ #include "qpainter.h" #include "qpainterpath.h" #include "qpixmap.h" +#include "qregexp.h" #include "qregion.h" #include "qdebug.h" diff --git a/src/gui/image/qxbmhandler.cpp b/src/gui/image/qxbmhandler.cpp index 65a5b63bc7..3cd15b3e4d 100644 --- a/src/gui/image/qxbmhandler.cpp +++ b/src/gui/image/qxbmhandler.cpp @@ -44,6 +44,7 @@ #include #include +#include #include #include diff --git a/src/gui/image/qxpmhandler.cpp b/src/gui/image/qxpmhandler.cpp index a32dfda96d..7349a400a6 100644 --- a/src/gui/image/qxpmhandler.cpp +++ b/src/gui/image/qxpmhandler.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include #include diff --git a/src/gui/kernel/qkeysequence.cpp b/src/gui/kernel/qkeysequence.cpp index 0fa3dcfbdb..8688bb8403 100644 --- a/src/gui/kernel/qkeysequence.cpp +++ b/src/gui/kernel/qkeysequence.cpp @@ -46,9 +46,6 @@ #include "qdebug.h" #include -#ifndef QT_NO_REGEXP -# include "qregexp.h" -#endif #ifndef QT_NO_DATASTREAM # include "qdatastream.h" #endif diff --git a/src/gui/kernel/qsimpledrag.cpp b/src/gui/kernel/qsimpledrag.cpp index 9aab332ef5..bba2a863a9 100644 --- a/src/gui/kernel/qsimpledrag.cpp +++ b/src/gui/kernel/qsimpledrag.cpp @@ -48,7 +48,6 @@ #include "qpoint.h" #include "qbuffer.h" #include "qimage.h" -#include "qregexp.h" #include "qdir.h" #include "qimagereader.h" #include "qimagewriter.h" diff --git a/src/network/access/qnetworkcookie.cpp b/src/network/access/qnetworkcookie.cpp index b7cf989477..903de322ff 100644 --- a/src/network/access/qnetworkcookie.cpp +++ b/src/network/access/qnetworkcookie.cpp @@ -46,6 +46,7 @@ #include "QtCore/qdebug.h" #include "QtCore/qlist.h" #include "QtCore/qlocale.h" +#include #include "QtCore/qstring.h" #include "QtCore/qstringlist.h" #include "QtCore/qurl.h" diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp index db2186644b..40d5749cf3 100644 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp +++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp @@ -48,7 +48,11 @@ #include #include #include +#if QT_CONFIG(regularexpression) #include +#else +#include +#endif #include #include diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm index d1695ea860..5f32400af0 100644 --- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm @@ -51,7 +51,6 @@ #include "qt_mac_p.h" #include "qcocoahelpers.h" #include "qcocoaeventdispatcher.h" -#include #include #include #include diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.mm b/src/plugins/platforms/cocoa/qcocoamenuitem.mm index e54b6284e5..32fc3ab660 100644 --- a/src/plugins/platforms/cocoa/qcocoamenuitem.mm +++ b/src/plugins/platforms/cocoa/qcocoamenuitem.mm @@ -53,6 +53,7 @@ #include #include +#include QT_BEGIN_NAMESPACE diff --git a/src/plugins/sqldrivers/sqlite2/qsql_sqlite2.cpp b/src/plugins/sqldrivers/sqlite2/qsql_sqlite2.cpp index 390f05c7aa..b7bcd044ab 100644 --- a/src/plugins/sqldrivers/sqlite2/qsql_sqlite2.cpp +++ b/src/plugins/sqldrivers/sqlite2/qsql_sqlite2.cpp @@ -43,7 +43,6 @@ #include #include #include -#include #include #include #include diff --git a/src/sql/kernel/qsqlresult.cpp b/src/sql/kernel/qsqlresult.cpp index 589088238b..cc91c6d0ed 100644 --- a/src/sql/kernel/qsqlresult.cpp +++ b/src/sql/kernel/qsqlresult.cpp @@ -41,7 +41,6 @@ #include "qvariant.h" #include "qhash.h" -#include "qregexp.h" #include "qsqlerror.h" #include "qsqlfield.h" #include "qsqlrecord.h" diff --git a/src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp b/src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp index 7c6f0bdeef..522c55593f 100644 --- a/src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp +++ b/src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp @@ -32,7 +32,6 @@ #include #include #include -#include #include #include diff --git a/src/tools/rcc/rcc.cpp b/src/tools/rcc/rcc.cpp index bb4e6e3615..08fb6fca5f 100644 --- a/src/tools/rcc/rcc.cpp +++ b/src/tools/rcc/rcc.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include diff --git a/src/tools/tracegen/etw.cpp b/src/tools/tracegen/etw.cpp index e839137915..acd81bd5c1 100644 --- a/src/tools/tracegen/etw.cpp +++ b/src/tools/tracegen/etw.cpp @@ -45,7 +45,6 @@ #include #include #include -#include #include static inline QString providerVar(const QString &providerName) diff --git a/src/tools/tracegen/lttng.cpp b/src/tools/tracegen/lttng.cpp index f0fbca9e16..1aef1b3d17 100644 --- a/src/tools/tracegen/lttng.cpp +++ b/src/tools/tracegen/lttng.cpp @@ -46,7 +46,6 @@ #include #include #include -#include #include static void writeCtfMacro(QTextStream &stream, const Tracepoint::Field &field) diff --git a/src/widgets/dialogs/qcolordialog.cpp b/src/widgets/dialogs/qcolordialog.cpp index c0bacd553d..a6b6df4045 100644 --- a/src/widgets/dialogs/qcolordialog.cpp +++ b/src/widgets/dialogs/qcolordialog.cpp @@ -57,6 +57,11 @@ #include "qpainter.h" #include "qpixmap.h" #include "qpushbutton.h" +#if QT_CONFIG(regularexpression) +#include +#else +#include +#endif #if QT_CONFIG(settings) #include "qsettings.h" #endif -- cgit v1.2.3 From 7d646508c8219408f90103ed13613db8d01a4065 Mon Sep 17 00:00:00 2001 From: Alexander Kanavin Date: Mon, 25 Feb 2019 16:05:13 +0100 Subject: libinput: add support for LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE This is required to get Qt EGLFS in qemu working, as qemu mouse device issues only absolute mouse events. Fixes: QTBUG-69172 Change-Id: Ia9985dc01d7871fdcd856c14160d54d3ce684396 Reviewed-by: Johan Helsing --- .../input/libinput/qlibinputhandler.cpp | 3 +++ .../input/libinput/qlibinputpointer.cpp | 18 ++++++++++++++++++ .../input/libinput/qlibinputpointer_p.h | 1 + 3 files changed, 22 insertions(+) (limited to 'src') diff --git a/src/platformsupport/input/libinput/qlibinputhandler.cpp b/src/platformsupport/input/libinput/qlibinputhandler.cpp index 52eaa18f4b..bb81890a67 100644 --- a/src/platformsupport/input/libinput/qlibinputhandler.cpp +++ b/src/platformsupport/input/libinput/qlibinputhandler.cpp @@ -205,6 +205,9 @@ void QLibInputHandler::processEvent(libinput_event *ev) case LIBINPUT_EVENT_POINTER_MOTION: m_pointer->processMotion(libinput_event_get_pointer_event(ev)); break; + case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE: + m_pointer->processAbsMotion(libinput_event_get_pointer_event(ev)); + break; case LIBINPUT_EVENT_POINTER_AXIS: m_pointer->processAxis(libinput_event_get_pointer_event(ev)); break; diff --git a/src/platformsupport/input/libinput/qlibinputpointer.cpp b/src/platformsupport/input/libinput/qlibinputpointer.cpp index c54b61fc66..db9e81b5df 100644 --- a/src/platformsupport/input/libinput/qlibinputpointer.cpp +++ b/src/platformsupport/input/libinput/qlibinputpointer.cpp @@ -103,6 +103,24 @@ void QLibInputPointer::processMotion(libinput_event_pointer *e) Qt::NoButton, QEvent::MouseMove, mods); } +void QLibInputPointer::processAbsMotion(libinput_event_pointer *e) +{ + QScreen * const primaryScreen = QGuiApplication::primaryScreen(); + const QRect g = QHighDpi::toNativePixels(primaryScreen->virtualGeometry(), primaryScreen); + + const double x = libinput_event_pointer_get_absolute_x_transformed(e, g.width()); + const double y = libinput_event_pointer_get_absolute_y_transformed(e, g.height()); + + m_pos.setX(qBound(g.left(), qRound(g.left() + x), g.right())); + m_pos.setY(qBound(g.top(), qRound(g.top() + y), g.bottom())); + + Qt::KeyboardModifiers mods = QGuiApplicationPrivate::inputDeviceManager()->keyboardModifiers(); + + QWindowSystemInterface::handleMouseEvent(nullptr, m_pos, m_pos, m_buttons, + Qt::NoButton, QEvent::MouseMove, mods); + +} + void QLibInputPointer::processAxis(libinput_event_pointer *e) { double value; // default axis value is 15 degrees per wheel click diff --git a/src/platformsupport/input/libinput/qlibinputpointer_p.h b/src/platformsupport/input/libinput/qlibinputpointer_p.h index a7a66337f1..55d4a5f919 100644 --- a/src/platformsupport/input/libinput/qlibinputpointer_p.h +++ b/src/platformsupport/input/libinput/qlibinputpointer_p.h @@ -64,6 +64,7 @@ public: void processButton(libinput_event_pointer *e); void processMotion(libinput_event_pointer *e); + void processAbsMotion(libinput_event_pointer *e); void processAxis(libinput_event_pointer *e); void setPos(const QPoint &pos); -- cgit v1.2.3 From c17d6d4e4657416051847d2c78ef944ea8f362f8 Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Tue, 23 Apr 2019 16:13:12 +0200 Subject: Fix compiling with QHOSTINFO_DEBUG enabled Since we require getaddrinfo and freeaddrinfo, those symbols are not resolved dynamically, and will never be null, which causes compile errors. Correctly appending a string literal shuts up compiler warnings. Change-Id: I0096dca6a77ad86e0c89890444b8d7bbb38a40f2 Reviewed-by: Thiago Macieira --- src/network/kernel/qhostinfo_win.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/network/kernel/qhostinfo_win.cpp b/src/network/kernel/qhostinfo_win.cpp index c51e9968f8..ef7cff46f1 100644 --- a/src/network/kernel/qhostinfo_win.cpp +++ b/src/network/kernel/qhostinfo_win.cpp @@ -79,9 +79,8 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) QHostInfo results; #if defined(QHOSTINFO_DEBUG) - qDebug("QHostInfoAgent::fromName(): looking up \"%s\" (IPv6 support is %s)", - hostName.toLatin1().constData(), - (getaddrinfo && freeaddrinfo) ? "enabled" : "disabled"); + qDebug("QHostInfoAgent::fromName(%s) looking up...", + hostName.toLatin1().constData()); #endif QHostAddress address; @@ -129,6 +128,12 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) if (err == 0) { QList addresses; for (addrinfo *p = res; p != 0; p = p->ai_next) { +#ifdef QHOSTINFO_DEBUG + qDebug() << "getaddrinfo node: flags:" << p->ai_flags << "family:" << p->ai_family + << "ai_socktype:" << p->ai_socktype << "ai_protocol:" << p->ai_protocol + << "ai_addrlen:" << p->ai_addrlen; +#endif + switch (p->ai_family) { case AF_INET: { QHostAddress addr; @@ -163,7 +168,7 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) QString tmp; QList addresses = results.addresses(); for (int i = 0; i < addresses.count(); ++i) { - if (i != 0) tmp += ", "; + if (i != 0) tmp += QLatin1String(", "); tmp += addresses.at(i).toString(); } qDebug("QHostInfoAgent::run(): found %i entries: {%s}", -- cgit v1.2.3 From b21b07877a96c175ee51e83e1b41425c2e67beb3 Mon Sep 17 00:00:00 2001 From: Johan Klokkhammer Helsing Date: Tue, 16 Apr 2019 09:58:23 +0200 Subject: Add a QVkConvenience class with vkFormatFromGlFormat Converts from OpenGL formats to Vulkan formats. There are commented out lines for the formats in QOpenGLTexture::TextureFormat for which it was hard to find an unambiguous mapping to vkFormat. Task-number: QTBUG-75108 Change-Id: I06a7fd8df7d98cef314410ffd79ca9cff6599357 Reviewed-by: Laszlo Agocs --- .../vkconvenience/qvkconvenience.cpp | 215 +++++++++++++++++++++ .../vkconvenience/qvkconvenience_p.h | 67 +++++++ .../vkconvenience/vkconvenience.pro | 2 + 3 files changed, 284 insertions(+) create mode 100644 src/platformsupport/vkconvenience/qvkconvenience.cpp create mode 100644 src/platformsupport/vkconvenience/qvkconvenience_p.h (limited to 'src') diff --git a/src/platformsupport/vkconvenience/qvkconvenience.cpp b/src/platformsupport/vkconvenience/qvkconvenience.cpp new file mode 100644 index 0000000000..462cdc9e0d --- /dev/null +++ b/src/platformsupport/vkconvenience/qvkconvenience.cpp @@ -0,0 +1,215 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qvkconvenience_p.h" + +#include + +QT_BEGIN_NAMESPACE + +/*! + \class QVkConvenience + \brief A collection of static helper functions for Vulkan support + \since 5.14 + \internal + \ingroup qpa + */ + +VkFormat QVkConvenience::vkFormatFromGlFormat(uint glFormat) +{ + using GlFormat = QOpenGLTexture::TextureFormat; + switch (glFormat) { + case GlFormat::NoFormat: return VK_FORMAT_UNDEFINED; // GL_NONE + + // Unsigned normalized formats + case GlFormat::R8_UNorm: return VK_FORMAT_R8_UNORM; // GL_R8 + case GlFormat::RG8_UNorm: return VK_FORMAT_R8G8_UNORM; // GL_RG8 + case GlFormat::RGB8_UNorm: return VK_FORMAT_R8G8B8_UNORM; // GL_RGB8 + case GlFormat::RGBA8_UNorm: return VK_FORMAT_R8G8B8A8_UNORM; // GL_RGBA8 + + case GlFormat::R16_UNorm: return VK_FORMAT_R16_UNORM; // GL_R16 + case GlFormat::RG16_UNorm: return VK_FORMAT_R16G16_UNORM; // GL_RG16 + case GlFormat::RGB16_UNorm: return VK_FORMAT_R16G16B16_UNORM; // GL_RGB16 + case GlFormat::RGBA16_UNorm: return VK_FORMAT_R16G16B16A16_UNORM; // GL_RGBA16 + + // Signed normalized formats + case GlFormat::R8_SNorm: return VK_FORMAT_R8_SNORM; // GL_R8_SNORM + case GlFormat::RG8_SNorm: return VK_FORMAT_R8G8_SNORM; // GL_RG8_SNORM + case GlFormat::RGB8_SNorm: return VK_FORMAT_R8G8B8_SNORM; // GL_RGB8_SNORM + case GlFormat::RGBA8_SNorm: return VK_FORMAT_R8G8B8A8_SNORM; // GL_RGBA8_SNORM + + case GlFormat::R16_SNorm: return VK_FORMAT_R16_SNORM; // GL_R16_SNORM + case GlFormat::RG16_SNorm: return VK_FORMAT_R16G16_SNORM; // GL_RG16_SNORM + case GlFormat::RGB16_SNorm: return VK_FORMAT_R16G16B16_SNORM; // GL_RGB16_SNORM + case GlFormat::RGBA16_SNorm: return VK_FORMAT_R16G16B16A16_SNORM; // GL_RGBA16_SNORM + + // Unsigned integer formats + case GlFormat::R8U: return VK_FORMAT_R8_UINT; // GL_R8UI + case GlFormat::RG8U: return VK_FORMAT_R8G8_UINT; // GL_RG8UI + case GlFormat::RGB8U: return VK_FORMAT_R8G8B8_UINT; // GL_RGB8UI + case GlFormat::RGBA8U: return VK_FORMAT_R8G8B8A8_UINT; // GL_RGBA8UI + + case GlFormat::R16U: return VK_FORMAT_R16_UINT; // GL_R16UI + case GlFormat::RG16U: return VK_FORMAT_R16G16_UINT; // GL_RG16UI + case GlFormat::RGB16U: return VK_FORMAT_R16G16B16_UINT; // GL_RGB16UI + case GlFormat::RGBA16U: return VK_FORMAT_R16G16B16A16_UINT; // GL_RGBA16UI + + case GlFormat::R32U: return VK_FORMAT_R32_UINT; // GL_R32UI + case GlFormat::RG32U: return VK_FORMAT_R32G32_UINT; // GL_RG32UI + case GlFormat::RGB32U: return VK_FORMAT_R32G32B32_UINT; // GL_RGB32UI + case GlFormat::RGBA32U: return VK_FORMAT_R32G32B32A32_UINT; // GL_RGBA32UI + + // Signed integer formats + case GlFormat::R8I: return VK_FORMAT_R8_SINT; // GL_R8I + case GlFormat::RG8I: return VK_FORMAT_R8G8_SINT; // GL_RG8I + case GlFormat::RGB8I: return VK_FORMAT_R8G8B8_SINT; // GL_RGB8I + case GlFormat::RGBA8I: return VK_FORMAT_R8G8B8A8_SINT; // GL_RGBA8I + + case GlFormat::R16I: return VK_FORMAT_R16_SINT; // GL_R16I + case GlFormat::RG16I: return VK_FORMAT_R16G16_SINT; // GL_RG16I + case GlFormat::RGB16I: return VK_FORMAT_R16G16B16_SINT; // GL_RGB16I + case GlFormat::RGBA16I: return VK_FORMAT_R16G16B16A16_SINT; // GL_RGBA16I + + case GlFormat::R32I: return VK_FORMAT_R32_SINT; // GL_R32I + case GlFormat::RG32I: return VK_FORMAT_R32G32_SINT; // GL_RG32I + case GlFormat::RGB32I: return VK_FORMAT_R32G32B32_SINT; // GL_RGB32I + case GlFormat::RGBA32I: return VK_FORMAT_R32G32B32A32_SINT; // GL_RGBA32I + + // Floating point formats + case GlFormat::R16F: return VK_FORMAT_R16_SFLOAT; // GL_R16F + case GlFormat::RG16F: return VK_FORMAT_R16G16_SFLOAT; // GL_RG16F + case GlFormat::RGB16F: return VK_FORMAT_R16G16B16_SFLOAT; // GL_RGB16F + case GlFormat::RGBA16F: return VK_FORMAT_R16G16B16A16_SFLOAT; // GL_RGBA16F + + case GlFormat::R32F: return VK_FORMAT_R32_SFLOAT; // GL_R32F + case GlFormat::RG32F: return VK_FORMAT_R32G32_SFLOAT; // GL_RG32F + case GlFormat::RGB32F: return VK_FORMAT_R32G32B32_SFLOAT; // GL_RGB32F + case GlFormat::RGBA32F: return VK_FORMAT_R32G32B32A32_SFLOAT; // GL_RGBA32F + + // Packed formats + case GlFormat::RGB9E5: return VK_FORMAT_E5B9G9R9_UFLOAT_PACK32; // GL_RGB9_E5 + case GlFormat::RG11B10F: return VK_FORMAT_B10G11R11_UFLOAT_PACK32; // GL_R11F_G11F_B10F +// case GlFormat::RG3B2: return VK_FORMAT_R3_G3_B2; // GL_R3_G3_B2 + case GlFormat::R5G6B5: return VK_FORMAT_R5G6B5_UNORM_PACK16; // GL_RGB565 + case GlFormat::RGB5A1: return VK_FORMAT_R5G5B5A1_UNORM_PACK16; // GL_RGB5_A1 + case GlFormat::RGBA4: return VK_FORMAT_R4G4B4A4_UNORM_PACK16; // GL_RGBA4 + case GlFormat::RGB10A2: return VK_FORMAT_A2R10G10B10_UINT_PACK32; // GL_RGB10_A2UI + + // Depth formats +// case Format::D16: return VK_FORMAT_DEPTH_COMPONENT16; // GL_DEPTH_COMPONENT16 +// case Format::D24: return VK_FORMAT_DEPTH_COMPONENT24; // GL_DEPTH_COMPONENT24 +// case Format::D24S8: return VK_FORMAT_DEPTH24_STENCIL8; // GL_DEPTH24_STENCIL8 +// case Format::D32: return VK_FORMAT_DEPTH_COMPONENT32; // GL_DEPTH_COMPONENT32 +// case Format::D32F: return VK_FORMAT_DEPTH_COMPONENT32F; // GL_DEPTH_COMPONENT32F +// case Format::D32FS8X24: return VK_FORMAT_DEPTH32F_STENCIL8; // GL_DEPTH32F_STENCIL8 +// case Format::S8: return VK_FORMAT_STENCIL_INDEX8; // GL_STENCIL_INDEX8 + + // Compressed formats + case GlFormat::RGB_DXT1: return VK_FORMAT_BC1_RGB_UNORM_BLOCK; // GL_COMPRESSED_RGB_S3TC_DXT1_EXT + case GlFormat::RGBA_DXT1: return VK_FORMAT_BC1_RGBA_UNORM_BLOCK; // GL_COMPRESSED_RGBA_S3TC_DXT1_EXT + case GlFormat::RGBA_DXT3: return VK_FORMAT_BC2_UNORM_BLOCK; // GL_COMPRESSED_RGBA_S3TC_DXT3_EXT + case GlFormat::RGBA_DXT5: return VK_FORMAT_BC3_UNORM_BLOCK; // GL_COMPRESSED_RGBA_S3TC_DXT5_EXT + case GlFormat::R_ATI1N_UNorm: return VK_FORMAT_BC4_UNORM_BLOCK; // GL_COMPRESSED_RED_RGTC1 + case GlFormat::R_ATI1N_SNorm: return VK_FORMAT_BC4_SNORM_BLOCK; // GL_COMPRESSED_SIGNED_RED_RGTC1 + case GlFormat::RG_ATI2N_UNorm: return VK_FORMAT_BC5_UNORM_BLOCK; // GL_COMPRESSED_RG_RGTC2 + case GlFormat::RG_ATI2N_SNorm: return VK_FORMAT_BC5_SNORM_BLOCK; // GL_COMPRESSED_SIGNED_RG_RGTC2 + case GlFormat::RGB_BP_UNSIGNED_FLOAT: return VK_FORMAT_BC6H_UFLOAT_BLOCK; // GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB + case GlFormat::RGB_BP_SIGNED_FLOAT: return VK_FORMAT_BC6H_SFLOAT_BLOCK; // GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB + case GlFormat::RGB_BP_UNorm: return VK_FORMAT_BC7_UNORM_BLOCK; // GL_COMPRESSED_RGBA_BPTC_UNORM_ARB + case GlFormat::R11_EAC_UNorm: return VK_FORMAT_EAC_R11_UNORM_BLOCK; // GL_COMPRESSED_R11_EAC + case GlFormat::R11_EAC_SNorm: return VK_FORMAT_EAC_R11_SNORM_BLOCK; // GL_COMPRESSED_SIGNED_R11_EAC + case GlFormat::RG11_EAC_UNorm: return VK_FORMAT_EAC_R11G11_UNORM_BLOCK; // GL_COMPRESSED_RG11_EAC + case GlFormat::RG11_EAC_SNorm: return VK_FORMAT_EAC_R11G11_SNORM_BLOCK; // GL_COMPRESSED_SIGNED_RG11_EAC + case GlFormat::RGB8_ETC2: return VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK; // GL_COMPRESSED_RGB8_ETC2 + case GlFormat::SRGB8_ETC2: return VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ETC2 + case GlFormat::RGB8_PunchThrough_Alpha1_ETC2: return VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK; // GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 + case GlFormat::SRGB8_PunchThrough_Alpha1_ETC2: return VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 + case GlFormat::RGBA8_ETC2_EAC: return VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK; // GL_COMPRESSED_RGBA8_ETC2_EAC + case GlFormat::SRGB8_Alpha8_ETC2_EAC: return VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC +// case GlFormat::RGB8_ETC1: return VK_FORMAT_ETC1_RGB8_OES; // GL_ETC1_RGB8_OES + case GlFormat::RGBA_ASTC_4x4: return VK_FORMAT_ASTC_4x4_UNORM_BLOCK; // GL_COMPRESSED_RGBA_ASTC_4x4_KHR + case GlFormat::RGBA_ASTC_5x4: return VK_FORMAT_ASTC_5x4_UNORM_BLOCK; // GL_COMPRESSED_RGBA_ASTC_5x4_KHR + case GlFormat::RGBA_ASTC_5x5: return VK_FORMAT_ASTC_5x5_UNORM_BLOCK; // GL_COMPRESSED_RGBA_ASTC_5x5_KHR + case GlFormat::RGBA_ASTC_6x5: return VK_FORMAT_ASTC_6x5_UNORM_BLOCK; // GL_COMPRESSED_RGBA_ASTC_6x5_KHR + case GlFormat::RGBA_ASTC_6x6: return VK_FORMAT_ASTC_6x6_UNORM_BLOCK; // GL_COMPRESSED_RGBA_ASTC_6x6_KHR + case GlFormat::RGBA_ASTC_8x5: return VK_FORMAT_ASTC_8x5_UNORM_BLOCK; // GL_COMPRESSED_RGBA_ASTC_8x5_KHR + case GlFormat::RGBA_ASTC_8x6: return VK_FORMAT_ASTC_8x6_UNORM_BLOCK; // GL_COMPRESSED_RGBA_ASTC_8x6_KHR + case GlFormat::RGBA_ASTC_8x8: return VK_FORMAT_ASTC_8x8_UNORM_BLOCK; // GL_COMPRESSED_RGBA_ASTC_8x8_KHR + case GlFormat::RGBA_ASTC_10x5: return VK_FORMAT_ASTC_10x5_UNORM_BLOCK; // GL_COMPRESSED_RGBA_ASTC_10x5_KHR + case GlFormat::RGBA_ASTC_10x6: return VK_FORMAT_ASTC_10x6_UNORM_BLOCK; // GL_COMPRESSED_RGBA_ASTC_10x6_KHR + case GlFormat::RGBA_ASTC_10x8: return VK_FORMAT_ASTC_10x8_UNORM_BLOCK; // GL_COMPRESSED_RGBA_ASTC_10x8_KHR + case GlFormat::RGBA_ASTC_10x10: return VK_FORMAT_ASTC_10x10_UNORM_BLOCK; // GL_COMPRESSED_RGBA_ASTC_10x10_KHR + case GlFormat::RGBA_ASTC_12x10: return VK_FORMAT_ASTC_12x10_UNORM_BLOCK; // GL_COMPRESSED_RGBA_ASTC_12x10_KHR + case GlFormat::RGBA_ASTC_12x12: return VK_FORMAT_ASTC_12x12_UNORM_BLOCK; // GL_COMPRESSED_RGBA_ASTC_12x12_KHR + case GlFormat::SRGB8_Alpha8_ASTC_4x4: return VK_FORMAT_ASTC_4x4_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR + case GlFormat::SRGB8_Alpha8_ASTC_5x4: return VK_FORMAT_ASTC_5x4_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR + case GlFormat::SRGB8_Alpha8_ASTC_5x5: return VK_FORMAT_ASTC_5x5_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR + case GlFormat::SRGB8_Alpha8_ASTC_6x5: return VK_FORMAT_ASTC_6x5_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR + case GlFormat::SRGB8_Alpha8_ASTC_6x6: return VK_FORMAT_ASTC_6x6_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR + case GlFormat::SRGB8_Alpha8_ASTC_8x5: return VK_FORMAT_ASTC_8x5_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR + case GlFormat::SRGB8_Alpha8_ASTC_8x6: return VK_FORMAT_ASTC_8x6_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR + case GlFormat::SRGB8_Alpha8_ASTC_8x8: return VK_FORMAT_ASTC_8x8_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR + case GlFormat::SRGB8_Alpha8_ASTC_10x5: return VK_FORMAT_ASTC_10x5_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR + case GlFormat::SRGB8_Alpha8_ASTC_10x6: return VK_FORMAT_ASTC_10x6_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR + case GlFormat::SRGB8_Alpha8_ASTC_10x8: return VK_FORMAT_ASTC_10x8_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR + case GlFormat::SRGB8_Alpha8_ASTC_10x10: return VK_FORMAT_ASTC_10x10_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR + case GlFormat::SRGB8_Alpha8_ASTC_12x10: return VK_FORMAT_ASTC_12x10_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR + case GlFormat::SRGB8_Alpha8_ASTC_12x12: return VK_FORMAT_ASTC_12x12_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR + + // sRGB formats + case GlFormat::SRGB8: return VK_FORMAT_R8G8B8_SRGB; // GL_SRGB8 + case GlFormat::SRGB8_Alpha8: return VK_FORMAT_R8G8B8A8_SRGB; // GL_SRGB8_ALPHA8 + case GlFormat::SRGB_DXT1: return VK_FORMAT_BC1_RGB_SRGB_BLOCK; // GL_COMPRESSED_SRGB_S3TC_DXT1_EXT + case GlFormat::SRGB_Alpha_DXT1: return VK_FORMAT_BC1_RGBA_SRGB_BLOCK; // GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT + case GlFormat::SRGB_Alpha_DXT3: return VK_FORMAT_BC2_SRGB_BLOCK; // GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT + case GlFormat::SRGB_Alpha_DXT5: return VK_FORMAT_BC3_SRGB_BLOCK; // GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT + case GlFormat::SRGB_BP_UNorm: return VK_FORMAT_BC7_SRGB_BLOCK; // GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB + + // ES 2 formats +// case GlFormat::DepthFormat: return VK_FORMAT_DEPTH_COMPONENT; // GL_DEPTH_COMPONENT +// case GlFormat::AlphaFormat: return VK_FORMAT_ALPHA; // GL_ALPHA +// case GlFormat::RGBFormat: return VK_FORMAT_RGB; // GL_RGB +// case GlFormat::RGBAFormat: return VK_FORMAT_RGBA; // GL_RGBA +// case GlFormat::LuminanceFormat: return VK_FORMAT_LUMINANCE; // GL_LUMINANCE +// case GlFormat::LuminanceAlphaFormat: return VK_FORMAT; + default: return VK_FORMAT_UNDEFINED; + } +} + +QT_END_NAMESPACE diff --git a/src/platformsupport/vkconvenience/qvkconvenience_p.h b/src/platformsupport/vkconvenience/qvkconvenience_p.h new file mode 100644 index 0000000000..1dd1dfc4a7 --- /dev/null +++ b/src/platformsupport/vkconvenience/qvkconvenience_p.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QVKCONVENIENCE_P_H +#define QVKCONVENIENCE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include + +QT_BEGIN_NAMESPACE + +class QVkConvenience +{ +public: + static VkFormat vkFormatFromGlFormat(uint glFormat); +}; + +QT_END_NAMESPACE + +#endif // QVKCONVENIENCE_P_H diff --git a/src/platformsupport/vkconvenience/vkconvenience.pro b/src/platformsupport/vkconvenience/vkconvenience.pro index 7a4cdb041d..ee540024cf 100644 --- a/src/platformsupport/vkconvenience/vkconvenience.pro +++ b/src/platformsupport/vkconvenience/vkconvenience.pro @@ -8,9 +8,11 @@ DEFINES += QT_NO_CAST_FROM_ASCII PRECOMPILED_HEADER = ../../corelib/global/qt_pch.h SOURCES += \ + qvkconvenience.cpp \ qbasicvulkanplatforminstance.cpp HEADERS += \ + qvkconvenience_p.h \ qbasicvulkanplatforminstance_p.h load(qt_module) -- cgit v1.2.3 From 2eb849ed516afc8e602dbec3da0ac12db2cdf8ec Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Thu, 21 Feb 2019 20:54:03 +0100 Subject: Implement std::numeric_limits This shall make it more nearly a first-class numeric type; in particular, I need some of these for testlib's comparing and formatting of float16 to handle NaNs and infinities sensibly. Change-Id: Ic894dd0eb3e05653cd7645ab496463e7a884dff8 Reviewed-by: Qt CI Bot Reviewed-by: Thiago Macieira --- src/corelib/global/qfloat16.h | 71 ++++++++++++++++++++++++++++++++ src/corelib/serialization/qcborvalue.cpp | 4 +- 2 files changed, 73 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/corelib/global/qfloat16.h b/src/corelib/global/qfloat16.h index 243aea98be..4c3f9ca063 100644 --- a/src/corelib/global/qfloat16.h +++ b/src/corelib/global/qfloat16.h @@ -1,5 +1,6 @@ /**************************************************************************** ** +** Copyright (C) 2019 The Qt Company Ltd. ** Copyright (C) 2016 by Southwest Research Institute (R) ** Contact: http://www.qt-project.org/legal ** @@ -66,6 +67,13 @@ QT_BEGIN_NAMESPACE class qfloat16 { + struct Wrap + { + // To let our private constructor work, without other code seeing + // ambiguity when constructing from int, double &c. + quint16 b16; + constexpr inline explicit Wrap(int value) : b16(value) {} + }; public: constexpr inline qfloat16() noexcept : b16(0) {} inline qfloat16(float f) noexcept; @@ -75,8 +83,20 @@ public: bool isInf() const noexcept { return ((b16 >> 8) & 0x7e) == 0x7c; } bool isNaN() const noexcept { return ((b16 >> 8) & 0x7e) == 0x7e; } bool isFinite() const noexcept { return ((b16 >> 8) & 0x7c) != 0x7c; } + // Support for std::numeric_limits + static constexpr qfloat16 _limit_epsilon() noexcept { return qfloat16(Wrap(0x1400)); } + static constexpr qfloat16 _limit_min() noexcept { return qfloat16(Wrap(0x400)); } + static constexpr qfloat16 _limit_denorm_min() noexcept { return qfloat16(Wrap(1)); } + static constexpr qfloat16 _limit_max() noexcept { return qfloat16(Wrap(0x7bff)); } + static constexpr qfloat16 _limit_lowest() noexcept { return qfloat16(Wrap(0xfbff)); } + static constexpr qfloat16 _limit_infinity() noexcept { return qfloat16(Wrap(0x7c00)); } + static constexpr qfloat16 _limit_quiet_NaN() noexcept { return qfloat16(Wrap(0x7e00)); } + // Signalling NaN is 0x7f00 + inline constexpr bool isNormal() const noexcept + { return b16 == 0 || ((b16 & 0x7c00) && (b16 & 0x7c00) != 0x7c00); } private: quint16 b16; + constexpr inline explicit qfloat16(Wrap nibble) noexcept : b16(nibble.b16) {} Q_CORE_EXPORT static const quint32 mantissatable[]; Q_CORE_EXPORT static const quint32 exponenttable[]; @@ -263,4 +283,55 @@ QT_END_NAMESPACE Q_DECLARE_METATYPE(qfloat16) +namespace std { +template<> +class numeric_limits : public numeric_limits +{ +public: + /* + Treat quint16 b16 as if it were: + uint S: 1; // b16 >> 15 (sign) + uint E: 5; // (b16 >> 10) & 0x1f (offset exponent) + uint M: 10; // b16 & 0x3ff (adjusted mantissa) + + for E == 0: magnitude is M / 2.^{24} + for 0 < E < 31: magnitude is (1. + M / 2.^{10}) * 2.^{E - 15) + for E == 31: not finite + */ + static constexpr int digits = 11; + static constexpr int min_exponent = -13; + static constexpr int max_exponent = 16; + + static constexpr int digits10 = 3; + static constexpr int max_digits10 = 5; + static constexpr int min_exponent10 = -4; + static constexpr int max_exponent10 = 4; + + static constexpr QT_PREPEND_NAMESPACE(qfloat16) epsilon() + { return QT_PREPEND_NAMESPACE(qfloat16)::_limit_epsilon(); } + static constexpr QT_PREPEND_NAMESPACE(qfloat16) (min)() + { return QT_PREPEND_NAMESPACE(qfloat16)::_limit_min(); } + static constexpr QT_PREPEND_NAMESPACE(qfloat16) denorm_min() + { return QT_PREPEND_NAMESPACE(qfloat16)::_limit_denorm_min(); } + static constexpr QT_PREPEND_NAMESPACE(qfloat16) (max)() + { return QT_PREPEND_NAMESPACE(qfloat16)::_limit_max(); } + static constexpr QT_PREPEND_NAMESPACE(qfloat16) lowest() + { return QT_PREPEND_NAMESPACE(qfloat16)::_limit_lowest(); } + static constexpr QT_PREPEND_NAMESPACE(qfloat16) infinity() + { return QT_PREPEND_NAMESPACE(qfloat16)::_limit_infinity(); } + static constexpr QT_PREPEND_NAMESPACE(qfloat16) quiet_NaN() + { return QT_PREPEND_NAMESPACE(qfloat16)::_limit_quiet_NaN(); } +}; + +template<> class numeric_limits + : public numeric_limits {}; +template<> class numeric_limits + : public numeric_limits {}; +template<> class numeric_limits + : public numeric_limits {}; + +// Adding overloads to std isn't allowed, so we can't extend this to support +// for fpclassify(), isnormal() &c. (which, furthermore, are macros on MinGW). +} // namespace std + #endif // QFLOAT16_H diff --git a/src/corelib/serialization/qcborvalue.cpp b/src/corelib/serialization/qcborvalue.cpp index 288446878c..d469735ae9 100644 --- a/src/corelib/serialization/qcborvalue.cpp +++ b/src/corelib/serialization/qcborvalue.cpp @@ -766,8 +766,8 @@ static void writeDoubleToCbor(QCborStreamWriter &writer, double d, QCborValue::E if (qt_is_nan(d)) { if (opt & QCborValue::UseFloat16) { if ((opt & QCborValue::UseFloat16) == QCborValue::UseFloat16) - return writer.append(qfloat16(qt_qnan())); - return writer.append(float(qt_qnan())); + return writer.append(std::numeric_limits::quiet_NaN()); + return writer.append(std::numeric_limits::quiet_NaN()); } return writer.append(qt_qnan()); } -- cgit v1.2.3 From 934000c11afe8b03c81a8f52f3a51be6615087c6 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Fri, 22 Mar 2019 16:03:59 +0100 Subject: Implement qFpClassify(qfloat16) This extends support for qfloat16 sufficiently for the things testlib needs in order to treat it as a first-class citizen. Extended tests for qfloat to check qFpClassify() on it. Change-Id: I906292afaf51cd9c94ba384ff5aaa855edd56da1 Reviewed-by: Thiago Macieira --- src/corelib/global/qfloat16.cpp | 13 +++++++++++++ src/corelib/global/qfloat16.h | 2 ++ 2 files changed, 15 insertions(+) (limited to 'src') diff --git a/src/corelib/global/qfloat16.cpp b/src/corelib/global/qfloat16.cpp index 680268c59b..2bf6ff00c2 100644 --- a/src/corelib/global/qfloat16.cpp +++ b/src/corelib/global/qfloat16.cpp @@ -1,5 +1,6 @@ /**************************************************************************** ** +** Copyright (C) 2019 The Qt Company Ltd. ** Copyright (C) 2016 by Southwest Research Institute (R) ** Contact: http://www.qt-project.org/legal ** @@ -39,6 +40,7 @@ #include "qfloat16.h" #include "private/qsimd_p.h" +#include // for fpclassify()'s return values QT_BEGIN_NAMESPACE @@ -91,6 +93,17 @@ QT_BEGIN_NAMESPACE \sa qIsFinite */ +/*! + \internal + Implements qFpClassify() for qfloat16. + */ + +int qfloat16::fpClassify() const noexcept +{ + return isInf() ? FP_INFINITE : isNaN() ? FP_NAN + : !b16 ? FP_ZERO : isNormal() ? FP_NORMAL : FP_SUBNORMAL; +} + /*! \fn int qRound(qfloat16 value) \relates diff --git a/src/corelib/global/qfloat16.h b/src/corelib/global/qfloat16.h index 4c3f9ca063..6f798f8b8f 100644 --- a/src/corelib/global/qfloat16.h +++ b/src/corelib/global/qfloat16.h @@ -83,6 +83,7 @@ public: bool isInf() const noexcept { return ((b16 >> 8) & 0x7e) == 0x7c; } bool isNaN() const noexcept { return ((b16 >> 8) & 0x7e) == 0x7e; } bool isFinite() const noexcept { return ((b16 >> 8) & 0x7c) != 0x7c; } + Q_CORE_EXPORT int fpClassify() const noexcept; // Support for std::numeric_limits static constexpr qfloat16 _limit_epsilon() noexcept { return qfloat16(Wrap(0x1400)); } static constexpr qfloat16 _limit_min() noexcept { return qfloat16(Wrap(0x400)); } @@ -117,6 +118,7 @@ Q_CORE_EXPORT void qFloatFromFloat16(float *, const qfloat16 *, qsizetype length Q_REQUIRED_RESULT inline bool qIsInf(qfloat16 f) noexcept { return f.isInf(); } Q_REQUIRED_RESULT inline bool qIsNaN(qfloat16 f) noexcept { return f.isNaN(); } Q_REQUIRED_RESULT inline bool qIsFinite(qfloat16 f) noexcept { return f.isFinite(); } +Q_REQUIRED_RESULT inline int qFpClassify(qfloat16 f) noexcept { return f.fpClassify(); } // Q_REQUIRED_RESULT quint32 qFloatDistance(qfloat16 a, qfloat16 b); // The remainder of these utility functions complement qglobal.h -- cgit v1.2.3 From 3abfa4dfff08d9d2ab9aeb474656b36076a48b3b Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Wed, 21 Nov 2018 14:36:08 +0100 Subject: QtTestLib: handle float16 the same as double and float In QCOMPARE, handle NaNs and infinities the way tests want them handled, rather than by strict IEEE rules. In particular, if a test expects NaN, this lets it treat that just like any other expected value, despite NaN != NaN as float16 values. Likewise, format infinities and NaNs specially in toString() so that they're reported consistently. Enable the qfloat16 tests that depend on this QCOMPARE() behavior. Refise the testlib selftest's float test to test qfloat16 the same way it tests float and double (and format the test the same way). This is a follow-up to 37f617c405a. Change-Id: I433256a09b1657e6725d68d07c5f80d805bf586a Reviewed-by: Thiago Macieira --- src/testlib/qtestcase.cpp | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index db44b3860a..cad29b5326 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -2539,7 +2539,8 @@ static bool floatingCompare(const T &t1, const T &t2) bool QTest::qCompare(qfloat16 const &t1, qfloat16 const &t2, const char *actual, const char *expected, const char *file, int line) { - return compare_helper(qFuzzyCompare(t1, t2), "Compared qfloat16s are not the same (fuzzy compare)", + return compare_helper(floatingCompare(t1, t2), + "Compared qfloat16s are not the same (fuzzy compare)", toString(t1), toString(t2), actual, expected, file, line); } @@ -2646,16 +2647,10 @@ template <> Q_TESTLIB_EXPORT char *QTest::toString(const TYPE &t) \ return msg; \ } +TO_STRING_FLOAT(qfloat16, %.3g) TO_STRING_FLOAT(float, %g) TO_STRING_FLOAT(double, %.12g) -template <> Q_TESTLIB_EXPORT char *QTest::toString(const qfloat16 &t) -{ - char *msg = new char[16]; - qsnprintf(msg, 16, "%.3g", static_cast(t)); - return msg; -} - template <> Q_TESTLIB_EXPORT char *QTest::toString(const char &t) { unsigned char c = static_cast(t); -- cgit v1.2.3 From 80853afd732aba126caa138ac421b036d2005f8d Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Thu, 23 Aug 2018 18:04:07 +0200 Subject: Add startOfDay() and endOfDay() methods to QDate These methods give the first and last QDateTime values in the given day, for a given time-zone or time-spec. These are usually the relevant midnight, or the millisecond before, except when time-zone transitions (typically DST changes) skip it, when care is needed to select the right moment. Adapted some code to make use of the new API, eliminating some old cruft from qdatetimeparser_p.h in the process. [ChangeLog][QtCore][QDate] Added startOfDay() and endOfDay() methods to provide a QDateTime at the start and end of a given date, taking account of any time skipped by transitions, e.g. a DST spring-forward, which can lead to a day starting at 01:00 or ending just before 23:00. Task-number: QTBUG-64485 Change-Id: I3dd7a34bedfbec8f8af00c43d13f50f99346ecd0 Reviewed-by: Thiago Macieira --- .../snippets/code/src_corelib_tools_qdatetime.cpp | 2 +- src/corelib/tools/qdatetime.cpp | 271 ++++++++++++++++++++- src/corelib/tools/qdatetime.h | 10 +- src/corelib/tools/qdatetimeparser.cpp | 10 +- src/corelib/tools/qdatetimeparser_p.h | 7 +- src/widgets/widgets/qabstractspinbox.cpp | 2 +- src/widgets/widgets/qdatetimeedit.cpp | 19 +- 7 files changed, 294 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qdatetime.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qdatetime.cpp index 3ecb67a48f..a477e91548 100644 --- a/src/corelib/doc/snippets/code/src_corelib_tools_qdatetime.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_tools_qdatetime.cpp @@ -128,7 +128,7 @@ qDebug("Time elapsed: %d ms", t.elapsed()); //! [11] QDateTime now = QDateTime::currentDateTime(); -QDateTime xmas(QDate(now.date().year(), 12, 25), QTime(0, 0)); +QDateTime xmas(QDate(now.date().year(), 12, 25).startOfDay()); qDebug("There are %d seconds to Christmas", now.secsTo(xmas)); //! [11] diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index 6fa735dab7..cc98f80feb 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2017 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Copyright (C) 2016 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** @@ -617,6 +617,268 @@ int QDate::weekNumber(int *yearNumber) const return week; } +static bool inDateTimeRange(qint64 jd, bool start) +{ + using Bounds = std::numeric_limits; + if (jd < Bounds::min() + JULIAN_DAY_FOR_EPOCH) + return false; + jd -= JULIAN_DAY_FOR_EPOCH; + const qint64 maxDay = Bounds::max() / MSECS_PER_DAY; + const qint64 minDay = Bounds::min() / MSECS_PER_DAY - 1; + // (Divisions rounded towards zero, as MSECS_PER_DAY has factors other than two.) + // Range includes start of last day and end of first: + if (start) + return jd > minDay && jd <= maxDay; + return jd >= minDay && jd < maxDay; +} + +static QDateTime toEarliest(const QDate &day, const QDateTime &form) +{ + const Qt::TimeSpec spec = form.timeSpec(); + const int offset = (spec == Qt::OffsetFromUTC) ? form.offsetFromUtc() : 0; +#if QT_CONFIG(timezone) + QTimeZone zone; + if (spec == Qt::TimeZone) + zone = form.timeZone(); +#endif + auto moment = [=](QTime time) { + switch (spec) { + case Qt::OffsetFromUTC: return QDateTime(day, time, spec, offset); +#if QT_CONFIG(timezone) + case Qt::TimeZone: return QDateTime(day, time, zone); +#endif + default: return QDateTime(day, time, spec); + } + }; + // Longest routine time-zone transition is 2 hours: + QDateTime when = moment(QTime(2, 0)); + if (!when.isValid()) { + // Noon should be safe ... + when = moment(QTime(12, 0)); + if (!when.isValid()) { + // ... unless it's a 24-hour jump (moving the date-line) + when = moment(QTime(23, 59, 59, 999)); + if (!when.isValid()) + return QDateTime(); + } + } + int high = when.time().msecsSinceStartOfDay() / 60000; + int low = 0; + // Binary chop to the right minute + while (high > low + 1) { + int mid = (high + low) / 2; + QDateTime probe = moment(QTime(mid / 60, mid % 60)); + if (probe.isValid() && probe.date() == day) { + high = mid; + when = probe; + } else { + low = mid; + } + } + return when; +} + +/*! + \since 5.14 + \fn QDateTime QDate::startOfDay(Qt::TimeSpec spec, int offsetSeconds) const + \fn QDateTime QDate::startOfDay(const QTimeZone &zone) const + + Returns the start-moment of the day. Usually, this shall be midnight at the + start of the day: however, if a time-zone transition causes the given date + to skip over that midnight (e.g. a DST spring-forward skipping from the end + of the previous day to 01:00 of the new day), the actual earliest time in + the day is returned. This can only arise when the start-moment is specified + in terms of a time-zone (by passing its QTimeZone as \a zone) or in terms of + local time (by passing Qt::LocalTime as \a spec; this is its default). + + The \a offsetSeconds is ignored unless \a spec is Qt::OffsetFromUTC, when it + gives the implied zone's offset from UTC. As UTC and such zones have no + transitions, the start of the day is QTime(0, 0) in these cases. + + In the rare case of a date that was entirely skipped (this happens when a + zone east of the international date-line switches to being west of it), the + return shall be invalid. Passing Qt::TimeZone as \a spec (instead of + passing a QTimeZone) or passing an invalid time-zone as \a zone will also + produce an invalid result, as shall dates that start outside the range + representable by QDateTime. + + \sa endOfDay() +*/ +QDateTime QDate::startOfDay(Qt::TimeSpec spec, int offsetSeconds) const +{ + if (!inDateTimeRange(jd, true)) + return QDateTime(); + + switch (spec) { + case Qt::TimeZone: // should pass a QTimeZone instead of Qt::TimeZone + qWarning() << "Called QDate::startOfDay(Qt::TimeZone) on" << *this; + return QDateTime(); + case Qt::OffsetFromUTC: + case Qt::UTC: + return QDateTime(*this, QTime(0, 0), spec, offsetSeconds); + + case Qt::LocalTime: + if (offsetSeconds) + qWarning("Ignoring offset (%d seconds) passed with Qt::LocalTime", offsetSeconds); + break; + } + QDateTime when(*this, QTime(0, 0), spec); + if (!when.isValid()) + when = toEarliest(*this, when); + + return when.isValid() ? when : QDateTime(); +} + +#if QT_CONFIG(timezone) +/*! + \overload + \since 5.14 +*/ +QDateTime QDate::startOfDay(const QTimeZone &zone) const +{ + if (!inDateTimeRange(jd, true) || !zone.isValid()) + return QDateTime(); + + QDateTime when(*this, QTime(0, 0), zone); + if (when.isValid()) + return when; + + // The start of the day must have fallen in a spring-forward's gap; find the spring-forward: + if (zone.hasTransitions()) { + QTimeZone::OffsetData tran = zone.previousTransition(QDateTime(*this, QTime(23, 59, 59, 999), zone)); + const QDateTime &at = tran.atUtc.toTimeZone(zone); + if (at.isValid() && at.date() == *this) + return at; + } + + when = toEarliest(*this, when); + return when.isValid() ? when : QDateTime(); +} +#endif // timezone + +static QDateTime toLatest(const QDate &day, const QDateTime &form) +{ + const Qt::TimeSpec spec = form.timeSpec(); + const int offset = (spec == Qt::OffsetFromUTC) ? form.offsetFromUtc() : 0; +#if QT_CONFIG(timezone) + QTimeZone zone; + if (spec == Qt::TimeZone) + zone = form.timeZone(); +#endif + auto moment = [=](QTime time) { + switch (spec) { + case Qt::OffsetFromUTC: return QDateTime(day, time, spec, offset); +#if QT_CONFIG(timezone) + case Qt::TimeZone: return QDateTime(day, time, zone); +#endif + default: return QDateTime(day, time, spec); + } + }; + // Longest routine time-zone transition is 2 hours: + QDateTime when = moment(QTime(21, 59, 59, 999)); + if (!when.isValid()) { + // Noon should be safe ... + when = moment(QTime(12, 0)); + if (!when.isValid()) { + // ... unless it's a 24-hour jump (moving the date-line) + when = moment(QTime(0, 0)); + if (!when.isValid()) + return QDateTime(); + } + } + int high = 24 * 60; + int low = when.time().msecsSinceStartOfDay() / 60000; + // Binary chop to the right minute + while (high > low + 1) { + int mid = (high + low) / 2; + QDateTime probe = moment(QTime(mid / 60, mid % 60, 59, 999)); + if (probe.isValid() && probe.date() == day) { + low = mid; + when = probe; + } else { + high = mid; + } + } + return when; +} + +/*! + \since 5.14 + \fn QDateTime QDate::endOfDay(Qt::TimeSpec spec, int offsetSeconds) const + \fn QDateTime QDate::endOfDay(const QTimeZone &zone) const + + Returns the end-moment of the day. Usually, this is one millisecond before + the midnight at the end of the day: however, if a time-zone transition + causes the given date to skip over that midnight (e.g. a DST spring-forward + skipping from just before 23:00 to the start of the next day), the actual + latest time in the day is returned. This can only arise when the + start-moment is specified in terms of a time-zone (by passing its QTimeZone + as \a zone) or in terms of local time (by passing Qt::LocalTime as \a spec; + this is its default). + + The \a offsetSeconds is ignored unless \a spec is Qt::OffsetFromUTC, when it + gives the implied zone's offset from UTC. As UTC and such zones have no + transitions, the end of the day is QTime(23, 59, 59, 999) in these cases. + + In the rare case of a date that was entirely skipped (this happens when a + zone east of the international date-line switches to being west of it), the + return shall be invalid. Passing Qt::TimeZone as \a spec (instead of + passing a QTimeZone) will also produce an invalid result, as shall dates + that end outside the range representable by QDateTime. + + \sa startOfDay() +*/ +QDateTime QDate::endOfDay(Qt::TimeSpec spec, int offsetSeconds) const +{ + if (!inDateTimeRange(jd, false)) + return QDateTime(); + + switch (spec) { + case Qt::TimeZone: // should pass a QTimeZone instead of Qt::TimeZone + qWarning() << "Called QDate::endOfDay(Qt::TimeZone) on" << *this; + return QDateTime(); + case Qt::UTC: + case Qt::OffsetFromUTC: + return QDateTime(*this, QTime(23, 59, 59, 999), spec, offsetSeconds); + + case Qt::LocalTime: + if (offsetSeconds) + qWarning("Ignoring offset (%d seconds) passed with Qt::LocalTime", offsetSeconds); + break; + } + QDateTime when(*this, QTime(23, 59, 59, 999), spec); + if (!when.isValid()) + when = toLatest(*this, when); + return when.isValid() ? when : QDateTime(); +} + +#if QT_CONFIG(timezone) +/*! + \overload + \since 5.14 +*/ +QDateTime QDate::endOfDay(const QTimeZone &zone) const +{ + if (!inDateTimeRange(jd, false) || !zone.isValid()) + return QDateTime(); + + QDateTime when(*this, QTime(23, 59, 59, 999), zone); + if (when.isValid()) + return when; + + // The end of the day must have fallen in a spring-forward's gap; find the spring-forward: + if (zone.hasTransitions()) { + QTimeZone::OffsetData tran = zone.nextTransition(QDateTime(*this, QTime(0, 0), zone)); + const QDateTime &at = tran.atUtc.toTimeZone(zone); + if (at.isValid() && at.date() == *this) + return at; + } + + when = toLatest(*this, when); + return when.isValid() ? when : QDateTime(); +} +#endif // timezone + #if QT_DEPRECATED_SINCE(5, 11) && QT_CONFIG(textdate) /*! \since 4.5 @@ -1468,7 +1730,8 @@ bool QDate::isLeapYear(int y) \fn QTime::QTime() Constructs a null time object. For a null time, isNull() returns \c true and - isValid() returns \c false. If you need a zero time, use QTime(0, 0). + isValid() returns \c false. If you need a zero time, use QTime(0, 0). For + the start of a day, see QDate::startOfDay(). \sa isNull(), isValid() */ @@ -2392,8 +2655,8 @@ static void msecsToTime(qint64 msecs, QDate *date, QTime *time) qint64 jd = JULIAN_DAY_FOR_EPOCH; qint64 ds = 0; - if (qAbs(msecs) >= MSECS_PER_DAY) { - jd += (msecs / MSECS_PER_DAY); + if (msecs >= MSECS_PER_DAY || msecs <= -MSECS_PER_DAY) { + jd += msecs / MSECS_PER_DAY; msecs %= MSECS_PER_DAY; } diff --git a/src/corelib/tools/qdatetime.h b/src/corelib/tools/qdatetime.h index 51d5dd9759..8873651f17 100644 --- a/src/corelib/tools/qdatetime.h +++ b/src/corelib/tools/qdatetime.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2017 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Copyright (C) 2016 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** @@ -55,6 +55,7 @@ Q_FORWARD_DECLARE_OBJC_CLASS(NSDate); QT_BEGIN_NAMESPACE class QTimeZone; +class QDateTime; class Q_CORE_EXPORT QDate { @@ -81,6 +82,13 @@ public: int daysInYear() const; int weekNumber(int *yearNum = nullptr) const; + QDateTime startOfDay(Qt::TimeSpec spec = Qt::LocalTime, int offsetSeconds = 0) const; + QDateTime endOfDay(Qt::TimeSpec spec = Qt::LocalTime, int offsetSeconds = 0) const; +#if QT_CONFIG(timezone) + QDateTime startOfDay(const QTimeZone &zone) const; + QDateTime endOfDay(const QTimeZone &zone) const; +#endif + #if QT_DEPRECATED_SINCE(5, 10) && QT_CONFIG(textdate) QT_DEPRECATED_X("Use QLocale::monthName or QLocale::standaloneMonthName") static QString shortMonthName(int month, MonthNameType type = DateFormat); diff --git a/src/corelib/tools/qdatetimeparser.cpp b/src/corelib/tools/qdatetimeparser.cpp index 5d1704daeb..e1dc596d2d 100644 --- a/src/corelib/tools/qdatetimeparser.cpp +++ b/src/corelib/tools/qdatetimeparser.cpp @@ -1982,7 +1982,7 @@ QString QDateTimeParser::stateName(State s) const #if QT_CONFIG(datestring) bool QDateTimeParser::fromString(const QString &t, QDate *date, QTime *time) const { - QDateTime val(QDate(1900, 1, 1), QDATETIMEEDIT_TIME_MIN); + QDateTime val(QDate(1900, 1, 1).startOfDay()); const StateNode tmp = parse(t, -1, val, false); if (tmp.state != Acceptable || tmp.conflicts) { return false; @@ -2010,20 +2010,20 @@ QDateTime QDateTimeParser::getMinimum() const { // Cache the most common case if (spec == Qt::LocalTime) { - static const QDateTime localTimeMin(QDATETIMEEDIT_DATE_MIN, QDATETIMEEDIT_TIME_MIN, Qt::LocalTime); + static const QDateTime localTimeMin(QDATETIMEEDIT_DATE_MIN.startOfDay(Qt::LocalTime)); return localTimeMin; } - return QDateTime(QDATETIMEEDIT_DATE_MIN, QDATETIMEEDIT_TIME_MIN, spec); + return QDateTime(QDATETIMEEDIT_DATE_MIN.startOfDay(spec)); } QDateTime QDateTimeParser::getMaximum() const { // Cache the most common case if (spec == Qt::LocalTime) { - static const QDateTime localTimeMax(QDATETIMEEDIT_DATE_MAX, QDATETIMEEDIT_TIME_MAX, Qt::LocalTime); + static const QDateTime localTimeMax(QDATETIMEEDIT_DATE_MAX.endOfDay(Qt::LocalTime)); return localTimeMax; } - return QDateTime(QDATETIMEEDIT_DATE_MAX, QDATETIMEEDIT_TIME_MAX, spec); + return QDateTime(QDATETIMEEDIT_DATE_MAX.endOfDay(spec)); } QString QDateTimeParser::getAmPmText(AmPm ap, Case cs) const diff --git a/src/corelib/tools/qdatetimeparser_p.h b/src/corelib/tools/qdatetimeparser_p.h index e244fed09a..d9e39f0795 100644 --- a/src/corelib/tools/qdatetimeparser_p.h +++ b/src/corelib/tools/qdatetimeparser_p.h @@ -65,14 +65,11 @@ QT_REQUIRE_CONFIG(datetimeparser); -#define QDATETIMEEDIT_TIME_MIN QTime(0, 0, 0, 0) -#define QDATETIMEEDIT_TIME_MAX QTime(23, 59, 59, 999) +#define QDATETIMEEDIT_TIME_MIN QTime(0, 0) // Prefer QDate::startOfDay() +#define QDATETIMEEDIT_TIME_MAX QTime(23, 59, 59, 999) // Prefer QDate::endOfDay() #define QDATETIMEEDIT_DATE_MIN QDate(100, 1, 1) #define QDATETIMEEDIT_COMPAT_DATE_MIN QDate(1752, 9, 14) #define QDATETIMEEDIT_DATE_MAX QDate(9999, 12, 31) -#define QDATETIMEEDIT_DATETIME_MIN QDateTime(QDATETIMEEDIT_DATE_MIN, QDATETIMEEDIT_TIME_MIN) -#define QDATETIMEEDIT_COMPAT_DATETIME_MIN QDateTime(QDATETIMEEDIT_COMPAT_DATE_MIN, QDATETIMEEDIT_TIME_MIN) -#define QDATETIMEEDIT_DATETIME_MAX QDateTime(QDATETIMEEDIT_DATE_MAX, QDATETIMEEDIT_TIME_MAX) #define QDATETIMEEDIT_DATE_INITIAL QDate(2000, 1, 1) QT_BEGIN_NAMESPACE diff --git a/src/widgets/widgets/qabstractspinbox.cpp b/src/widgets/widgets/qabstractspinbox.cpp index c617525c45..56697c5e8f 100644 --- a/src/widgets/widgets/qabstractspinbox.cpp +++ b/src/widgets/widgets/qabstractspinbox.cpp @@ -2097,7 +2097,7 @@ QVariant operator*(const QVariant &arg1, double multiplier) days -= daysInt; qint64 msecs = qint64(arg1.toDateTime().time().msecsSinceStartOfDay() * multiplier + days * (24 * 3600 * 1000)); - ret = QDateTime(QDATETIMEEDIT_DATE_MIN.addDays(daysInt), QTime::fromMSecsSinceStartOfDay(msecs)); + ret = QDATETIMEEDIT_DATE_MIN.addDays(daysInt).startOfDay().addMSecs(msecs); break; } #endif // datetimeparser diff --git a/src/widgets/widgets/qdatetimeedit.cpp b/src/widgets/widgets/qdatetimeedit.cpp index b874e4e3a9..3f41fdeb59 100644 --- a/src/widgets/widgets/qdatetimeedit.cpp +++ b/src/widgets/widgets/qdatetimeedit.cpp @@ -153,7 +153,7 @@ QDateTimeEdit::QDateTimeEdit(QWidget *parent) : QAbstractSpinBox(*new QDateTimeEditPrivate, parent) { Q_D(QDateTimeEdit); - d->init(QDateTime(QDATETIMEEDIT_DATE_INITIAL, QDATETIMEEDIT_TIME_MIN)); + d->init(QDATETIMEEDIT_DATE_INITIAL.startOfDay()); } /*! @@ -165,8 +165,7 @@ QDateTimeEdit::QDateTimeEdit(const QDateTime &datetime, QWidget *parent) : QAbstractSpinBox(*new QDateTimeEditPrivate, parent) { Q_D(QDateTimeEdit); - d->init(datetime.isValid() ? datetime : QDateTime(QDATETIMEEDIT_DATE_INITIAL, - QDATETIMEEDIT_TIME_MIN)); + d->init(datetime.isValid() ? datetime : QDATETIMEEDIT_DATE_INITIAL.startOfDay()); } /*! @@ -342,7 +341,7 @@ QDateTime QDateTimeEdit::minimumDateTime() const void QDateTimeEdit::clearMinimumDateTime() { - setMinimumDateTime(QDateTime(QDATETIMEEDIT_COMPAT_DATE_MIN, QDATETIMEEDIT_TIME_MIN)); + setMinimumDateTime(QDATETIMEEDIT_COMPAT_DATE_MIN.startOfDay()); } void QDateTimeEdit::setMinimumDateTime(const QDateTime &dt) @@ -385,7 +384,7 @@ QDateTime QDateTimeEdit::maximumDateTime() const void QDateTimeEdit::clearMaximumDateTime() { - setMaximumDateTime(QDATETIMEEDIT_DATETIME_MAX); + setMaximumDateTime(QDATETIMEEDIT_DATE_MAX.endOfDay()); } void QDateTimeEdit::setMaximumDateTime(const QDateTime &dt) @@ -1658,8 +1657,8 @@ QDateTimeEditPrivate::QDateTimeEditPrivate() first.pos = 0; sections = 0; calendarPopup = false; - minimum = QDATETIMEEDIT_COMPAT_DATETIME_MIN; - maximum = QDATETIMEEDIT_DATETIME_MAX; + minimum = QDATETIMEEDIT_COMPAT_DATE_MIN.startOfDay(); + maximum = QDATETIMEEDIT_DATE_MAX.endOfDay(); arrowState = QStyle::State_None; monthCalendar = 0; readLocaleSettings(); @@ -1683,8 +1682,8 @@ void QDateTimeEditPrivate::updateTimeSpec() const bool dateShown = (sections & QDateTimeEdit::DateSections_Mask); if (!dateShown) { if (minimum.toTime() >= maximum.toTime()){ - minimum = QDateTime(value.toDate(), QDATETIMEEDIT_TIME_MIN, spec); - maximum = QDateTime(value.toDate(), QDATETIMEEDIT_TIME_MAX, spec); + minimum = value.toDate().startOfDay(spec); + maximum = value.toDate().endOfDay(spec); } } } @@ -2382,7 +2381,7 @@ void QDateTimeEditPrivate::init(const QVariant &var) Q_Q(QDateTimeEdit); switch (var.type()) { case QVariant::Date: - value = QDateTime(var.toDate(), QDATETIMEEDIT_TIME_MIN); + value = var.toDate().startOfDay(); updateTimeSpec(); q->setDisplayFormat(defaultDateFormat); if (sectionNodes.isEmpty()) // ### safeguard for broken locale -- cgit v1.2.3 From ae38dd485bab4a0591745b78afa28547ce6ae6fc Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 24 Apr 2019 15:41:48 +0200 Subject: uic: Fix missing Python import for QFontComboBox It requires QFontDatabase from QtGui. Add more classes from QtGui. Fixes: PYSIDE-994 Change-Id: Ib84c86e2305fad60560a3f12997eb1e46deb67cb Reviewed-by: Cristian Maureira-Fredes --- src/tools/uic/python/pythonwriteimports.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/tools/uic/python/pythonwriteimports.cpp b/src/tools/uic/python/pythonwriteimports.cpp index 8e11981f37..303615f77b 100644 --- a/src/tools/uic/python/pythonwriteimports.cpp +++ b/src/tools/uic/python/pythonwriteimports.cpp @@ -40,7 +40,9 @@ QT_BEGIN_NAMESPACE static const char *standardImports = R"I(from PySide2.QtCore import (QCoreApplication, QMetaObject, QObject, QPoint, QRect, QSize, QUrl, Qt) -from PySide2.QtGui import (QColor, QFont, QIcon, QPixmap) +from PySide2.QtGui import (QBrush, QColor, QConicalGradient, QFont, + QFontDatabase, QIcon, QLinearGradient, QPalette, QPainter, QPixmap, + QRadialGradient) from PySide2.QtWidgets import * )I"; -- cgit v1.2.3 From f10d37c9c10c323c37d5ec617588348458e7286f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5rten=20Nordheim?= Date: Wed, 24 Apr 2019 15:57:55 +0200 Subject: Fix -Wc++11-narrowing error in qtextmarkdownimporter error: non-constant-expression cannot be narrowed from type 'qt::QFlags::Int' (aka 'int') to 'unsigned int' in initializer list [-Wc++11-narrowing] Change-Id: Ic634a98d29a108741d41955da1fbf2c986e4a943 Reviewed-by: Shawn Rutledge --- src/gui/text/qtextmarkdownimporter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/gui/text/qtextmarkdownimporter.cpp b/src/gui/text/qtextmarkdownimporter.cpp index 6c053ac81a..6bff337ff4 100644 --- a/src/gui/text/qtextmarkdownimporter.cpp +++ b/src/gui/text/qtextmarkdownimporter.cpp @@ -117,7 +117,7 @@ void QTextMarkdownImporter::import(QTextDocument *doc, const QString &markdown) { MD_PARSER callbacks = { 0, // abi_version - m_features, + unsigned(m_features), &CbEnterBlock, &CbLeaveBlock, &CbEnterSpan, -- cgit v1.2.3 From e6d9617c79ea029cf60c5555a3d7a32bac1cdbf6 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 3 Mar 2016 20:20:42 +0100 Subject: QHash/QMultiHash: add range constructors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QMap and QMultiMap will go in a separate commit, due to QMap's insertion behavior that "reverses" the inserted elements. [ChangeLog][QtCore][QHash] Added range constructor. [ChangeLog][QtCore][QMultiHash] Added range constructor. Change-Id: Icfd0d0afde27792e8439ed6df3e8774696b134d3 Reviewed-by: Edward Welbourne Reviewed-by: Sérgio Martins Reviewed-by: Thiago Macieira --- src/corelib/tools/qcontainertools_impl.h | 43 ++++++++++++++++++++++++++++++++ src/corelib/tools/qhash.cpp | 22 ++++++++++++++++ src/corelib/tools/qhash.h | 43 ++++++++++++++++++++++++++++++++ 3 files changed, 108 insertions(+) (limited to 'src') diff --git a/src/corelib/tools/qcontainertools_impl.h b/src/corelib/tools/qcontainertools_impl.h index c2de50b145..86a16eb32b 100644 --- a/src/corelib/tools/qcontainertools_impl.h +++ b/src/corelib/tools/qcontainertools_impl.h @@ -84,6 +84,49 @@ void reserveIfForwardIterator(Container *c, ForwardIterator f, ForwardIterator l { c->reserve(static_cast(std::distance(f, l))); } + +// for detecting expression validity +template +using void_t = void; + +template > +struct AssociativeIteratorHasKeyAndValue : std::false_type +{ +}; + +template +struct AssociativeIteratorHasKeyAndValue< + Iterator, + void_t().key()), + decltype(std::declval().value())> + > + : std::true_type +{ +}; + +template , typename = void_t<>> +struct AssociativeIteratorHasFirstAndSecond : std::false_type +{ +}; + +template +struct AssociativeIteratorHasFirstAndSecond< + Iterator, + void_t()->first), + decltype(std::declval()->second)> + > + : std::true_type +{ +}; + +template +using IfAssociativeIteratorHasKeyAndValue = + typename std::enable_if::value, bool>::type; + +template +using IfAssociativeIteratorHasFirstAndSecond = + typename std::enable_if::value, bool>::type; + } // namespace QtPrivate QT_END_NAMESPACE diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp index dd22a38be1..5c7e535c30 100644 --- a/src/corelib/tools/qhash.cpp +++ b/src/corelib/tools/qhash.cpp @@ -1251,6 +1251,17 @@ uint qHash(long double key, uint seed) noexcept compiled in C++11 mode. */ +/*! \fn template template QHash::QHash(InputIterator begin, InputIterator end) + \since 5.14 + + Constructs a hash with a copy of each of the elements in the iterator range + [\a begin, \a end). Either the elements iterated by the range must be + objects with \c{first} and \c{second} data members (like \c{QPair}, + \c{std::pair}, etc.) convertible to \c Key and to \c T respectively; or the + iterators must have \c{key()} and \c{value()} member functions, returning a + key convertible to \c Key and a value convertible to \c T respectively. +*/ + /*! \fn template QHash::QHash(const QHash &other) Constructs a copy of \a other. @@ -2586,6 +2597,17 @@ uint qHash(long double key, uint seed) noexcept \sa operator=() */ +/*! \fn template template QMultiHash::QMultiHash(InputIterator begin, InputIterator end) + \since 5.14 + + Constructs a multi-hash with a copy of each of the elements in the iterator range + [\a begin, \a end). Either the elements iterated by the range must be + objects with \c{first} and \c{second} data members (like \c{QPair}, + \c{std::pair}, etc.) convertible to \c Key and to \c T respectively; or the + iterators must have \c{key()} and \c{value()} member functions, returning a + key convertible to \c Key and a value convertible to \c T respectively. +*/ + /*! \fn template QMultiHash::iterator QMultiHash::replace(const Key &key, const T &value) Inserts a new item with the \a key and a value of \a value. diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h index 120ee9cc85..a757e85386 100644 --- a/src/corelib/tools/qhash.h +++ b/src/corelib/tools/qhash.h @@ -46,6 +46,7 @@ #include #include #include +#include #ifdef Q_COMPILER_INITIALIZER_LISTS #include @@ -258,6 +259,28 @@ public: QHash(QHash &&other) noexcept : d(other.d) { other.d = const_cast(&QHashData::shared_null); } QHash &operator=(QHash &&other) noexcept { QHash moved(std::move(other)); swap(moved); return *this; } +#endif +#ifdef Q_QDOC + template + QHash(InputIterator f, InputIterator l); +#else + template = true> + QHash(InputIterator f, InputIterator l) + : QHash() + { + QtPrivate::reserveIfForwardIterator(this, f, l); + for (; f != l; ++f) + insert(f.key(), f.value()); + } + + template = true> + QHash(InputIterator f, InputIterator l) + : QHash() + { + QtPrivate::reserveIfForwardIterator(this, f, l); + for (; f != l; ++f) + insert(f->first, f->second); + } #endif void swap(QHash &other) noexcept { qSwap(d, other.d); } @@ -1028,6 +1051,26 @@ public: for (typename std::initializer_list >::const_iterator it = list.begin(); it != list.end(); ++it) insert(it->first, it->second); } +#endif +#ifdef Q_QDOC + template + QMultiHash(InputIterator f, InputIterator l); +#else + template = true> + QMultiHash(InputIterator f, InputIterator l) + { + QtPrivate::reserveIfForwardIterator(this, f, l); + for (; f != l; ++f) + insert(f.key(), f.value()); + } + + template = true> + QMultiHash(InputIterator f, InputIterator l) + { + QtPrivate::reserveIfForwardIterator(this, f, l); + for (; f != l; ++f) + insert(f->first, f->second); + } #endif // compiler-generated copy/move ctors/assignment operators are fine! // compiler-generated destructor is fine! -- cgit v1.2.3 From 220028d37c38835987b817193ecaf0e2a1ad066b Mon Sep 17 00:00:00 2001 From: Christian Ehrlicher Date: Tue, 5 Mar 2019 22:39:27 +0100 Subject: QtBase: introduce QT_DEPRECATED_VERSION/QT_DEPRECATED_VERSION_X QT_DEPRECATED_VERSION(major, minor) and QT_DEPRECATED_VERSION_X(major, minor, text) outputs a deprecation warning if QT_DEPRECATED_WARNINGS_SINCE is equal or greater than the version specified as major, minor. This allows the user to hide deprecation warnings which can't yet be fixed for their codebase because the minimum required Qt version does not provide the replacement function. If QT_DEPRECATED_WARNINGS_SINCE is not set by the user, it's set to QT_DISABLE_DEPRECATED_BEFORE if available, otherwise to QT_VERSION. [ChangeLog][QtCore][QtGlobal] Add new macros QT_DEPRECATED_VERSION and QT_DEPRECATED_VERSION_X to conditionally display deprecation warnings Change-Id: I61b1a7624c9b870695c9e3274313de636f804b5d Reviewed-by: Konstantin Shegunov Reviewed-by: Edward Welbourne Reviewed-by: hjk --- src/corelib/global/qglobal.h | 53 +++++++++++++++++++++++++++++++++++++++++ src/widgets/widgets/qcombobox.h | 6 ++--- 2 files changed, 56 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index a0207b483d..3c17bbb2d4 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -307,6 +307,14 @@ typedef double qreal; # define QT_DEPRECATED_CONSTRUCTOR #endif +#ifndef QT_DEPRECATED_WARNINGS_SINCE +# ifdef QT_DISABLE_DEPRECATED_BEFORE +# define QT_DEPRECATED_WARNINGS_SINCE QT_DISABLE_DEPRECATED_BEFORE +# else +# define QT_DEPRECATED_WARNINGS_SINCE QT_VERSION +# endif +#endif + #ifndef QT_DISABLE_DEPRECATED_BEFORE #define QT_DISABLE_DEPRECATED_BEFORE QT_VERSION_CHECK(5, 0, 0) #endif @@ -329,6 +337,51 @@ typedef double qreal; #define QT_DEPRECATED_SINCE(major, minor) 0 #endif +/* + QT_DEPRECATED_VERSION(major, minor) and QT_DEPRECATED_VERSION_X(major, minor, text) + outputs a deprecation warning if QT_DEPRECATED_WARNINGS_SINCE is equal or greater + than the version specified as major, minor. This makes it possible to deprecate a + function without annoying a user who needs to stick at a specified minimum version + and therefore can't use the new function. +*/ +#if QT_DEPRECATED_WARNINGS_SINCE >= QT_VERSION_CHECK(5, 12, 0) +# define QT_DEPRECATED_VERSION_X_5_12(text) QT_DEPRECATED_X(text) +# define QT_DEPRECATED_VERSION_5_12 QT_DEPRECATED +#else +# define QT_DEPRECATED_VERSION_X_5_12(text) +# define QT_DEPRECATED_VERSION_5_12 +#endif + +#if QT_DEPRECATED_WARNINGS_SINCE >= QT_VERSION_CHECK(5, 13, 0) +# define QT_DEPRECATED_VERSION_X_5_13(text) QT_DEPRECATED_X(text) +# define QT_DEPRECATED_VERSION_5_13 QT_DEPRECATED +#else +# define QT_DEPRECATED_VERSION_X_5_13(text) +# define QT_DEPRECATED_VERSION_5_13 +#endif + +#if QT_DEPRECATED_WARNINGS_SINCE >= QT_VERSION_CHECK(5, 14, 0) +# define QT_DEPRECATED_VERSION_X_5_14(text) QT_DEPRECATED_X(text) +# define QT_DEPRECATED_VERSION_5_14 QT_DEPRECATED +#else +# define QT_DEPRECATED_VERSION_X_5_14(text) +# define QT_DEPRECATED_VERSION_5_14 +#endif + +#if QT_DEPRECATED_WARNINGS_SINCE >= QT_VERSION_CHECK(5, 15, 0) +# define QT_DEPRECATED_VERSION_X_5_15(text) QT_DEPRECATED_X(text) +# define QT_DEPRECATED_VERSION_5_15 QT_DEPRECATED +#else +# define QT_DEPRECATED_VERSION_X_5_15(text) +# define QT_DEPRECATED_VERSION_5_15 +#endif + +#define QT_DEPRECATED_VERSION_X_5(minor, text) QT_DEPRECATED_VERSION_X_5_##minor(text) +#define QT_DEPRECATED_VERSION_X(major, minor, text) QT_DEPRECATED_VERSION_X_##major(minor, text) + +#define QT_DEPRECATED_VERSION_5(minor) QT_DEPRECATED_VERSION_5_##minor() +#define QT_DEPRECATED_VERSION(major, minor) QT_DEPRECATED_VERSION_##major(minor) + /* The Qt modules' export macros. The options are: diff --git a/src/widgets/widgets/qcombobox.h b/src/widgets/widgets/qcombobox.h index 6a87a675a4..37b155774d 100644 --- a/src/widgets/widgets/qcombobox.h +++ b/src/widgets/widgets/qcombobox.h @@ -226,13 +226,13 @@ Q_SIGNALS: void currentIndexChanged(int index); void currentTextChanged(const QString &); #if QT_DEPRECATED_SINCE(5, 13) - QT_DEPRECATED_X("Use currentTextChanged() instead") + QT_DEPRECATED_VERSION_X(5, 13, "Use currentTextChanged() instead") void currentIndexChanged(const QString &); #endif #if QT_DEPRECATED_SINCE(5, 15) - QT_DEPRECATED_X("Use textActivated() instead") + QT_DEPRECATED_VERSION_X(5, 15, "Use textActivated() instead") void activated(const QString &); - QT_DEPRECATED_X("Use textHighlighted() instead") + QT_DEPRECATED_VERSION_X(5, 15, "Use textHighlighted() instead") void highlighted(const QString &); #endif -- cgit v1.2.3 From c530ca1c170798159c3d84029841a1224d1cdc65 Mon Sep 17 00:00:00 2001 From: Christian Ehrlicher Date: Sun, 3 Mar 2019 12:14:43 +0100 Subject: QLineF: add intersects() as a replacement for intersect() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QLineF::intersect() does not follow the naming rules for functions. Therefore add a replacement function intersects() instead and also rename the return type from IntersectType to IntersectionType [ChangeLog][QtCore][QLineF] added QLineF::intersects() as a replacement for QLineF::intersect() Change-Id: I744b960ea339cb817facb12f296f78cca3e7d938 Reviewed-by: Jędrzej Nowacki Reviewed-by: Konstantin Shegunov --- src/corelib/tools/qline.cpp | 26 +++++++++++++++++++++++++- src/corelib/tools/qline.h | 6 ++++-- src/gui/painting/qstroker.cpp | 2 +- 3 files changed, 30 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/corelib/tools/qline.cpp b/src/corelib/tools/qline.cpp index 6f3c22a6ec..3afd23d76b 100644 --- a/src/corelib/tools/qline.cpp +++ b/src/corelib/tools/qline.cpp @@ -347,7 +347,7 @@ QDataStream &operator>>(QDataStream &stream, QLine &line) function to determine whether the QLineF represents a valid line or a null line. - The intersect() function determines the IntersectType for this + The intersects() function determines the IntersectionType for this line and a given line, while the angleTo() function returns the angle between the lines. In addition, the unitVector() function returns a line that has the same starting point as this line, but @@ -370,6 +370,11 @@ QDataStream &operator>>(QDataStream &stream, QLine &line) /*! \enum QLineF::IntersectType + \obsolete Use QLineF::IntersectionType instead +*/ + +/*! + \enum QLineF::IntersectionType Describes the intersection between two lines. @@ -657,8 +662,10 @@ QLineF QLineF::unitVector() const return f; } +#if QT_DEPRECATED_SINCE(5, 14) /*! \fn QLineF::IntersectType QLineF::intersect(const QLineF &line, QPointF *intersectionPoint) const + \obsolete Use intersects() instead Returns a value indicating whether or not \e this line intersects with the given \a line. @@ -669,6 +676,23 @@ QLineF QLineF::unitVector() const */ QLineF::IntersectType QLineF::intersect(const QLineF &l, QPointF *intersectionPoint) const +{ + return intersects(l, intersectionPoint); +} +#endif + +/*! + \fn QLineF::IntersectionType QLineF::intersects(const QLineF &line, QPointF *intersectionPoint) const + \since 5.14 + + Returns a value indicating whether or not \e this line intersects + with the given \a line. + + The actual intersection point is extracted to \a intersectionPoint + (if the pointer is valid). If the lines are parallel, the + intersection point is undefined. +*/ +QLineF::IntersectionType QLineF::intersects(const QLineF &l, QPointF *intersectionPoint) const { // ipmlementation is based on Graphics Gems III's "Faster Line Segment Intersection" const QPointF a = pt2 - pt1; diff --git a/src/corelib/tools/qline.h b/src/corelib/tools/qline.h index 14980b60a0..c96d624afd 100644 --- a/src/corelib/tools/qline.h +++ b/src/corelib/tools/qline.h @@ -215,6 +215,7 @@ class Q_CORE_EXPORT QLineF { public: enum IntersectType { NoIntersection, BoundedIntersection, UnboundedIntersection }; + using IntersectionType = IntersectType; Q_DECL_CONSTEXPR inline QLineF(); Q_DECL_CONSTEXPR inline QLineF(const QPointF &pt1, const QPointF &pt2); @@ -248,10 +249,11 @@ public: Q_REQUIRED_RESULT QLineF unitVector() const; Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QLineF normalVector() const; - // ### Qt 6: rename intersects() or intersection() and rename IntersectType IntersectionType - IntersectType intersect(const QLineF &l, QPointF *intersectionPoint) const; + IntersectionType intersects(const QLineF &l, QPointF *intersectionPoint) const; #if QT_DEPRECATED_SINCE(5, 14) + QT_DEPRECATED_VERSION_X(5, 14, "Use intersects() instead") + IntersectType intersect(const QLineF &l, QPointF *intersectionPoint) const; QT_DEPRECATED_X("Use angleTo() instead, take care that the return value is between 0 and 360 degree.") qreal angle(const QLineF &l) const; #endif diff --git a/src/gui/painting/qstroker.cpp b/src/gui/painting/qstroker.cpp index f8f8d72d14..f158222f82 100644 --- a/src/gui/painting/qstroker.cpp +++ b/src/gui/painting/qstroker.cpp @@ -456,7 +456,7 @@ void QStroker::joinPoints(qfixed focal_x, qfixed focal_y, const QLineF &nextLine QLineF prevLine(qt_fixed_to_real(m_back2X), qt_fixed_to_real(m_back2Y), qt_fixed_to_real(m_back1X), qt_fixed_to_real(m_back1Y)); QPointF isect; - QLineF::IntersectType type = prevLine.intersect(nextLine, &isect); + QLineF::IntersectionType type = prevLine.intersects(nextLine, &isect); if (join == FlatJoin) { QLineF shortCut(prevLine.p2(), nextLine.p1()); -- cgit v1.2.3 From e092b32922ef650d49167aaf48f9d33190191f9f Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Tue, 23 Apr 2019 07:48:50 +0200 Subject: QTextMarkdownImporter: insert list items into the correct list There was a bug when handling situations like 1. first 1) subfirst 2. second It was always inserting items into the list where the cursor already was, but it needs to insert the "second" list item into the list which is currently the top of m_listStack. Change-Id: Id0899032efafb2e2b9e7c45a6fb9f2c5221fc4df Reviewed-by: Gatis Paeglis --- src/gui/text/qtextmarkdownimporter.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/gui/text/qtextmarkdownimporter.cpp b/src/gui/text/qtextmarkdownimporter.cpp index 6bff337ff4..2477e0bc74 100644 --- a/src/gui/text/qtextmarkdownimporter.cpp +++ b/src/gui/text/qtextmarkdownimporter.cpp @@ -165,13 +165,14 @@ int QTextMarkdownImporter::cbEnterBlock(MD_BLOCKTYPE type, void *det) } break; case MD_BLOCK_LI: { MD_BLOCK_LI_DETAIL *detail = static_cast(det); - QTextBlockFormat bfmt = m_cursor->blockFormat(); + QTextList *list = m_listStack.top(); + QTextBlockFormat bfmt = list->item(list->count() - 1).blockFormat(); bfmt.setMarker(detail->is_task ? (detail->task_mark == ' ' ? QTextBlockFormat::Unchecked : QTextBlockFormat::Checked) : QTextBlockFormat::NoMarker); if (!m_emptyList) { m_cursor->insertBlock(bfmt, QTextCharFormat()); - m_listStack.top()->add(m_cursor->block()); + list->add(m_cursor->block()); } m_cursor->setBlockFormat(bfmt); m_emptyList = false; // Avoid insertBlock for the first item (because insertList already did that) -- cgit v1.2.3 From 8059762565d1ed6b7aaee2729d3a637efcd671d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5rten=20Nordheim?= Date: Thu, 25 Apr 2019 17:30:36 +0200 Subject: Set 'originalRequest' in QNetworkReplyImpl It's what's returned when calling request() on a QNetworkReply, but for QNetworkReplyImpl (the implementation used for e.g. FTP) it was not set, so it returned a default object. Change-Id: Id82f7920e4268c1a7743e681fc503bcd28889b6e Reviewed-by: Thiago Macieira Reviewed-by: Markus Goetz (Woboq GmbH) Reviewed-by: Edward Welbourne --- src/network/access/qnetworkreplyimpl.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp index a794b492e7..f5bb4d5887 100644 --- a/src/network/access/qnetworkreplyimpl.cpp +++ b/src/network/access/qnetworkreplyimpl.cpp @@ -368,6 +368,7 @@ void QNetworkReplyImplPrivate::setup(QNetworkAccessManager::Operation op, const outgoingData = data; request = req; + originalRequest = req; url = request.url(); operation = op; -- cgit v1.2.3 From 9a6a84731131b205f74b10f866ae212e0895bd4a Mon Sep 17 00:00:00 2001 From: Andreas Schwab Date: Tue, 18 Dec 2018 16:41:39 +0100 Subject: Add RISC-V detection Change-Id: I0203c88e0944064841c9f6fe9f8a7888d6c421d1 Reviewed-by: Giuseppe D'Angelo Reviewed-by: Thiago Macieira --- src/corelib/global/archdetect.cpp | 4 ++++ src/corelib/global/qglobal.cpp | 36 ++++++++++++++++++++++++++++++++ src/corelib/global/qprocessordetection.h | 14 +++++++++++++ 3 files changed, 54 insertions(+) (limited to 'src') diff --git a/src/corelib/global/archdetect.cpp b/src/corelib/global/archdetect.cpp index 66a5e074f6..1d00b7f5a5 100644 --- a/src/corelib/global/archdetect.cpp +++ b/src/corelib/global/archdetect.cpp @@ -67,6 +67,10 @@ # define ARCH_PROCESSOR "power" #elif defined(Q_PROCESSOR_POWER_64) # define ARCH_PROCESSOR "power64" +#elif defined(Q_PROCESSOR_RISCV_32) +# define ARCH_PROCESSOR "riscv32" +#elif defined(Q_PROCESSOR_RISCV_64) +# define ARCH_PROCESSOR "riscv64" #elif defined(Q_PROCESSOR_S390_X) # define ARCH_PROCESSOR "s390x" #elif defined(Q_PROCESSOR_S390) diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index d95064af27..16d8d8b8ac 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -1883,6 +1883,42 @@ bool qSharedBuild() noexcept \sa QSysInfo::buildCpuArchitecture() */ +/*! + \macro Q_PROCESSOR_RISCV + \relates + \since 5.13 + + Defined if the application is compiled for RISC-V processors. Qt currently + supports two RISC-V variants: \l Q_PROCESSOR_RISCV_32 and \l + Q_PROCESSOR_RISCV_64. + + \sa QSysInfo::buildCpuArchitecture() +*/ + +/*! + \macro Q_PROCESSOR_RISCV_32 + \relates + \since 5.13 + + Defined if the application is compiled for 32-bit RISC-V processors. The \l + Q_PROCESSOR_RISCV macro is also defined when Q_PROCESSOR_RISCV_32 is + defined. + + \sa QSysInfo::buildCpuArchitecture() +*/ + +/*! + \macro Q_PROCESSOR_RISCV_64 + \relates + \since 5.13 + + Defined if the application is compiled for 64-bit RISC-V processors. The \l + Q_PROCESSOR_RISCV macro is also defined when Q_PROCESSOR_RISCV_64 is + defined. + + \sa QSysInfo::buildCpuArchitecture() +*/ + /*! \macro Q_PROCESSOR_S390 \relates diff --git a/src/corelib/global/qprocessordetection.h b/src/corelib/global/qprocessordetection.h index 1f327c352e..8d65720850 100644 --- a/src/corelib/global/qprocessordetection.h +++ b/src/corelib/global/qprocessordetection.h @@ -281,6 +281,20 @@ # endif // Q_BYTE_ORDER not defined, use endianness auto-detection +/* + RISC-V family, known variants: 32- and 64-bit + + RISC-V is little-endian. +*/ +#elif defined(__riscv) +# define Q_PROCESSOR_RISCV +# if __riscv_xlen == 64 +# define Q_PROCESSOR_RISCV_64 +# else +# define Q_PROCESSOR_RISCV_32 +# endif +# define Q_BYTE_ORDER Q_LITTLE_ENDIAN + /* S390 family, known variant: S390X (64-bit) -- cgit v1.2.3 From 8e82e536cdbf2b6c36a7eabd6fba1a85613973f8 Mon Sep 17 00:00:00 2001 From: Jesus Fernandez Date: Tue, 19 Mar 2019 11:41:53 +0100 Subject: FTP: Workaround for servers without HELP command support Ignores errors produced by the HELP command. It will continue executing the commands sent to QFtp when a server does not have a HELP command implemented. Commands SIZE, MDTM, and PWD are not going to be used if the HELP command failed. [ChangeLog][QtNetwork][QNetworkAccessManager] Don't fail when FTP does not implement the HELP command. Task-number: QTBUG-69477 Change-Id: I0ebd51b134535730c6bef83de1abf1a427b8d2ce Reviewed-by: Thiago Macieira Reviewed-by: Edward Welbourne --- src/network/access/qftp.cpp | 11 +++++++++++ src/network/access/qftp_p.h | 3 +++ src/network/access/qnetworkaccessftpbackend.cpp | 7 ++++++- 3 files changed, 20 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/network/access/qftp.cpp b/src/network/access/qftp.cpp index 4e399f018f..b6b721030b 100644 --- a/src/network/access/qftp.cpp +++ b/src/network/access/qftp.cpp @@ -2122,6 +2122,17 @@ void QFtp::abort() d_func()->pi.abort(); } +/*! + \internal + Clears the last error. + + \sa currentCommand() +*/ +void QFtp::clearError() +{ + d_func()->error = NoError; +} + /*! \internal Returns the identifier of the FTP command that is being executed diff --git a/src/network/access/qftp_p.h b/src/network/access/qftp_p.h index 91d78d1351..a55429933b 100644 --- a/src/network/access/qftp_p.h +++ b/src/network/access/qftp_p.h @@ -157,6 +157,9 @@ Q_SIGNALS: void commandFinished(int, bool); void done(bool); +protected: + void clearError(); + private: Q_DISABLE_COPY_MOVE(QFtp) Q_DECLARE_PRIVATE(QFtp) diff --git a/src/network/access/qnetworkaccessftpbackend.cpp b/src/network/access/qnetworkaccessftpbackend.cpp index 5ad820eba0..51ed2f5a55 100644 --- a/src/network/access/qnetworkaccessftpbackend.cpp +++ b/src/network/access/qnetworkaccessftpbackend.cpp @@ -99,6 +99,8 @@ public: connect(this, SIGNAL(done(bool)), this, SLOT(deleteLater())); close(); } + + using QFtp::clearError; }; QNetworkAccessFtpBackend::QNetworkAccessFtpBackend() @@ -282,7 +284,10 @@ void QNetworkAccessFtpBackend::ftpDone() } // check for errors: - if (ftp->error() != QFtp::NoError) { + if (state == CheckingFeatures && ftp->error() == QFtp::UnknownError) { + qWarning("QNetworkAccessFtpBackend: HELP command failed, ignoring it"); + ftp->clearError(); + } else if (ftp->error() != QFtp::NoError) { QString msg; if (operation() == QNetworkAccessManager::GetOperation) msg = tr("Error while downloading %1: %2"); -- cgit v1.2.3 From dc3e5c48380ff564df9a232b13e2cf1fab65f66d Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Wed, 24 Apr 2019 17:06:15 +0200 Subject: Consolidate Unix and Windows implementations of QHostInfo::fromName The implementations were practically identical, so we can just move the code into qhostinfo.cpp, cleaning up things along the way. Since QHostInfoAgent is an internal class, add the shared code as additional static helper functions. And since half the code already used QCoreApplication::translate anyway, we can remove the QObject inheritance which was only added for getting a tr(). Change-Id: I58eafbdc3e7d06d2e898486a1add63cd63d98c96 Reviewed-by: Thiago Macieira --- src/network/kernel/qhostinfo.cpp | 168 ++++++++++++++++++++++++++++++++++ src/network/kernel/qhostinfo_p.h | 7 +- src/network/kernel/qhostinfo_unix.cpp | 139 +--------------------------- src/network/kernel/qhostinfo_win.cpp | 111 +--------------------- 4 files changed, 178 insertions(+), 247 deletions(-) (limited to 'src') diff --git a/src/network/kernel/qhostinfo.cpp b/src/network/kernel/qhostinfo.cpp index d3fe85f5d5..9374728244 100644 --- a/src/network/kernel/qhostinfo.cpp +++ b/src/network/kernel/qhostinfo.cpp @@ -37,8 +37,11 @@ ** ****************************************************************************/ +//#define QHOSTINFO_DEBUG + #include "qhostinfo.h" #include "qhostinfo_p.h" +#include #include "QtCore/qscopedpointer.h" #include @@ -53,6 +56,15 @@ #ifdef Q_OS_UNIX # include +# include +# include +# if defined(AI_ADDRCONFIG) +# define Q_ADDRCONFIG AI_ADDRCONFIG +# endif +#elif defined Q_OS_WIN +# include + +# define QT_SOCKLEN_T int #endif QT_BEGIN_NAMESPACE @@ -412,6 +424,162 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName, QSharedPointer(&sa4); + saSize = sizeof(sa4); + memset(&sa4, 0, sizeof(sa4)); + sa4.sin_family = AF_INET; + sa4.sin_addr.s_addr = htonl(address.toIPv4Address()); + } else { + sa = reinterpret_cast(&sa6); + saSize = sizeof(sa6); + memset(&sa6, 0, sizeof(sa6)); + sa6.sin6_family = AF_INET6; + memcpy(&sa6.sin6_addr, address.toIPv6Address().c, sizeof(sa6.sin6_addr)); + } + + char hbuf[NI_MAXHOST]; + if (sa && getnameinfo(sa, saSize, hbuf, sizeof(hbuf), nullptr, 0, 0) == 0) + results.setHostName(QString::fromLatin1(hbuf)); + + if (results.hostName().isEmpty()) + results.setHostName(address.toString()); + results.setAddresses(QList() << address); + + return results; +} + +/* + Call getaddrinfo, and returns the results as QHostInfo::addresses +*/ +QHostInfo QHostInfoAgent::lookup(const QString &hostName) +{ + QHostInfo results; + + // IDN support + QByteArray aceHostname = QUrl::toAce(hostName); + results.setHostName(hostName); + if (aceHostname.isEmpty()) { + results.setError(QHostInfo::HostNotFound); + results.setErrorString(hostName.isEmpty() ? + QCoreApplication::translate("QHostInfoAgent", "No host name given") : + QCoreApplication::translate("QHostInfoAgent", "Invalid hostname")); + return results; + } + + addrinfo *res = 0; + struct addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; +#ifdef Q_ADDRCONFIG + hints.ai_flags = Q_ADDRCONFIG; +#endif + + int result = getaddrinfo(aceHostname.constData(), nullptr, &hints, &res); +# ifdef Q_ADDRCONFIG + if (result == EAI_BADFLAGS) { + // if the lookup failed with AI_ADDRCONFIG set, try again without it + hints.ai_flags = 0; + result = getaddrinfo(aceHostname.constData(), nullptr, &hints, &res); + } +# endif + + if (result == 0) { + addrinfo *node = res; + QList addresses; + while (node) { +#ifdef QHOSTINFO_DEBUG + qDebug() << "getaddrinfo node: flags:" << node->ai_flags << "family:" << node->ai_family + << "ai_socktype:" << node->ai_socktype << "ai_protocol:" << node->ai_protocol + << "ai_addrlen:" << node->ai_addrlen; +#endif + switch (node->ai_family) { + case AF_INET: { + QHostAddress addr; + addr.setAddress(ntohl(((sockaddr_in *) node->ai_addr)->sin_addr.s_addr)); + if (!addresses.contains(addr)) + addresses.append(addr); + break; + } + case AF_INET6: { + QHostAddress addr; + sockaddr_in6 *sa6 = (sockaddr_in6 *) node->ai_addr; + addr.setAddress(sa6->sin6_addr.s6_addr); + if (sa6->sin6_scope_id) + addr.setScopeId(QString::number(sa6->sin6_scope_id)); + if (!addresses.contains(addr)) + addresses.append(addr); + break; + } + default: + results.setError(QHostInfo::UnknownError); + results.setErrorString(QCoreApplication::translate("QHostInfoAgent", "Unknown address type")); + } + node = node->ai_next; + } + if (addresses.isEmpty()) { + // Reached the end of the list, but no addresses were found; this + // means the list contains one or more unknown address types. + results.setError(QHostInfo::UnknownError); + results.setErrorString(QCoreApplication::translate("QHostInfoAgent", "Unknown address type")); + } + + results.setAddresses(addresses); + freeaddrinfo(res); + } else { + switch (result) { +#ifdef Q_OS_WIN + case WSAHOST_NOT_FOUND: //authoritative not found + case WSATRY_AGAIN: //non authoritative not found + case WSANO_DATA: //valid name, no associated address +#else + case EAI_NONAME: + case EAI_FAIL: +# ifdef EAI_NODATA // EAI_NODATA is deprecated in RFC 3493 + case EAI_NODATA: +# endif +#endif + results.setError(QHostInfo::HostNotFound); + results.setErrorString(QCoreApplication::translate("QHostInfoAgent", "Host not found")); + break; + default: + results.setError(QHostInfo::UnknownError); +#ifdef Q_OS_WIN + results.setErrorString(QString::fromWCharArray(gai_strerror(result))); +#else + results.setErrorString(QString::fromLocal8Bit(gai_strerror(result))); +#endif + break; + } + } + +#if defined(QHOSTINFO_DEBUG) + if (results.error() != QHostInfo::NoError) { + qDebug("QHostInfoAgent::fromName(): error #%d %s", + h_errno, results.errorString().toLatin1().constData()); + } else { + QString tmp; + QList addresses = results.addresses(); + for (int i = 0; i < addresses.count(); ++i) { + if (i != 0) tmp += QLatin1String(", "); + tmp += addresses.at(i).toString(); + } + qDebug("QHostInfoAgent::fromName(): found %i entries for \"%s\": {%s}", + addresses.count(), aceHostname.constData(), + tmp.toLatin1().constData()); + } +#endif + + return results; +} /*! \enum QHostInfo::HostInfoError diff --git a/src/network/kernel/qhostinfo_p.h b/src/network/kernel/qhostinfo_p.h index da02163ddf..3c0ee2a0d8 100644 --- a/src/network/kernel/qhostinfo_p.h +++ b/src/network/kernel/qhostinfo_p.h @@ -127,15 +127,16 @@ Q_SIGNALS: void resultsReady(const QHostInfo &info); }; -// needs to be QObject because fromName calls tr() -class QHostInfoAgent : public QObject +class QHostInfoAgent { - Q_OBJECT public: static QHostInfo fromName(const QString &hostName); #ifndef QT_NO_BEARERMANAGEMENT static QHostInfo fromName(const QString &hostName, QSharedPointer networkSession); #endif +private: + static QHostInfo lookup(const QString &hostName); + static QHostInfo reverseLookup(const QHostAddress &address); }; class QHostInfoPrivate diff --git a/src/network/kernel/qhostinfo_unix.cpp b/src/network/kernel/qhostinfo_unix.cpp index e4810d68ee..78a05f8407 100644 --- a/src/network/kernel/qhostinfo_unix.cpp +++ b/src/network/kernel/qhostinfo_unix.cpp @@ -72,17 +72,6 @@ QT_BEGIN_NAMESPACE -// Almost always the same. If not, specify in qplatformdefs.h. -#if !defined(QT_SOCKOPTLEN_T) -# define QT_SOCKOPTLEN_T QT_SOCKLEN_T -#endif - -// HP-UXi has a bug in getaddrinfo(3) that makes it thread-unsafe -// with this flag. So disable it in that platform. -#if defined(AI_ADDRCONFIG) && !defined(Q_OS_HPUX) -# define Q_ADDRCONFIG AI_ADDRCONFIG -#endif - enum LibResolvFeature { NeedResInit, NeedResNInit @@ -197,132 +186,10 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) local_res_init(); QHostAddress address; - if (address.setAddress(hostName)) { - // Reverse lookup - sockaddr_in sa4; - sockaddr_in6 sa6; - sockaddr *sa = 0; - QT_SOCKLEN_T saSize = 0; - if (address.protocol() == QAbstractSocket::IPv4Protocol) { - sa = (sockaddr *)&sa4; - saSize = sizeof(sa4); - memset(&sa4, 0, sizeof(sa4)); - sa4.sin_family = AF_INET; - sa4.sin_addr.s_addr = htonl(address.toIPv4Address()); - } - else { - sa = (sockaddr *)&sa6; - saSize = sizeof(sa6); - memset(&sa6, 0, sizeof(sa6)); - sa6.sin6_family = AF_INET6; - memcpy(sa6.sin6_addr.s6_addr, address.toIPv6Address().c, sizeof(sa6.sin6_addr.s6_addr)); - } - - char hbuf[NI_MAXHOST]; - if (sa && getnameinfo(sa, saSize, hbuf, sizeof(hbuf), 0, 0, 0) == 0) - results.setHostName(QString::fromLatin1(hbuf)); - - if (results.hostName().isEmpty()) - results.setHostName(address.toString()); - results.setAddresses(QList() << address); - return results; - } - - // IDN support - QByteArray aceHostname = QUrl::toAce(hostName); - results.setHostName(hostName); - if (aceHostname.isEmpty()) { - results.setError(QHostInfo::HostNotFound); - results.setErrorString(hostName.isEmpty() ? - QCoreApplication::translate("QHostInfoAgent", "No host name given") : - QCoreApplication::translate("QHostInfoAgent", "Invalid hostname")); - return results; - } - - // Call getaddrinfo, and place all IPv4 addresses at the start and - // the IPv6 addresses at the end of the address list in results. - addrinfo *res = 0; - struct addrinfo hints; - memset(&hints, 0, sizeof(hints)); - hints.ai_family = PF_UNSPEC; -#ifdef Q_ADDRCONFIG - hints.ai_flags = Q_ADDRCONFIG; -#endif + if (address.setAddress(hostName)) + return reverseLookup(address); - int result = getaddrinfo(aceHostname.constData(), 0, &hints, &res); -# ifdef Q_ADDRCONFIG - if (result == EAI_BADFLAGS) { - // if the lookup failed with AI_ADDRCONFIG set, try again without it - hints.ai_flags = 0; - result = getaddrinfo(aceHostname.constData(), 0, &hints, &res); - } -# endif - - if (result == 0) { - addrinfo *node = res; - QList addresses; - while (node) { -#ifdef QHOSTINFO_DEBUG - qDebug() << "getaddrinfo node: flags:" << node->ai_flags << "family:" << node->ai_family << "ai_socktype:" << node->ai_socktype << "ai_protocol:" << node->ai_protocol << "ai_addrlen:" << node->ai_addrlen; -#endif - if (node->ai_family == AF_INET) { - QHostAddress addr; - addr.setAddress(ntohl(((sockaddr_in *) node->ai_addr)->sin_addr.s_addr)); - if (!addresses.contains(addr)) - addresses.append(addr); - } - else if (node->ai_family == AF_INET6) { - QHostAddress addr; - sockaddr_in6 *sa6 = (sockaddr_in6 *) node->ai_addr; - addr.setAddress(sa6->sin6_addr.s6_addr); - if (sa6->sin6_scope_id) - addr.setScopeId(QString::number(sa6->sin6_scope_id)); - if (!addresses.contains(addr)) - addresses.append(addr); - } - node = node->ai_next; - } - if (addresses.isEmpty() && node == 0) { - // Reached the end of the list, but no addresses were found; this - // means the list contains one or more unknown address types. - results.setError(QHostInfo::UnknownError); - results.setErrorString(tr("Unknown address type")); - } - - results.setAddresses(addresses); - freeaddrinfo(res); - } else if (result == EAI_NONAME - || result == EAI_FAIL -#ifdef EAI_NODATA - // EAI_NODATA is deprecated in RFC 3493 - || result == EAI_NODATA -#endif - ) { - results.setError(QHostInfo::HostNotFound); - results.setErrorString(tr("Host not found")); - } else { - results.setError(QHostInfo::UnknownError); - results.setErrorString(QString::fromLocal8Bit(gai_strerror(result))); - } - - -#if defined(QHOSTINFO_DEBUG) - if (results.error() != QHostInfo::NoError) { - qDebug("QHostInfoAgent::fromName(): error #%d %s", - h_errno, results.errorString().toLatin1().constData()); - } else { - QString tmp; - QList addresses = results.addresses(); - for (int i = 0; i < addresses.count(); ++i) { - if (i != 0) tmp += ", "; - tmp += addresses.at(i).toString(); - } - qDebug("QHostInfoAgent::fromName(): found %i entries for \"%s\": {%s}", - addresses.count(), hostName.toLatin1().constData(), - tmp.toLatin1().constData()); - } -#endif - return results; + return lookup(hostName); } QString QHostInfo::localDomainName() diff --git a/src/network/kernel/qhostinfo_win.cpp b/src/network/kernel/qhostinfo_win.cpp index ef7cff46f1..0b5cc98970 100644 --- a/src/network/kernel/qhostinfo_win.cpp +++ b/src/network/kernel/qhostinfo_win.cpp @@ -51,27 +51,10 @@ QT_BEGIN_NAMESPACE //#define QHOSTINFO_DEBUG //### -#define QT_SOCKLEN_T int #ifndef NI_MAXHOST // already defined to 1025 in ws2tcpip.h? #define NI_MAXHOST 1024 #endif -static void translateWSAError(int error, QHostInfo *results) -{ - switch (error) { - case WSAHOST_NOT_FOUND: //authoritative not found - case WSATRY_AGAIN: //non authoritative not found - case WSANO_DATA: //valid name, no associated address - results->setError(QHostInfo::HostNotFound); - results->setErrorString(QHostInfoAgent::tr("Host not found")); - return; - default: - results->setError(QHostInfo::UnknownError); - results->setErrorString(QHostInfoAgent::tr("Unknown error (%1)").arg(error)); - return; - } -} - QHostInfo QHostInfoAgent::fromName(const QString &hostName) { QSysInfo::machineHostName(); // this initializes ws2_32.dll @@ -84,98 +67,10 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) #endif QHostAddress address; - if (address.setAddress(hostName)) { - // Reverse lookup - sockaddr_in sa4; - sockaddr_in6 sa6; - sockaddr *sa; - QT_SOCKLEN_T saSize; - if (address.protocol() == QAbstractSocket::IPv4Protocol) { - sa = reinterpret_cast(&sa4); - saSize = sizeof(sa4); - memset(&sa4, 0, sizeof(sa4)); - sa4.sin_family = AF_INET; - sa4.sin_addr.s_addr = htonl(address.toIPv4Address()); - } else { - sa = reinterpret_cast(&sa6); - saSize = sizeof(sa6); - memset(&sa6, 0, sizeof(sa6)); - sa6.sin6_family = AF_INET6; - memcpy(&sa6.sin6_addr, address.toIPv6Address().c, sizeof(sa6.sin6_addr)); - } - - char hbuf[NI_MAXHOST]; - if (getnameinfo(sa, saSize, hbuf, sizeof(hbuf), 0, 0, 0) == 0) - results.setHostName(QString::fromLatin1(hbuf)); - - if (results.hostName().isEmpty()) - results.setHostName(address.toString()); - results.setAddresses(QList() << address); - return results; - } - - // IDN support - QByteArray aceHostname = QUrl::toAce(hostName); - results.setHostName(hostName); - if (aceHostname.isEmpty()) { - results.setError(QHostInfo::HostNotFound); - results.setErrorString(hostName.isEmpty() ? tr("No host name given") : tr("Invalid hostname")); - return results; - } + if (address.setAddress(hostName)) + return reverseLookup(address); - addrinfo *res; - int err = getaddrinfo(aceHostname.constData(), 0, 0, &res); - if (err == 0) { - QList addresses; - for (addrinfo *p = res; p != 0; p = p->ai_next) { -#ifdef QHOSTINFO_DEBUG - qDebug() << "getaddrinfo node: flags:" << p->ai_flags << "family:" << p->ai_family - << "ai_socktype:" << p->ai_socktype << "ai_protocol:" << p->ai_protocol - << "ai_addrlen:" << p->ai_addrlen; -#endif - - switch (p->ai_family) { - case AF_INET: { - QHostAddress addr; - addr.setAddress(ntohl(reinterpret_cast(p->ai_addr)->sin_addr.s_addr)); - if (!addresses.contains(addr)) - addresses.append(addr); - } - break; - case AF_INET6: { - QHostAddress addr; - addr.setAddress(reinterpret_cast(p->ai_addr)->sin6_addr.s6_addr); - if (!addresses.contains(addr)) - addresses.append(addr); - } - break; - default: - results.setError(QHostInfo::UnknownError); - results.setErrorString(tr("Unknown address type")); - } - } - results.setAddresses(addresses); - freeaddrinfo(res); - } else { - translateWSAError(WSAGetLastError(), &results); - } - -#if defined(QHOSTINFO_DEBUG) - if (results.error() != QHostInfo::NoError) { - qDebug("QHostInfoAgent::run(): error (%s)", - results.errorString().toLatin1().constData()); - } else { - QString tmp; - QList addresses = results.addresses(); - for (int i = 0; i < addresses.count(); ++i) { - if (i != 0) tmp += QLatin1String(", "); - tmp += addresses.at(i).toString(); - } - qDebug("QHostInfoAgent::run(): found %i entries: {%s}", - addresses.count(), tmp.toLatin1().constData()); - } -#endif - return results; + return lookup(hostName); } // QString QHostInfo::localDomainName() defined in qnetworkinterface_win.cpp -- cgit v1.2.3 From abd2cf3b0a8c862d09f8163278424ca54297f854 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Fri, 26 Apr 2019 11:47:00 +0200 Subject: Remove extraneous sodipodi/inkskape cruft from Qt SVG Change-Id: Ib2d77331b33cac97e819e8273362703fcd80886c Reviewed-by: Allan Sandfeld Jensen --- src/plugins/platforms/wasm/qtlogo.svg | 29 +---------------------------- 1 file changed, 1 insertion(+), 28 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/wasm/qtlogo.svg b/src/plugins/platforms/wasm/qtlogo.svg index cb8989bb79..ad7c7776bf 100644 --- a/src/plugins/platforms/wasm/qtlogo.svg +++ b/src/plugins/platforms/wasm/qtlogo.svg @@ -5,15 +5,10 @@ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="462pt" height="339pt" viewBox="0 0 462 339" - version="1.1" - id="svg2" - inkscape:version="0.91 r13725" - sodipodi:docname="TheQtCompany_logo_2.svg"> + version="1.1"> @@ -26,28 +21,6 @@ - - Date: Tue, 30 Apr 2019 09:44:18 +0200 Subject: QList: do not call std::swap directly; use ADL Change-Id: Iaf6b965dd123f39436ba134ea1065d8dc4278c1e Reviewed-by: Thiago Macieira --- src/corelib/tools/qlist.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index dfb8a8a4ab..48a71b0ecf 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -709,7 +709,8 @@ inline void QList::swapItemsAt(int i, int j) Q_ASSERT_X(i >= 0 && i < p.size() && j >= 0 && j < p.size(), "QList::swap", "index out of range"); detach(); - std::swap(d->array[d->begin + i], d->array[d->begin + j]); + using std::swap; + swap(d->array[d->begin + i], d->array[d->begin + j]); } template -- cgit v1.2.3 From 9ec564b0bfc94c2d33f02b24ca081b64ff9ebb9b Mon Sep 17 00:00:00 2001 From: James McDonnell Date: Fri, 4 May 2018 14:23:51 -0400 Subject: Basic foreign window support for QNX Requires a screen with working context permission parsing. Currently, all context permission requests fail because the parsing is incorrect. A context permission is added temporarily to prevent CLOSE/CREATE events when Qt reparents foreign windows. Qt does this temporarily when a foreign window is wrapped in a widget. Change-Id: I84c18e70d43239286fcd53715332d7015cf1a826 Reviewed-by: Rafael Roquetto --- src/plugins/platforms/qnx/qnx.pro | 2 + src/plugins/platforms/qnx/qqnxforeignwindow.cpp | 65 +++++++++++ src/plugins/platforms/qnx/qqnxforeignwindow.h | 61 ++++++++++ src/plugins/platforms/qnx/qqnxintegration.cpp | 27 ++++- src/plugins/platforms/qnx/qqnxintegration.h | 7 +- .../platforms/qnx/qqnxscreeneventhandler.cpp | 49 ++++++++ src/plugins/platforms/qnx/qqnxscreentraits.h | 127 +++++++++++++++++++++ src/plugins/platforms/qnx/qqnxwindow.cpp | 96 +++++++++++++++- src/plugins/platforms/qnx/qqnxwindow.h | 8 +- 9 files changed, 432 insertions(+), 10 deletions(-) create mode 100644 src/plugins/platforms/qnx/qqnxforeignwindow.cpp create mode 100644 src/plugins/platforms/qnx/qqnxforeignwindow.h create mode 100644 src/plugins/platforms/qnx/qqnxscreentraits.h (limited to 'src') diff --git a/src/plugins/platforms/qnx/qnx.pro b/src/plugins/platforms/qnx/qnx.pro index 96bfa1dd19..bfd56e8d13 100644 --- a/src/plugins/platforms/qnx/qnx.pro +++ b/src/plugins/platforms/qnx/qnx.pro @@ -33,6 +33,7 @@ QT += \ SOURCES = main.cpp \ qqnxbuffer.cpp \ + qqnxforeignwindow.cpp \ qqnxintegration.cpp \ qqnxscreen.cpp \ qqnxwindow.cpp \ @@ -50,6 +51,7 @@ SOURCES = main.cpp \ HEADERS = main.h \ qqnxbuffer.h \ + qqnxforeignwindow.h \ qqnxkeytranslator.h \ qqnxintegration.h \ qqnxscreen.h \ diff --git a/src/plugins/platforms/qnx/qqnxforeignwindow.cpp b/src/plugins/platforms/qnx/qqnxforeignwindow.cpp new file mode 100644 index 0000000000..94608215dc --- /dev/null +++ b/src/plugins/platforms/qnx/qqnxforeignwindow.cpp @@ -0,0 +1,65 @@ +/*************************************************************************** +** +** Copyright (C) 2018 QNX Software Systems. All rights reserved. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qqnxforeignwindow.h" +#include "qqnxintegration.h" + +QT_BEGIN_NAMESPACE + +QQnxForeignWindow::QQnxForeignWindow(QWindow *window, + screen_context_t context, + screen_window_t screenWindow) + : QQnxWindow(window, context, screenWindow) +{ + initWindow(); +} + +bool QQnxForeignWindow::isForeignWindow() const +{ + return true; +} + +int QQnxForeignWindow::pixelFormat() const +{ + int result = SCREEN_FORMAT_RGBA8888; + screen_get_window_property_iv(nativeHandle(), SCREEN_PROPERTY_FORMAT, &result); + return result; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/qnx/qqnxforeignwindow.h b/src/plugins/platforms/qnx/qqnxforeignwindow.h new file mode 100644 index 0000000000..22dde643e4 --- /dev/null +++ b/src/plugins/platforms/qnx/qqnxforeignwindow.h @@ -0,0 +1,61 @@ +/*************************************************************************** +** +** Copyright (C) 2018 QNX Software Systems. All rights reserved. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQNXFOREIGNWINDOW_H +#define QQNXFOREIGNWINDOW_H + +#include "qqnxwindow.h" + +QT_BEGIN_NAMESPACE + +class QQnxForeignWindow : public QQnxWindow +{ +public: + QQnxForeignWindow(QWindow *window, + screen_context_t context, + screen_window_t screenWindow); + + bool isForeignWindow() const override; + int pixelFormat() const override; + void resetBuffers() override {} +}; + +QT_END_NAMESPACE + +#endif // QQNXFOREIGNWINDOW_H diff --git a/src/plugins/platforms/qnx/qqnxintegration.cpp b/src/plugins/platforms/qnx/qqnxintegration.cpp index a45dcabeb7..d9120256b3 100644 --- a/src/plugins/platforms/qnx/qqnxintegration.cpp +++ b/src/plugins/platforms/qnx/qqnxintegration.cpp @@ -51,6 +51,7 @@ #include "qqnxabstractvirtualkeyboard.h" #include "qqnxservices.h" +#include "qqnxforeignwindow.h" #include "qqnxrasterwindow.h" #if !defined(QT_NO_OPENGL) #include "qqnxeglwindow.h" @@ -147,6 +148,7 @@ static inline int getContextCapabilities(const QStringList ¶mList) QQnxIntegration::QQnxIntegration(const QStringList ¶mList) : QPlatformIntegration() + , m_screenContextId(256, 0) , m_screenEventThread(0) , m_navigatorEventHandler(new QQnxNavigatorEventHandler()) , m_virtualKeyboard(0) @@ -178,6 +180,11 @@ QQnxIntegration::QQnxIntegration(const QStringList ¶mList) qFatal("%s - Screen: Failed to create screen context - Error: %s (%i)", Q_FUNC_INFO, strerror(errno), errno); } + screen_get_context_property_cv(m_screenContext, + SCREEN_PROPERTY_ID, + m_screenContextId.size(), + m_screenContextId.data()); + m_screenContextId.resize(strlen(m_screenContextId.constData())); #if QT_CONFIG(qqnx_pps) // Create/start navigator event notifier @@ -310,6 +317,7 @@ bool QQnxIntegration::hasCapability(QPlatformIntegration::Capability cap) const qIntegrationDebug(); switch (cap) { case MultipleWindows: + case ForeignWindows: case ThreadedPixmaps: return true; #if !defined(QT_NO_OPENGL) @@ -323,6 +331,18 @@ bool QQnxIntegration::hasCapability(QPlatformIntegration::Capability cap) const } } +QPlatformWindow *QQnxIntegration::createForeignWindow(QWindow *window, WId nativeHandle) const +{ + screen_window_t screenWindow = reinterpret_cast(nativeHandle); + if (this->window(screenWindow)) { + qWarning() << "QWindow already created for foreign window" + << screenWindow; + return nullptr; + } + + return new QQnxForeignWindow(window, m_screenContext, screenWindow); +} + QPlatformWindow *QQnxIntegration::createPlatformWindow(QWindow *window) const { qIntegrationDebug(); @@ -478,7 +498,7 @@ QPlatformServices * QQnxIntegration::services() const return m_services; } -QWindow *QQnxIntegration::window(screen_window_t qnxWindow) +QWindow *QQnxIntegration::window(screen_window_t qnxWindow) const { qIntegrationDebug(); QMutexLocker locker(&m_windowMapperMutex); @@ -706,6 +726,11 @@ screen_context_t QQnxIntegration::screenContext() return m_screenContext; } +QByteArray QQnxIntegration::screenContextId() +{ + return m_screenContextId; +} + QQnxNavigatorEventHandler *QQnxIntegration::navigatorEventHandler() { return m_navigatorEventHandler; diff --git a/src/plugins/platforms/qnx/qqnxintegration.h b/src/plugins/platforms/qnx/qqnxintegration.h index 366556dc4b..0bf37880d1 100644 --- a/src/plugins/platforms/qnx/qqnxintegration.h +++ b/src/plugins/platforms/qnx/qqnxintegration.h @@ -92,6 +92,7 @@ public: bool hasCapability(QPlatformIntegration::Capability cap) const override; + QPlatformWindow *createForeignWindow(QWindow *window, WId nativeHandle) const override; QPlatformWindow *createPlatformWindow(QWindow *window) const override; QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const override; @@ -123,7 +124,7 @@ public: QPlatformServices *services() const override; - QWindow *window(screen_window_t qnxWindow); + QWindow *window(screen_window_t qnxWindow) const; QQnxScreen *screenForNative(screen_display_t qnxScreen) const; @@ -132,6 +133,7 @@ public: QQnxScreen *primaryDisplay() const; Options options() const; screen_context_t screenContext(); + QByteArray screenContextId(); QQnxNavigatorEventHandler *navigatorEventHandler(); @@ -145,6 +147,7 @@ private: int displayCount); screen_context_t m_screenContext; + QByteArray m_screenContextId; QQnxScreenEventThread *m_screenEventThread; QQnxNavigatorEventHandler *m_navigatorEventHandler; QQnxAbstractVirtualKeyboard *m_virtualKeyboard; @@ -168,7 +171,7 @@ private: QSimpleDrag *m_drag; #endif QQnxWindowMapper m_windowMapper; - QMutex m_windowMapperMutex; + mutable QMutex m_windowMapperMutex; Options m_options; diff --git a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp index c2471751f5..56131dcc48 100644 --- a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp +++ b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp @@ -45,6 +45,7 @@ #include "qqnxkeytranslator.h" #include "qqnxscreen.h" #include "qqnxscreeneventfilter.h" +#include "qqnxscreentraits.h" #include #include @@ -89,6 +90,51 @@ static QString capKeyString(int cap, int modifiers, int key) return QString(); } +template +static void finishCloseEvent(screen_event_t event) +{ + T t; + screen_get_event_property_pv(event, + screen_traits::propertyName, + reinterpret_cast(&t)); + screen_traits::destroy(t); +} + +static void finishCloseEvent(screen_event_t event) +{ + // Let libscreen know that we're finished with anything that may have been acquired. + int objectType = SCREEN_OBJECT_TYPE_CONTEXT; + screen_get_event_property_iv(event, SCREEN_PROPERTY_OBJECT_TYPE, &objectType); + switch (objectType) { + case SCREEN_OBJECT_TYPE_CONTEXT: + finishCloseEvent(event); + break; + case SCREEN_OBJECT_TYPE_DEVICE: + finishCloseEvent(event); + break; + case SCREEN_OBJECT_TYPE_DISPLAY: + // no screen_destroy_display + break; + case SCREEN_OBJECT_TYPE_GROUP: + finishCloseEvent(event); + break; + case SCREEN_OBJECT_TYPE_PIXMAP: + finishCloseEvent(event); + break; + case SCREEN_OBJECT_TYPE_SESSION: + finishCloseEvent(event); + break; +#if _SCREEN_VERSION >= _SCREEN_MAKE_VERSION(2, 0, 0) + case SCREEN_OBJECT_TYPE_STREAM: + finishCloseEvent(event); + break; +#endif + case SCREEN_OBJECT_TYPE_WINDOW: + finishCloseEvent(event); + break; + } +} + QT_BEGIN_NAMESPACE QQnxScreenEventHandler::QQnxScreenEventHandler(QQnxIntegration *integration) @@ -251,6 +297,9 @@ void QQnxScreenEventHandler::processEvents() bool handled = dispatcher && dispatcher->filterNativeEvent(QByteArrayLiteral("screen_event_t"), event, &result); if (!handled) handleEvent(event); + + if (type == SCREEN_EVENT_CLOSE) + finishCloseEvent(event); } m_eventThread->armEventsPending(count); diff --git a/src/plugins/platforms/qnx/qqnxscreentraits.h b/src/plugins/platforms/qnx/qqnxscreentraits.h new file mode 100644 index 0000000000..ebd74141f2 --- /dev/null +++ b/src/plugins/platforms/qnx/qqnxscreentraits.h @@ -0,0 +1,127 @@ +/*************************************************************************** +** +** Copyright (C) 2018 QNX Software Systems. All rights reserved. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQNXSCREENTRAITS_H +#define QQNXSCREENTRAITS_H + +#include + +QT_BEGIN_NAMESPACE + +template +class screen_traits +{ +}; + +template <> +class screen_traits +{ +public: + typedef screen_context_t screen_type; + static const int propertyName = SCREEN_PROPERTY_CONTEXT; + static int destroy(screen_context_t context) { return screen_destroy_context(context); } +}; + +template <> +class screen_traits +{ +public: + typedef screen_device_t screen_type; + static const int propertyName = SCREEN_PROPERTY_DEVICE; + static int destroy(screen_device_t device) { return screen_destroy_device(device); } +}; + +template <> +class screen_traits +{ +public: + typedef screen_display_t screen_type; + static const int propertyName = SCREEN_PROPERTY_DISPLAY; +}; + +template <> +class screen_traits +{ +public: + typedef screen_group_t screen_type; + static const int propertyName = SCREEN_PROPERTY_GROUP; + static int destroy(screen_group_t group) { return screen_destroy_group(group); } +}; + +template <> +class screen_traits +{ +public: + typedef screen_pixmap_t screen_type; + static const int propertyName = SCREEN_PROPERTY_PIXMAP; + static int destroy(screen_pixmap_t pixmap) { return screen_destroy_pixmap(pixmap); } +}; + +template <> +class screen_traits +{ +public: + typedef screen_session_t screen_type; + static const int propertyName = SCREEN_PROPERTY_SESSION; + static int destroy(screen_session_t session) { return screen_destroy_session(session); } +}; + +#if _SCREEN_VERSION >= _SCREEN_MAKE_VERSION(2, 0, 0) +template <> +class screen_traits +{ +public: + typedef screen_stream_t screen_type; + static const int propertyName = SCREEN_PROPERTY_STREAM; + static int destroy(screen_stream_t stream) { return screen_destroy_stream(stream); } +}; +#endif + +template <> +class screen_traits +{ +public: + typedef screen_window_t screen_type; + static const int propertyName = SCREEN_PROPERTY_WINDOW; + static int destroy(screen_window_t window) { return screen_destroy_window(window); } +}; + +QT_END_NAMESPACE + +#endif // QQNXSCREENTRAITS_H diff --git a/src/plugins/platforms/qnx/qqnxwindow.cpp b/src/plugins/platforms/qnx/qqnxwindow.cpp index 7644e28b44..1d3d609017 100644 --- a/src/plugins/platforms/qnx/qqnxwindow.cpp +++ b/src/plugins/platforms/qnx/qqnxwindow.cpp @@ -155,6 +155,7 @@ QQnxWindow::QQnxWindow(QWindow *window, screen_context_t context, bool needRootW m_parentWindow(0), m_visible(false), m_exposed(true), + m_foreign(false), m_windowState(Qt::WindowNoState), m_mmRendererWindow(0), m_firstActivateHandled(false) @@ -254,6 +255,39 @@ QQnxWindow::QQnxWindow(QWindow *window, screen_context_t context, bool needRootW } } +QQnxWindow::QQnxWindow(QWindow *window, screen_context_t context, screen_window_t screenWindow) + : QPlatformWindow(window) + , m_screenContext(context) + , m_window(screenWindow) + , m_screen(0) + , m_parentWindow(0) + , m_visible(false) + , m_exposed(true) + , m_foreign(true) + , m_windowState(Qt::WindowNoState) + , m_mmRendererWindow(0) + , m_parentGroupName(256, 0) + , m_isTopLevel(false) +{ + qWindowDebug() << "window =" << window << ", size =" << window->size(); + + collectWindowGroup(); + + screen_get_window_property_cv(m_window, + SCREEN_PROPERTY_PARENT, + m_parentGroupName.size(), + m_parentGroupName.data()); + m_parentGroupName.resize(strlen(m_parentGroupName.constData())); + + // If a window group has been provided join it now. If it's an empty string that's OK too, + // it'll cause us not to join a group (the app will presumably join at some future time). + QVariant parentGroup = window->property("qnxInitialWindowGroup"); + if (!parentGroup.isValid()) + parentGroup = window->property("_q_platform_qnxParentGroup"); + if (parentGroup.isValid() && parentGroup.canConvert()) + joinWindowGroup(parentGroup.toByteArray()); +} + QQnxWindow::~QQnxWindow() { qWindowDebug() << "window =" << window(); @@ -270,7 +304,11 @@ QQnxWindow::~QQnxWindow() m_screen->updateHierarchy(); // Cleanup QNX window and its buffers - screen_destroy_window(m_window); + // Foreign windows are cleaned up externally after the CLOSE event has been handled. + if (m_foreign) + removeContextPermission(); + else + screen_destroy_window(m_window); } void QQnxWindow::setGeometry(const QRect &rect) @@ -793,14 +831,24 @@ void QQnxWindow::initWindow() setGeometryHelper(shouldMakeFullScreen() ? screen()->geometry() : window()->geometry()); } -void QQnxWindow::createWindowGroup() +void QQnxWindow::collectWindowGroup() { - // Generate a random window group name - m_windowGroupName = QUuid::createUuid().toByteArray(); + QByteArray groupName(256, 0); + Q_SCREEN_CHECKERROR(screen_get_window_property_cv(m_window, + SCREEN_PROPERTY_GROUP, + groupName.size(), + groupName.data()), + "Failed to retrieve window group"); + groupName.resize(strlen(groupName.constData())); + m_windowGroupName = groupName; +} - // Create window group so child windows can be parented by container window - Q_SCREEN_CHECKERROR(screen_create_window_group(m_window, m_windowGroupName.constData()), +void QQnxWindow::createWindowGroup() +{ + Q_SCREEN_CHECKERROR(screen_create_window_group(m_window, nullptr), "Failed to create window group"); + + collectWindowGroup(); } void QQnxWindow::joinWindowGroup(const QByteArray &groupName) @@ -809,6 +857,17 @@ void QQnxWindow::joinWindowGroup(const QByteArray &groupName) qWindowDebug() << "group:" << groupName; + // screen has this annoying habit of generating a CLOSE/CREATE when the owner context of + // the parent group moves a foreign window to another group that it also owns. The + // CLOSE/CREATE changes the identity of the foreign window. Usually, this is undesirable. + // To prevent this CLOSE/CREATE when changing the parent group, we temporarily add a + // context permission for the Qt context. screen won't send a CLOSE/CREATE when the + // context has some permission other than the PARENT permission. If there isn't a new + // group (the window has no parent), this context permission is left in place. + + if (m_foreign && !m_parentGroupName.isEmpty())\ + addContextPermission(); + if (!groupName.isEmpty()) { if (groupName != m_parentGroupName) { screen_join_window_group(m_window, groupName); @@ -827,6 +886,9 @@ void QQnxWindow::joinWindowGroup(const QByteArray &groupName) m_parentGroupName = ""; } + if (m_foreign && !groupName.isEmpty()) + removeContextPermission(); + if (changed) screen_flush_context(m_screenContext, 0); } @@ -899,4 +961,26 @@ bool QQnxWindow::focusable() const return (window()->flags() & Qt::WindowDoesNotAcceptFocus) != Qt::WindowDoesNotAcceptFocus; } +void QQnxWindow::addContextPermission() +{ + QByteArray grantString("context:"); + grantString.append(QQnxIntegration::instance()->screenContextId()); + grantString.append(":rw-"); + screen_set_window_property_cv(m_window, + SCREEN_PROPERTY_PERMISSIONS, + grantString.length(), + grantString.data()); +} + +void QQnxWindow::removeContextPermission() +{ + QByteArray revokeString("context:"); + revokeString.append(QQnxIntegration::instance()->screenContextId()); + revokeString.append(":---"); + screen_set_window_property_cv(m_window, + SCREEN_PROPERTY_PERMISSIONS, + revokeString.length(), + revokeString.data()); +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/qnx/qqnxwindow.h b/src/plugins/platforms/qnx/qqnxwindow.h index 20c38cb4b7..9040619c41 100644 --- a/src/plugins/platforms/qnx/qqnxwindow.h +++ b/src/plugins/platforms/qnx/qqnxwindow.h @@ -64,7 +64,8 @@ class QQnxWindow : public QPlatformWindow { friend class QQnxScreen; public: - QQnxWindow(QWindow *window, screen_context_t context, bool needRootWindow); + explicit QQnxWindow(QWindow *window, screen_context_t context, bool needRootWindow); + explicit QQnxWindow(QWindow *window, screen_context_t context, screen_window_t screenWindow); virtual ~QQnxWindow(); void setGeometry(const QRect &rect) override; @@ -124,6 +125,7 @@ protected: screen_context_t m_screenContext; private: + void collectWindowGroup(); void createWindowGroup(); void setGeometryHelper(const QRect &rect); void removeFromParent(); @@ -135,6 +137,9 @@ private: bool showWithoutActivating() const; bool focusable() const; + void addContextPermission(); + void removeContextPermission(); + screen_window_t m_window; QSize m_bufferSize; @@ -144,6 +149,7 @@ private: QScopedPointer m_cover; bool m_visible; bool m_exposed; + bool m_foreign; QRect m_unmaximizedGeometry; Qt::WindowStates m_windowState; QString m_mmRendererWindowName; -- cgit v1.2.3 From 23c2da3cc23a2e04a0b3b3c8ad7fa9cc6126ff23 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Tue, 19 Dec 2017 15:25:55 +0100 Subject: Add QTextMarkdownWriter, QTextEdit::markdown property etc. A QTextDocument can now be written out in Markdown format. - Add the QTextMarkdownWriter as a private class for now - Add QTextDocument::toMarkdown() - QTextDocumentWriter uses QTextMarkdownWriter if setFormat("markdown") is called or if the file suffix is .md or .mkd - Add QTextEdit::toMarkdown() and the markdown property [ChangeLog][QtGui][Text] Markdown (CommonMark or GitHub dialect) is now a supported format for reading into and writing from QTextDocument. Change-Id: I663a77017fac7ae1b3f9a400f5cd357bb40750af Reviewed-by: Gatis Paeglis --- src/gui/configure.json | 8 +- src/gui/text/qtextdocument.cpp | 34 ++- src/gui/text/qtextdocument.h | 8 +- src/gui/text/qtextdocumentwriter.cpp | 19 ++ src/gui/text/qtextmarkdownwriter.cpp | 363 +++++++++++++++++++++++++++++ src/gui/text/qtextmarkdownwriter_p.h | 78 +++++++ src/gui/text/text.pri | 7 + src/widgets/widgets/qtextedit.cpp | 62 ++++- src/widgets/widgets/qtextedit.h | 8 +- src/widgets/widgets/qwidgettextcontrol.cpp | 7 + src/widgets/widgets/qwidgettextcontrol_p.h | 3 + 11 files changed, 586 insertions(+), 11 deletions(-) create mode 100644 src/gui/text/qtextmarkdownwriter.cpp create mode 100644 src/gui/text/qtextmarkdownwriter_p.h (limited to 'src') diff --git a/src/gui/configure.json b/src/gui/configure.json index d7c0da4640..9e76fc455e 100644 --- a/src/gui/configure.json +++ b/src/gui/configure.json @@ -1611,6 +1611,12 @@ "condition": "libs.libmd4c", "output": [ "publicFeature" ] }, + "textmarkdownwriter": { + "label": "MarkdownWriter", + "purpose": "Provides a Markdown (CommonMark) writer", + "section": "Kernel", + "output": [ "publicFeature" ] + }, "textodfwriter": { "label": "OdfWriter", "purpose": "Provides an ODF writer.", @@ -1892,7 +1898,7 @@ QMAKE_LIBDIR_OPENGL[_ES2] and QMAKE_LIBS_OPENGL[_ES2] in the mkspec for your pla { "section": "Text formats", "entries": [ - "texthtmlparser", "cssparser", "textodfwriter", "textmarkdownreader", "system-textmarkdownreader" + "texthtmlparser", "cssparser", "textodfwriter", "textmarkdownreader", "system-textmarkdownreader", "textmarkdownwriter" ] }, "egl", diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp index 87c8f1ba8a..0a59bfb838 100644 --- a/src/gui/text/qtextdocument.cpp +++ b/src/gui/text/qtextdocument.cpp @@ -73,6 +73,9 @@ #if QT_CONFIG(textmarkdownreader) #include #endif +#if QT_CONFIG(textmarkdownwriter) +#include +#endif #include @@ -3288,6 +3291,22 @@ QString QTextDocument::toHtml(const QByteArray &encoding) const } #endif // QT_NO_TEXTHTMLPARSER +/*! + Returns a string containing a Markdown representation of the document, + or an empty string if writing fails for any reason. +*/ +#if QT_CONFIG(textmarkdownwriter) +QString QTextDocument::toMarkdown(QTextDocument::MarkdownFeatures features) const +{ + QString ret; + QTextStream s(&ret); + QTextMarkdownWriter w(s, features); + if (w.writeAll(*this)) + return ret; + return QString(); +} +#endif + /*! Replaces the entire contents of the document with the given Markdown-formatted text in the \a markdown string, with the given @@ -3301,8 +3320,19 @@ QString QTextDocument::toHtml(const QByteArray &encoding) const Parsing of HTML included in the \a markdown string is handled in the same way as in \l setHtml; however, Markdown formatting inside HTML blocks is - not supported. The \c MarkdownNoHTML feature flag can be set to disable - HTML parsing. + not supported. + + Some features of the parser can be enabled or disabled via the \a features + argument: + + \value MarkdownNoHTML + Any HTML tags in the Markdown text will be discarded + \value MarkdownDialectCommonMark + The parser supports only the features standardized by CommonMark + \value MarkdownDialectGitHub + The parser supports the GitHub dialect + + The default is \c MarkdownDialectGitHub. The undo/redo history is reset when this function is called. */ diff --git a/src/gui/text/qtextdocument.h b/src/gui/text/qtextdocument.h index ade67999ad..31c06976a5 100644 --- a/src/gui/text/qtextdocument.h +++ b/src/gui/text/qtextdocument.h @@ -151,7 +151,7 @@ public: void setHtml(const QString &html); #endif -#if QT_CONFIG(textmarkdownreader) +#if QT_CONFIG(textmarkdownwriter) || QT_CONFIG(textmarkdownreader) // Must be in sync with QTextMarkdownImporter::Features, should be in sync with #define MD_FLAG_* in md4c enum MarkdownFeature { MarkdownNoHTML = 0x0020 | 0x0040, @@ -160,7 +160,13 @@ public: }; Q_DECLARE_FLAGS(MarkdownFeatures, MarkdownFeature) Q_FLAG(MarkdownFeatures) +#endif +#if QT_CONFIG(textmarkdownwriter) + QString toMarkdown(MarkdownFeatures features = MarkdownDialectGitHub) const; +#endif + +#if QT_CONFIG(textmarkdownreader) void setMarkdown(const QString &markdown, MarkdownFeatures features = MarkdownDialectGitHub); #endif diff --git a/src/gui/text/qtextdocumentwriter.cpp b/src/gui/text/qtextdocumentwriter.cpp index 42e623153a..c82ff873cd 100644 --- a/src/gui/text/qtextdocumentwriter.cpp +++ b/src/gui/text/qtextdocumentwriter.cpp @@ -51,6 +51,9 @@ #include "qtextdocumentfragment_p.h" #include "qtextodfwriter_p.h" +#if QT_CONFIG(textmarkdownwriter) +#include "qtextmarkdownwriter_p.h" +#endif #include @@ -267,6 +270,18 @@ bool QTextDocumentWriter::write(const QTextDocument *document) } #endif // QT_NO_TEXTODFWRITER +#if QT_CONFIG(textmarkdownwriter) + if (format == "md" || format == "mkd" || format == "markdown") { + if (!d->device->isWritable() && !d->device->open(QIODevice::WriteOnly)) { + qWarning("QTextDocumentWriter::write: the device can not be opened for writing"); + return false; + } + QTextStream s(d->device); + QTextMarkdownWriter writer(s, QTextDocument::MarkdownDialectGitHub); + return writer.writeAll(*document); + } +#endif // textmarkdownwriter + #ifndef QT_NO_TEXTHTMLPARSER if (format == "html" || format == "htm") { if (!d->device->isWritable() && ! d->device->open(QIODevice::WriteOnly)) { @@ -348,6 +363,7 @@ QTextCodec *QTextDocumentWriter::codec() const \header \li Format \li Description \row \li plaintext \li Plain text \row \li HTML \li HyperText Markup Language + \row \li markdown \li Markdown (CommonMark or GitHub dialects) \row \li ODF \li OpenDocument Format \endtable @@ -364,6 +380,9 @@ QList QTextDocumentWriter::supportedDocumentFormats() #ifndef QT_NO_TEXTODFWRITER answer << "ODF"; #endif // QT_NO_TEXTODFWRITER +#if QT_CONFIG(textmarkdownwriter) + answer << "markdown"; +#endif std::sort(answer.begin(), answer.end()); return answer; diff --git a/src/gui/text/qtextmarkdownwriter.cpp b/src/gui/text/qtextmarkdownwriter.cpp new file mode 100644 index 0000000000..c91248757a --- /dev/null +++ b/src/gui/text/qtextmarkdownwriter.cpp @@ -0,0 +1,363 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qtextmarkdownwriter_p.h" +#include "qtextdocumentlayout_p.h" +#include "qfontinfo.h" +#include "qfontmetrics.h" +#include "qtextdocument_p.h" +#include "qtextlist.h" +#include "qtexttable.h" +#include "qtextcursor.h" +#include "qtextimagehandler_p.h" + +QT_BEGIN_NAMESPACE + +static const QChar Space = QLatin1Char(' '); +static const QChar Newline = QLatin1Char('\n'); +static const QChar Backtick = QLatin1Char('`'); + +QTextMarkdownWriter::QTextMarkdownWriter(QTextStream &stream, QTextDocument::MarkdownFeatures features) + : m_stream(stream), m_features(features) +{ +} + +bool QTextMarkdownWriter::writeAll(const QTextDocument &document) +{ + writeFrame(document.rootFrame()); + return true; +} + +void QTextMarkdownWriter::writeFrame(const QTextFrame *frame) +{ + Q_ASSERT(frame); + const QTextTable *table = qobject_cast (frame); + QTextFrame::iterator iterator = frame->begin(); + QTextFrame *child = 0; + int tableRow = -1; + bool lastWasList = false; + QVector tableColumnWidths; + if (table) { + tableColumnWidths.resize(table->columns()); + for (int col = 0; col < table->columns(); ++col) { + for (int row = 0; row < table->rows(); ++ row) { + QTextTableCell cell = table->cellAt(row, col); + int cellTextLen = 0; + auto it = cell.begin(); + while (it != cell.end()) { + QTextBlock block = it.currentBlock(); + if (block.isValid()) + cellTextLen += block.text().length(); + ++it; + } + if (cell.columnSpan() == 1 && tableColumnWidths[col] < cellTextLen) + tableColumnWidths[col] = cellTextLen; + } + } + } + while (!iterator.atEnd()) { + if (iterator.currentFrame() && child != iterator.currentFrame()) + writeFrame(iterator.currentFrame()); + else { // no frame, it's a block + QTextBlock block = iterator.currentBlock(); + if (table) { + QTextTableCell cell = table->cellAt(block.position()); + if (tableRow < cell.row()) { + if (tableRow == 0) { + m_stream << Newline; + for (int col = 0; col < tableColumnWidths.length(); ++col) + m_stream << '|' << QString(tableColumnWidths[col], QLatin1Char('-')); + m_stream << '|'; + } + m_stream << Newline << "|"; + tableRow = cell.row(); + } + } else if (!block.textList()) { + if (lastWasList) + m_stream << Newline; + } + int endingCol = writeBlock(block, !table, table && tableRow == 0); + if (table) { + QTextTableCell cell = table->cellAt(block.position()); + int paddingLen = -endingCol; + int spanEndCol = cell.column() + cell.columnSpan(); + for (int col = cell.column(); col < spanEndCol; ++col) + paddingLen += tableColumnWidths[col]; + if (paddingLen > 0) + m_stream << QString(paddingLen, Space); + for (int col = cell.column(); col < spanEndCol; ++col) + m_stream << "|"; + } else if (block.textList()) { + m_stream << Newline; + } else if (endingCol > 0) { + m_stream << Newline << Newline; + } + lastWasList = block.textList(); + } + child = iterator.currentFrame(); + ++iterator; + } + if (table) + m_stream << Newline << Newline; +} + +static int nearestWordWrapIndex(const QString &s, int before) +{ + before = qMin(before, s.length()); + for (int i = before - 1; i >= 0; --i) { + if (s.at(i).isSpace()) + return i; + } + return -1; +} + +static int adjacentBackticksCount(const QString &s) +{ + int start = -1, len = s.length(); + int ret = 0; + for (int i = 0; i < len; ++i) { + if (s.at(i) == Backtick) { + if (start < 0) + start = i; + } else if (start >= 0) { + ret = qMax(ret, i - start); + start = -1; + } + } + if (s.at(len - 1) == Backtick) + ret = qMax(ret, len - start); + return ret; +} + +static void maybeEscapeFirstChar(QString &s) +{ + QString sTrimmed = s.trimmed(); + if (sTrimmed.isEmpty()) + return; + char firstChar = sTrimmed.at(0).toLatin1(); + if (firstChar == '*' || firstChar == '+' || firstChar == '-') { + int i = s.indexOf(QLatin1Char(firstChar)); + s.insert(i, QLatin1Char('\\')); + } +} + +int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ignoreFormat) +{ + int ColumnLimit = 80; + int wrapIndent = 0; + if (block.textList()) { // it's a list-item + auto fmt = block.textList()->format(); + const int listLevel = fmt.indent(); + const int number = block.textList()->itemNumber(block) + 1; + QByteArray bullet = " "; + bool numeric = false; + switch (fmt.style()) { + case QTextListFormat::ListDisc: bullet = "-"; break; + case QTextListFormat::ListCircle: bullet = "*"; break; + case QTextListFormat::ListSquare: bullet = "+"; break; + case QTextListFormat::ListStyleUndefined: break; + case QTextListFormat::ListDecimal: + case QTextListFormat::ListLowerAlpha: + case QTextListFormat::ListUpperAlpha: + case QTextListFormat::ListLowerRoman: + case QTextListFormat::ListUpperRoman: + numeric = true; + break; + } + switch (block.blockFormat().marker()) { + case QTextBlockFormat::Checked: + bullet += " [x]"; + break; + case QTextBlockFormat::Unchecked: + bullet += " [ ]"; + break; + default: + break; + } + QString prefix((listLevel - 1) * (numeric ? 4 : 2), Space); + if (numeric) + prefix += QString::number(number) + fmt.numberSuffix() + Space; + else + prefix += QLatin1String(bullet) + Space; + m_stream << prefix; + wrapIndent = prefix.length(); + } + + if (block.blockFormat().headingLevel()) + m_stream << QByteArray(block.blockFormat().headingLevel(), '#') << ' '; + + QString wrapIndentString(wrapIndent, Space); + // It would be convenient if QTextStream had a lineCharPos() accessor, + // to keep track of how many characters (not bytes) have been written on the current line, + // but it doesn't. So we have to keep track with this col variable. + int col = wrapIndent; + bool mono = false; + bool startsOrEndsWithBacktick = false; + bool bold = false; + bool italic = false; + bool underline = false; + bool strikeOut = false; + QString backticks(Backtick); + for (QTextBlock::Iterator frag = block.begin(); !frag.atEnd(); ++frag) { + QString fragmentText = frag.fragment().text(); + while (fragmentText.endsWith(QLatin1Char('\n'))) + fragmentText.chop(1); + startsOrEndsWithBacktick |= fragmentText.startsWith(Backtick) || fragmentText.endsWith(Backtick); + QTextCharFormat fmt = frag.fragment().charFormat(); + if (fmt.isImageFormat()) { + QTextImageFormat ifmt = fmt.toImageFormat(); + QString s = QLatin1String("![image](") + ifmt.name() + QLatin1Char(')'); + if (wrap && col + s.length() > ColumnLimit) { + m_stream << Newline << wrapIndentString; + col = wrapIndent; + } + m_stream << s; + col += s.length(); + } else if (fmt.hasProperty(QTextFormat::AnchorHref)) { + QString s = QLatin1Char('[') + fragmentText + QLatin1String("](") + + fmt.property(QTextFormat::AnchorHref).toString() + QLatin1Char(')'); + if (wrap && col + s.length() > ColumnLimit) { + m_stream << Newline << wrapIndentString; + col = wrapIndent; + } + m_stream << s; + col += s.length(); + } else { + QFontInfo fontInfo(fmt.font()); + bool monoFrag = fontInfo.fixedPitch(); + QString markers; + if (!ignoreFormat) { + if (monoFrag != mono) { + if (monoFrag) + backticks = QString::fromLatin1(QByteArray(adjacentBackticksCount(fragmentText) + 1, '`')); + markers += backticks; + if (startsOrEndsWithBacktick) + markers += Space; + mono = monoFrag; + } + if (!block.blockFormat().headingLevel() && !mono) { + if (fmt.font().bold() != bold) { + markers += QLatin1String("**"); + bold = fmt.font().bold(); + } + if (fmt.font().italic() != italic) { + markers += QLatin1Char('*'); + italic = fmt.font().italic(); + } + if (fmt.font().strikeOut() != strikeOut) { + markers += QLatin1String("~~"); + strikeOut = fmt.font().strikeOut(); + } + if (fmt.font().underline() != underline) { + // Markdown doesn't support underline, but the parser will treat a single underline + // the same as a single asterisk, and the marked fragment will be rendered in italics. + // That will have to do. + markers += QLatin1Char('_'); + underline = fmt.font().underline(); + } + } + } + if (wrap && col + markers.length() * 2 + fragmentText.length() > ColumnLimit) { + int i = 0; + int fragLen = fragmentText.length(); + bool breakingLine = false; + while (i < fragLen) { + int j = i + ColumnLimit - col; + if (j < fragLen) { + int wi = nearestWordWrapIndex(fragmentText, j); + if (wi < 0) { + j = fragLen; + } else { + j = wi; + breakingLine = true; + } + } else { + j = fragLen; + breakingLine = false; + } + QString subfrag = fragmentText.mid(i, j - i); + if (!i) { + m_stream << markers; + col += markers.length(); + } + if (col == wrapIndent) + maybeEscapeFirstChar(subfrag); + m_stream << subfrag; + if (breakingLine) { + m_stream << Newline << wrapIndentString; + col = wrapIndent; + } else { + col += subfrag.length(); + } + i = j + 1; + } + } else { + m_stream << markers << fragmentText; + col += markers.length() + fragmentText.length(); + } + } + } + if (mono) { + if (startsOrEndsWithBacktick) { + m_stream << Space; + col += 1; + } + m_stream << backticks; + col += backticks.size(); + } + if (bold) { + m_stream << "**"; + col += 2; + } + if (italic) { + m_stream << "*"; + col += 1; + } + if (underline) { + m_stream << "_"; + col += 1; + } + if (strikeOut) { + m_stream << "~~"; + col += 2; + } + return col; +} + +QT_END_NAMESPACE diff --git a/src/gui/text/qtextmarkdownwriter_p.h b/src/gui/text/qtextmarkdownwriter_p.h new file mode 100644 index 0000000000..9845355259 --- /dev/null +++ b/src/gui/text/qtextmarkdownwriter_p.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTEXTMARKDOWNWRITER_P_H +#define QTEXTMARKDOWNWRITER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include + +#include "qtextdocument_p.h" +#include "qtextdocumentwriter.h" + +QT_BEGIN_NAMESPACE + +class Q_GUI_EXPORT QTextMarkdownWriter +{ +public: + QTextMarkdownWriter(QTextStream &stream, QTextDocument::MarkdownFeatures features); + bool writeAll(const QTextDocument &document); + + int writeBlock(const QTextBlock &block, bool table, bool ignoreFormat); + void writeFrame(const QTextFrame *frame); + +private: + QTextStream &m_stream; + QTextDocument::MarkdownFeatures m_features; +}; + +QT_END_NAMESPACE + +#endif // QTEXTMARKDOWNWRITER_P_H diff --git a/src/gui/text/text.pri b/src/gui/text/text.pri index b35a231747..5e97b312f1 100644 --- a/src/gui/text/text.pri +++ b/src/gui/text/text.pri @@ -109,6 +109,13 @@ qtConfig(textmarkdownreader) { text/qtextmarkdownimporter.cpp } +qtConfig(textmarkdownwriter) { + HEADERS += \ + text/qtextmarkdownwriter_p.h + SOURCES += \ + text/qtextmarkdownwriter.cpp +} + qtConfig(cssparser) { HEADERS += \ text/qcssparser_p.h diff --git a/src/widgets/widgets/qtextedit.cpp b/src/widgets/widgets/qtextedit.cpp index 9e134493b5..5f734258b2 100644 --- a/src/widgets/widgets/qtextedit.cpp +++ b/src/widgets/widgets/qtextedit.cpp @@ -366,8 +366,8 @@ void QTextEditPrivate::_q_ensureVisible(const QRectF &_rect) \section1 Introduction and Concepts QTextEdit is an advanced WYSIWYG viewer/editor supporting rich - text formatting using HTML-style tags. It is optimized to handle - large documents and to respond quickly to user input. + text formatting using HTML-style tags, or Markdown format. It is optimized + to handle large documents and to respond quickly to user input. QTextEdit works on paragraphs and characters. A paragraph is a formatted string which is word-wrapped to fit into the width of @@ -381,7 +381,7 @@ void QTextEditPrivate::_q_ensureVisible(const QRectF &_rect) QTextEdit can display images, lists and tables. If the text is too large to view within the text edit's viewport, scroll bars will appear. The text edit can load both plain text and rich text files. - Rich text is described using a subset of HTML 4 markup, refer to the + Rich text can be described using a subset of HTML 4 markup; refer to the \l {Supported HTML Subset} page for more information. If you just need to display a small piece of rich text use QLabel. @@ -401,12 +401,19 @@ void QTextEditPrivate::_q_ensureVisible(const QRectF &_rect) QTextEdit can display a large HTML subset, including tables and images. - The text is set or replaced using setHtml() which deletes any + The text can be set or replaced using \l setHtml() which deletes any existing text and replaces it with the text passed in the setHtml() call. If you call setHtml() with legacy HTML, and then call toHtml(), the text that is returned may have different markup, but will render the same. The entire text can be deleted with clear(). + Text can also be set or replaced using \l setMarkdown(), and the same + caveats apply: if you then call \l toMarkdown(), the text that is returned + may be different, but the meaning is preserved as much as possible. + Markdown with some embedded HTML can be parsed, with the same limitations + that \l setHtml() has; but \l toMarkdown() only writes "pure" Markdown, + without any embedded HTML. + Text itself can be inserted using the QTextCursor class or using the convenience functions insertHtml(), insertPlainText(), append() or paste(). QTextCursor is also able to insert complex objects like tables @@ -1213,11 +1220,54 @@ QString QTextEdit::toHtml() const } #endif +#if QT_CONFIG(textmarkdownreader) && QT_CONFIG(textmarkdownwriter) +/*! + \property QTextEdit::markdown + + This property provides a Markdown interface to the text of the text edit. + + \c toMarkdown() returns the text of the text edit as "pure" Markdown, + without any embedded HTML formatting. Some features that QTextDocument + supports (such as the use of specific colors and named fonts) cannot be + expressed in "pure" Markdown, and they will be omitted. + + \c setMarkdown() changes the text of the text edit. Any previous text is + removed and the undo/redo history is cleared. The input text is + interpreted as rich text in Markdown format. + + Parsing of HTML included in the \a markdown string is handled in the same + way as in \l setHtml; however, Markdown formatting inside HTML blocks is + not supported. + + Some features of the parser can be enabled or disabled via the \a features + argument: + + \value MarkdownNoHTML + Any HTML tags in the Markdown text will be discarded + \value MarkdownDialectCommonMark + The parser supports only the features standardized by CommonMark + \value MarkdownDialectGitHub + The parser supports the GitHub dialect + + The default is \c MarkdownDialectGitHub. + + \sa plainText, html, QTextDocument::toMarkdown(), QTextDocument::setMarkdown() +*/ +#endif + #if QT_CONFIG(textmarkdownreader) -void QTextEdit::setMarkdown(const QString &text) +void QTextEdit::setMarkdown(const QString &markdown) +{ + Q_D(const QTextEdit); + d->control->setMarkdown(markdown); +} +#endif + +#if QT_CONFIG(textmarkdownwriter) +QString QTextEdit::toMarkdown(QTextDocument::MarkdownFeatures features) const { Q_D(const QTextEdit); - d->control->setMarkdown(text); + return d->control->toMarkdown(features); } #endif diff --git a/src/widgets/widgets/qtextedit.h b/src/widgets/widgets/qtextedit.h index f20bd936c4..3b7e610786 100644 --- a/src/widgets/widgets/qtextedit.h +++ b/src/widgets/widgets/qtextedit.h @@ -71,6 +71,9 @@ class Q_WIDGETS_EXPORT QTextEdit : public QAbstractScrollArea QDOC_PROPERTY(QTextOption::WrapMode wordWrapMode READ wordWrapMode WRITE setWordWrapMode) Q_PROPERTY(int lineWrapColumnOrWidth READ lineWrapColumnOrWidth WRITE setLineWrapColumnOrWidth) Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly) +#if QT_CONFIG(textmarkdownreader) && QT_CONFIG(textmarkdownwriter) + Q_PROPERTY(QString markdown READ toMarkdown WRITE setMarkdown NOTIFY textChanged) +#endif #ifndef QT_NO_TEXTHTMLPARSER Q_PROPERTY(QString html READ toHtml WRITE setHtml NOTIFY textChanged USER true) #endif @@ -174,6 +177,9 @@ public: #ifndef QT_NO_TEXTHTMLPARSER QString toHtml() const; #endif +#if QT_CONFIG(textmarkdownwriter) + QString toMarkdown(QTextDocument::MarkdownFeatures features = QTextDocument::MarkdownDialectGitHub) const; +#endif void ensureCursorVisible(); @@ -239,7 +245,7 @@ public Q_SLOTS: void setHtml(const QString &text); #endif #if QT_CONFIG(textmarkdownreader) - void setMarkdown(const QString &text); + void setMarkdown(const QString &markdown); #endif void setText(const QString &text); diff --git a/src/widgets/widgets/qwidgettextcontrol.cpp b/src/widgets/widgets/qwidgettextcontrol.cpp index 5744d43cbf..209156b901 100644 --- a/src/widgets/widgets/qwidgettextcontrol.cpp +++ b/src/widgets/widgets/qwidgettextcontrol.cpp @@ -3130,6 +3130,13 @@ QString QWidgetTextControl::toHtml() const } #endif +#ifndef QT_NO_TEXTHTMLPARSER +QString QWidgetTextControl::toMarkdown(QTextDocument::MarkdownFeatures features) const +{ + return document()->toMarkdown(features); +} +#endif + void QWidgetTextControlPrivate::append(const QString &text, Qt::TextFormat format) { QTextCursor tmp(doc); diff --git a/src/widgets/widgets/qwidgettextcontrol_p.h b/src/widgets/widgets/qwidgettextcontrol_p.h index 4c9e47dfc9..e521e7b356 100644 --- a/src/widgets/widgets/qwidgettextcontrol_p.h +++ b/src/widgets/widgets/qwidgettextcontrol_p.h @@ -128,6 +128,9 @@ public: #ifndef QT_NO_TEXTHTMLPARSER QString toHtml() const; #endif +#if QT_CONFIG(textmarkdownwriter) + QString toMarkdown(QTextDocument::MarkdownFeatures features = QTextDocument::MarkdownDialectGitHub) const; +#endif virtual void ensureCursorVisible(); -- cgit v1.2.3 From d4435a37cae43abfbdb247b7d4a3a950aced2751 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Tue, 30 Apr 2019 12:39:22 +0200 Subject: Add qobject_cast operators for std::shared_ptr Mimicking what we currently have for QSharedPointer, but also adding * snake_case version (matching the ones in std) * rvalue-overloaded versions (matching the C++2a overloads). [ChangeLog][QtCore][QSharedPointer] Overloads of qSharedPointerObjectCast have been added to work on std::shared_ptr. Change-Id: I26ddffd82b000bf876e7c141fdce86a7b8c1d75a Reviewed-by: Thiago Macieira --- src/corelib/tools/qsharedpointer.cpp | 51 +++++++++++++++++++++++++++++++++ src/corelib/tools/qsharedpointer_impl.h | 42 +++++++++++++++++++++++++++ 2 files changed, 93 insertions(+) (limited to 'src') diff --git a/src/corelib/tools/qsharedpointer.cpp b/src/corelib/tools/qsharedpointer.cpp index 62b76c5bb7..0aedf4c6d6 100644 --- a/src/corelib/tools/qsharedpointer.cpp +++ b/src/corelib/tools/qsharedpointer.cpp @@ -1299,6 +1299,57 @@ \sa QSharedPointer::objectCast(), qSharedPointerCast(), qSharedPointerConstCast() */ +/*! + \fn template std::shared_ptr qSharedPointerObjectCast(const std::shared_ptr &src) + \relates QSharedPointer + \since 5.14 + + Returns a shared pointer to the pointer held by \a src, using a + \l qobject_cast() to type \tt X to obtain an internal pointer of the + appropriate type. If the \tt qobject_cast fails, the object + returned will be null. + + Note that \tt X must have the same cv-qualifiers (\tt const and + \tt volatile) that \tt T has, or the code will fail to + compile. Use const_pointer_cast to cast away the constness. +*/ + +/*! + \fn template std::shared_ptr qobject_pointer_cast(const std::shared_ptr &src) + \relates QSharedPointer + \since 5.14 + + Same as qSharedPointerObjectCast(). This function is provided for STL + compatibility. +*/ + +/*! + \fn template std::shared_ptr qSharedPointerObjectCast(std::shared_ptr &&src) + \relates QSharedPointer + \since 5.14 + + Returns a shared pointer to the pointer held by \a src, using a + \l qobject_cast() to type \tt X to obtain an internal pointer of the + appropriate type. + + If the \tt qobject_cast succeeds, the function will return a valid shared + pointer, and \a src is reset to null. If the \tt qobject_cast fails, the + object returned will be null, and \a src will not be modified. + + Note that \tt X must have the same cv-qualifiers (\tt const and + \tt volatile) that \tt T has, or the code will fail to + compile. Use const_pointer_cast to cast away the constness. +*/ + +/*! + \fn template std::shared_ptr qobject_pointer_cast(std::shared_ptr &&src) + \relates QSharedPointer + \since 5.14 + + Same as qSharedPointerObjectCast(). This function is provided for STL + compatibility. +*/ + /*! \fn template template QSharedPointer qSharedPointerObjectCast(const QWeakPointer &src) \relates QSharedPointer diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h index 81d8dcd839..0851121ff2 100644 --- a/src/corelib/tools/qsharedpointer_impl.h +++ b/src/corelib/tools/qsharedpointer_impl.h @@ -67,6 +67,8 @@ QT_END_NAMESPACE #endif #include +#include + QT_BEGIN_NAMESPACE @@ -996,6 +998,46 @@ qSharedPointerFromVariant(const QVariant &variant) return qSharedPointerObjectCast(QtSharedPointer::sharedPointerFromVariant_internal(variant)); } +// std::shared_ptr helpers + +template +std::shared_ptr qobject_pointer_cast(const std::shared_ptr &src) +{ + using element_type = typename std::shared_ptr::element_type; + return std::shared_ptr(src, qobject_cast(src.get())); +} + +template +std::shared_ptr qobject_pointer_cast(std::shared_ptr &&src) +{ + using element_type = typename std::shared_ptr::element_type; + auto castResult = qobject_cast(src.get()); + if (castResult) { + auto result = std::shared_ptr(std::move(src), castResult); +#if __cplusplus <= 201703L + // C++2a's move aliasing constructor will leave src empty. + // Before C++2a we don't really know if the compiler has support for it. + // The move aliasing constructor is the resolution for LWG2996, + // which does not impose a feature-testing macro. So: clear src. + src.reset(); +#endif + return result; + } + return std::shared_ptr(); +} + +template +std::shared_ptr qSharedPointerObjectCast(const std::shared_ptr &src) +{ + return qobject_pointer_cast(src); +} + +template +std::shared_ptr qSharedPointerObjectCast(std::shared_ptr &&src) +{ + return qobject_pointer_cast(std::move(src)); +} + #endif template Q_DECLARE_TYPEINFO_BODY(QWeakPointer, Q_MOVABLE_TYPE); -- cgit v1.2.3 From 2ded0043ca5115ddec41c15b2b98481f45bf0eba Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Tue, 30 Apr 2019 11:16:25 +0200 Subject: Moc: compile generate_keywords with corelib only It does not depend on QtGui. Change-Id: If7b01d1a6d2ce3945562f4480177ce883abfdbf4 Reviewed-by: Thiago Macieira Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/tools/moc/util/generate_keywords.pro | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/tools/moc/util/generate_keywords.pro b/src/tools/moc/util/generate_keywords.pro index 2bbc3ced61..e29738c18a 100644 --- a/src/tools/moc/util/generate_keywords.pro +++ b/src/tools/moc/util/generate_keywords.pro @@ -1,4 +1,5 @@ CONFIG -= moc CONFIG += cmdline +QT = core SOURCES += generate_keywords.cpp -- cgit v1.2.3 From b32b61f17eb6f816d854d6177e70df9c9e8fb895 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Tue, 30 Apr 2019 17:16:17 +0200 Subject: Remove handling of missing Q_COMPILER_RVALUE_REFS Remove remaining handling of missing support for rvalue refs. Change-Id: I78bab8bccfeeb9c76f464f345874364a37e4840a Reviewed-by: Edward Welbourne Reviewed-by: Thiago Macieira --- src/corelib/global/qglobal.h | 5 +---- src/corelib/mimetypes/qmimetype_p.h | 19 ------------------- src/corelib/tools/qdatetime.h | 2 -- src/corelib/tools/qeasingcurve.h | 2 -- src/corelib/tools/qhash.h | 4 ---- src/corelib/tools/qlinkedlist.h | 2 -- src/corelib/tools/qlist.h | 2 -- src/corelib/tools/qlocale.h | 2 -- src/corelib/tools/qmap.h | 4 ---- src/corelib/tools/qpair.h | 2 -- src/corelib/tools/qregexp.h | 2 -- src/corelib/tools/qregularexpression.h | 8 -------- src/corelib/tools/qshareddata.h | 4 ---- src/corelib/tools/qsharedpointer_impl.h | 5 ----- src/corelib/tools/qstring.h | 4 ---- src/corelib/tools/qstringlist.h | 4 ---- src/corelib/tools/qtimezone.h | 2 -- src/corelib/tools/qvector.h | 8 -------- src/corelib/tools/qversionnumber.h | 4 ---- src/dbus/qdbusargument.h | 2 -- src/dbus/qdbusconnection.h | 2 -- src/dbus/qdbuserror.h | 2 -- src/dbus/qdbusextratypes.h | 6 ------ src/dbus/qdbusmessage.h | 2 -- src/dbus/qdbuspendingcall.h | 2 -- src/dbus/qdbusunixfiledescriptor.h | 6 +----- src/gui/image/qicon.h | 4 ---- src/gui/image/qimage.h | 4 ---- src/gui/image/qpicture.h | 2 -- src/gui/image/qpixmap.h | 4 ---- src/gui/image/qpixmapcache.h | 2 -- src/gui/kernel/qcursor.h | 2 -- src/gui/kernel/qevent.h | 2 -- src/gui/kernel/qkeysequence.h | 2 -- src/gui/kernel/qpalette.h | 2 -- src/gui/opengl/qopengldebug.h | 2 -- src/gui/opengl/qopenglpixeltransferoptions.h | 2 -- src/gui/painting/qbrush.h | 2 -- src/gui/painting/qcolor.h | 2 -- src/gui/painting/qpagelayout.h | 2 -- src/gui/painting/qpagesize.h | 2 -- src/gui/painting/qpainterpath.h | 2 -- src/gui/painting/qpen.h | 2 -- src/gui/painting/qpolygon.h | 8 -------- src/gui/painting/qregion.h | 2 -- src/gui/text/qfont.h | 2 -- src/gui/text/qfontmetrics.h | 4 ---- src/gui/text/qglyphrun.h | 2 -- src/gui/text/qrawfont.h | 2 -- src/gui/text/qstatictext.h | 2 -- src/gui/text/qtextcursor.h | 2 -- src/network/access/qabstractnetworkcache.h | 2 -- src/network/access/qhttpmultipart.h | 2 -- src/network/access/qnetworkcookie.h | 2 -- src/network/access/qnetworkrequest.h | 2 -- src/network/bearer/qnetworkconfiguration.h | 2 -- src/network/kernel/qdnslookup.h | 10 ---------- src/network/kernel/qhostaddress.h | 3 --- src/network/kernel/qnetworkinterface.h | 4 ---- src/network/kernel/qnetworkproxy.h | 4 ---- src/network/ssl/qsslcertificate.h | 2 -- src/network/ssl/qsslcertificateextension.h | 2 -- src/network/ssl/qsslcipher.h | 2 -- src/network/ssl/qsslconfiguration.h | 2 -- src/network/ssl/qsslerror.h | 2 -- src/network/ssl/qsslpresharedkeyauthenticator.h | 2 -- src/printsupport/kernel/qprintdevice_p.h | 2 -- 67 files changed, 2 insertions(+), 214 deletions(-) (limited to 'src') diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 3c17bbb2d4..ceae0583ee 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -509,11 +509,8 @@ namespace QtPrivate { template struct AlignOf : AlignOf_Default { }; template struct AlignOf : AlignOf {}; - template struct AlignOf : AlignOf {}; - -#ifdef Q_COMPILER_RVALUE_REFS template struct AlignOf : AlignOf {}; -#endif + template struct AlignOf : AlignOf {}; #if defined(Q_PROCESSOR_X86_32) && !defined(Q_OS_WIN) template struct AlignOf_WorkaroundForI386Abi { enum { Value = sizeof(T) }; }; diff --git a/src/corelib/mimetypes/qmimetype_p.h b/src/corelib/mimetypes/qmimetype_p.h index 2918309ad7..0d6b4b4b12 100644 --- a/src/corelib/mimetypes/qmimetype_p.h +++ b/src/corelib/mimetypes/qmimetype_p.h @@ -84,25 +84,6 @@ public: QT_END_NAMESPACE -#define QMIMETYPE_BUILDER \ - QT_BEGIN_NAMESPACE \ - static QMimeType buildQMimeType ( \ - const QString &name, \ - const QString &genericIconName, \ - const QString &iconName, \ - const QStringList &globPatterns \ - ) \ - { \ - QMimeTypePrivate qMimeTypeData; \ - qMimeTypeData.name = name; \ - qMimeTypeData.loaded = true; \ - qMimeTypeData.genericIconName = genericIconName; \ - qMimeTypeData.iconName = iconName; \ - qMimeTypeData.globPatterns = globPatterns; \ - return QMimeType(qMimeTypeData); \ - } \ - QT_END_NAMESPACE - #define QMIMETYPE_BUILDER_FROM_RVALUE_REFS \ QT_BEGIN_NAMESPACE \ static QMimeType buildQMimeType ( \ diff --git a/src/corelib/tools/qdatetime.h b/src/corelib/tools/qdatetime.h index 8873651f17..79fd25d762 100644 --- a/src/corelib/tools/qdatetime.h +++ b/src/corelib/tools/qdatetime.h @@ -278,9 +278,7 @@ public: QDateTime(QDateTime &&other) noexcept; ~QDateTime(); -#ifdef Q_COMPILER_RVALUE_REFS QDateTime &operator=(QDateTime &&other) noexcept { swap(other); return *this; } -#endif QDateTime &operator=(const QDateTime &other) noexcept; void swap(QDateTime &other) noexcept { qSwap(d.d, other.d.d); } diff --git a/src/corelib/tools/qeasingcurve.h b/src/corelib/tools/qeasingcurve.h index 1791f19199..725ddd5dcc 100644 --- a/src/corelib/tools/qeasingcurve.h +++ b/src/corelib/tools/qeasingcurve.h @@ -80,11 +80,9 @@ public: QEasingCurve &operator=(const QEasingCurve &other) { if ( this != &other ) { QEasingCurve copy(other); swap(copy); } return *this; } -#ifdef Q_COMPILER_RVALUE_REFS QEasingCurve(QEasingCurve &&other) noexcept : d_ptr(other.d_ptr) { other.d_ptr = nullptr; } QEasingCurve &operator=(QEasingCurve &&other) noexcept { qSwap(d_ptr, other.d_ptr); return *this; } -#endif void swap(QEasingCurve &other) noexcept { qSwap(d_ptr, other.d_ptr); } diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h index a757e85386..0078bbbee9 100644 --- a/src/corelib/tools/qhash.h +++ b/src/corelib/tools/qhash.h @@ -255,11 +255,9 @@ public: ~QHash() { if (!d->ref.deref()) freeData(d); } QHash &operator=(const QHash &other); -#ifdef Q_COMPILER_RVALUE_REFS QHash(QHash &&other) noexcept : d(other.d) { other.d = const_cast(&QHashData::shared_null); } QHash &operator=(QHash &&other) noexcept { QHash moved(std::move(other)); swap(moved); return *this; } -#endif #ifdef Q_QDOC template QHash(InputIterator f, InputIterator l); @@ -1076,9 +1074,7 @@ public: // compiler-generated destructor is fine! QMultiHash(const QHash &other) : QHash(other) {} -#ifdef Q_COMPILER_RVALUE_REFS QMultiHash(QHash &&other) noexcept : QHash(std::move(other)) {} -#endif void swap(QMultiHash &other) noexcept { QHash::swap(other); } // prevent QMultiHash<->QHash swaps inline typename QHash::iterator replace(const Key &key, const T &value) diff --git a/src/corelib/tools/qlinkedlist.h b/src/corelib/tools/qlinkedlist.h index 83f70deceb..0c8a99e258 100644 --- a/src/corelib/tools/qlinkedlist.h +++ b/src/corelib/tools/qlinkedlist.h @@ -95,12 +95,10 @@ public: } ~QLinkedList(); QLinkedList &operator=(const QLinkedList &); -#ifdef Q_COMPILER_RVALUE_REFS QLinkedList(QLinkedList &&other) noexcept : d(other.d) { other.d = const_cast(&QLinkedListData::shared_null); } QLinkedList &operator=(QLinkedList &&other) noexcept { QLinkedList moved(std::move(other)); swap(moved); return *this; } -#endif inline void swap(QLinkedList &other) noexcept { qSwap(d, other.d); } bool operator==(const QLinkedList &l) const; inline bool operator!=(const QLinkedList &l) const { return !(*this == l); } diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index 48a71b0ecf..59578b1e61 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -161,12 +161,10 @@ public: QList(const QList &l); ~QList(); QList &operator=(const QList &l); -#ifdef Q_COMPILER_RVALUE_REFS inline QList(QList &&other) noexcept : d(other.d) { other.d = const_cast(&QListData::shared_null); } inline QList &operator=(QList &&other) noexcept { QList moved(std::move(other)); swap(moved); return *this; } -#endif inline void swap(QList &other) noexcept { qSwap(d, other.d); } #ifdef Q_COMPILER_INITIALIZER_LISTS inline QList(std::initializer_list args) diff --git a/src/corelib/tools/qlocale.h b/src/corelib/tools/qlocale.h index 3dc5ee0a01..977c4c6c9c 100644 --- a/src/corelib/tools/qlocale.h +++ b/src/corelib/tools/qlocale.h @@ -939,9 +939,7 @@ public: QLocale(Language language, Country country = AnyCountry); QLocale(Language language, Script script, Country country); QLocale(const QLocale &other); -#ifdef Q_COMPILER_RVALUE_REFS QLocale &operator=(QLocale &&other) noexcept { swap(other); return *this; } -#endif QLocale &operator=(const QLocale &other); ~QLocale(); diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h index 103124f4ad..3b8aad9a33 100644 --- a/src/corelib/tools/qmap.h +++ b/src/corelib/tools/qmap.h @@ -339,7 +339,6 @@ public: inline ~QMap() { if (!d->ref.deref()) d->destroy(); } QMap &operator=(const QMap &other); -#ifdef Q_COMPILER_RVALUE_REFS inline QMap(QMap &&other) noexcept : d(other.d) { @@ -349,7 +348,6 @@ public: inline QMap &operator=(QMap &&other) noexcept { QMap moved(std::move(other)); swap(moved); return *this; } -#endif inline void swap(QMap &other) noexcept { qSwap(d, other.d); } explicit QMap(const typename std::map &other); std::map toStdMap() const; @@ -1196,9 +1194,7 @@ public: } #endif QMultiMap(const QMap &other) : QMap(other) {} -#ifdef Q_COMPILER_RVALUE_REFS QMultiMap(QMap &&other) noexcept : QMap(std::move(other)) {} -#endif void swap(QMultiMap &other) noexcept { QMap::swap(other); } inline typename QMap::iterator replace(const Key &key, const T &value) diff --git a/src/corelib/tools/qpair.h b/src/corelib/tools/qpair.h index 6d1e67efb7..9ebf88bc8f 100644 --- a/src/corelib/tools/qpair.h +++ b/src/corelib/tools/qpair.h @@ -71,7 +71,6 @@ struct QPair noexcept((std::is_nothrow_assignable::value && std::is_nothrow_assignable::value)) { first = p.first; second = p.second; return *this; } -#ifdef Q_COMPILER_RVALUE_REFS template Q_DECL_CONSTEXPR QPair(QPair &&p) noexcept((std::is_nothrow_constructible::value && @@ -83,7 +82,6 @@ struct QPair noexcept((std::is_nothrow_assignable::value && std::is_nothrow_assignable::value)) { first = std::move(p.first); second = std::move(p.second); return *this; } -#endif Q_DECL_RELAXED_CONSTEXPR void swap(QPair &other) noexcept(noexcept(qSwap(other.first, other.first)) && noexcept(qSwap(other.second, other.second))) diff --git a/src/corelib/tools/qregexp.h b/src/corelib/tools/qregexp.h index c043a06496..8f6de24c74 100644 --- a/src/corelib/tools/qregexp.h +++ b/src/corelib/tools/qregexp.h @@ -73,9 +73,7 @@ public: QRegExp(const QRegExp &rx); ~QRegExp(); QRegExp &operator=(const QRegExp &rx); -#ifdef Q_COMPILER_RVALUE_REFS QRegExp &operator=(QRegExp &&other) noexcept { swap(other); return *this; } -#endif void swap(QRegExp &other) noexcept { qSwap(priv, other.priv); } bool operator==(const QRegExp &rx) const; diff --git a/src/corelib/tools/qregularexpression.h b/src/corelib/tools/qregularexpression.h index f16b7e91be..f799a38ae4 100644 --- a/src/corelib/tools/qregularexpression.h +++ b/src/corelib/tools/qregularexpression.h @@ -86,11 +86,8 @@ public: QRegularExpression(const QRegularExpression &re); ~QRegularExpression(); QRegularExpression &operator=(const QRegularExpression &re); - -#ifdef Q_COMPILER_RVALUE_REFS QRegularExpression &operator=(QRegularExpression &&re) noexcept { d.swap(re.d); return *this; } -#endif void swap(QRegularExpression &other) noexcept { d.swap(other.d); } @@ -186,11 +183,8 @@ public: ~QRegularExpressionMatch(); QRegularExpressionMatch(const QRegularExpressionMatch &match); QRegularExpressionMatch &operator=(const QRegularExpressionMatch &match); - -#ifdef Q_COMPILER_RVALUE_REFS QRegularExpressionMatch &operator=(QRegularExpressionMatch &&match) noexcept { d.swap(match.d); return *this; } -#endif void swap(QRegularExpressionMatch &other) noexcept { d.swap(other.d); } QRegularExpression regularExpression() const; @@ -257,10 +251,8 @@ public: ~QRegularExpressionMatchIterator(); QRegularExpressionMatchIterator(const QRegularExpressionMatchIterator &iterator); QRegularExpressionMatchIterator &operator=(const QRegularExpressionMatchIterator &iterator); -#ifdef Q_COMPILER_RVALUE_REFS QRegularExpressionMatchIterator &operator=(QRegularExpressionMatchIterator &&iterator) noexcept { d.swap(iterator.d); return *this; } -#endif void swap(QRegularExpressionMatchIterator &other) noexcept { d.swap(other.d); } bool isValid() const; diff --git a/src/corelib/tools/qshareddata.h b/src/corelib/tools/qshareddata.h index cbaa1aa3c4..04051472d6 100644 --- a/src/corelib/tools/qshareddata.h +++ b/src/corelib/tools/qshareddata.h @@ -112,7 +112,6 @@ public: } return *this; } -#ifdef Q_COMPILER_RVALUE_REFS QSharedDataPointer(QSharedDataPointer &&o) noexcept : d(o.d) { o.d = nullptr; } inline QSharedDataPointer &operator=(QSharedDataPointer &&other) noexcept { @@ -120,7 +119,6 @@ public: swap(moved); return *this; } -#endif inline bool operator!() const { return !d; } @@ -218,7 +216,6 @@ public: } return *this; } -#ifdef Q_COMPILER_RVALUE_REFS inline QExplicitlySharedDataPointer(QExplicitlySharedDataPointer &&o) noexcept : d(o.d) { o.d = nullptr; } inline QExplicitlySharedDataPointer &operator=(QExplicitlySharedDataPointer &&other) noexcept { @@ -226,7 +223,6 @@ public: swap(moved); return *this; } -#endif inline bool operator!() const { return !d; } diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h index 0851121ff2..9fb452da6b 100644 --- a/src/corelib/tools/qsharedpointer_impl.h +++ b/src/corelib/tools/qsharedpointer_impl.h @@ -337,7 +337,6 @@ public: swap(copy); return *this; } -#ifdef Q_COMPILER_RVALUE_REFS QSharedPointer(QSharedPointer &&other) noexcept : value(other.value), d(other.d) { @@ -367,8 +366,6 @@ public: return *this; } -#endif - template QSharedPointer(const QSharedPointer &other) noexcept : value(other.value), d(other.d) { if (d) ref(); } @@ -590,7 +587,6 @@ public: QWeakPointer(const QWeakPointer &other) noexcept : d(other.d), value(other.value) { if (d) d->weakref.ref(); } -#ifdef Q_COMPILER_RVALUE_REFS QWeakPointer(QWeakPointer &&other) noexcept : d(other.d), value(other.value) { @@ -599,7 +595,6 @@ public: } QWeakPointer &operator=(QWeakPointer &&other) noexcept { QWeakPointer moved(std::move(other)); swap(moved); return *this; } -#endif QWeakPointer &operator=(const QWeakPointer &other) noexcept { QWeakPointer copy(other); diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index a526a6537a..e4798eb51b 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -230,11 +230,9 @@ public: QString &operator=(QChar c); QString &operator=(const QString &) noexcept; QString &operator=(QLatin1String latin1); -#ifdef Q_COMPILER_RVALUE_REFS inline QString(QString && other) noexcept : d(other.d) { other.d = Data::sharedNull(); } inline QString &operator=(QString &&other) noexcept { qSwap(d, other.d); return *this; } -#endif inline void swap(QString &other) noexcept { qSwap(d, other.d); } inline int size() const { return d->size; } inline int count() const { return d->size; } @@ -1437,10 +1435,8 @@ public: QStringRef(const QStringRef &other) noexcept :m_string(other.m_string), m_position(other.m_position), m_size(other.m_size) {} -#ifdef Q_COMPILER_RVALUE_REFS QStringRef(QStringRef &&other) noexcept : m_string(other.m_string), m_position(other.m_position), m_size(other.m_size) {} QStringRef &operator=(QStringRef &&other) noexcept { return *this = other; } -#endif QStringRef &operator=(const QStringRef &other) noexcept { m_string = other.m_string; m_position = other.m_position; diff --git a/src/corelib/tools/qstringlist.h b/src/corelib/tools/qstringlist.h index 5ad01a0658..73ac737643 100644 --- a/src/corelib/tools/qstringlist.h +++ b/src/corelib/tools/qstringlist.h @@ -104,9 +104,7 @@ public: inline QStringList() noexcept { } inline explicit QStringList(const QString &i) { append(i); } inline QStringList(const QList &l) : QList(l) { } -#ifdef Q_COMPILER_RVALUE_REFS inline QStringList(QList &&l) noexcept : QList(std::move(l)) { } -#endif #ifdef Q_COMPILER_INITIALIZER_LISTS inline QStringList(std::initializer_list args) : QList(args) { } #endif @@ -116,10 +114,8 @@ public: QStringList &operator=(const QList &other) { QList::operator=(other); return *this; } -#ifdef Q_COMPILER_RVALUE_REFS QStringList &operator=(QList &&other) noexcept { QList::operator=(std::move(other)); return *this; } -#endif #if QT_STRINGVIEW_LEVEL < 2 inline bool contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; diff --git a/src/corelib/tools/qtimezone.h b/src/corelib/tools/qtimezone.h index ca98986ec1..62ecee49bb 100644 --- a/src/corelib/tools/qtimezone.h +++ b/src/corelib/tools/qtimezone.h @@ -99,9 +99,7 @@ public: ~QTimeZone(); QTimeZone &operator=(const QTimeZone &other); - #ifdef Q_COMPILER_RVALUE_REFS QTimeZone &operator=(QTimeZone &&other) noexcept { swap(other); return *this; } -#endif void swap(QTimeZone &other) noexcept { d.swap(other.d); } diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h index 6cbf794c6c..7e14a0c9b2 100644 --- a/src/corelib/tools/qvector.h +++ b/src/corelib/tools/qvector.h @@ -72,11 +72,9 @@ public: inline QVector(const QVector &v); inline ~QVector() { if (!d->ref.deref()) freeData(d); } QVector &operator=(const QVector &v); -#if defined(Q_COMPILER_RVALUE_REFS) || defined(Q_CLANG_QDOC) QVector(QVector &&other) noexcept : d(other.d) { other.d = Data::sharedNull(); } QVector &operator=(QVector &&other) noexcept { QVector moved(std::move(other)); swap(moved); return *this; } -#endif void swap(QVector &other) noexcept { qSwap(d, other.d); } #ifdef Q_COMPILER_INITIALIZER_LISTS inline QVector(std::initializer_list args); @@ -143,9 +141,7 @@ public: T &operator[](int i); const T &operator[](int i) const; void append(const T &t); -#if defined(Q_COMPILER_RVALUE_REFS) || defined(Q_CLANG_QDOC) void append(T &&t); -#endif inline void append(const QVector &l) { *this += l; } void prepend(T &&t); void prepend(const T &t); @@ -268,10 +264,8 @@ public: typedef const_iterator ConstIterator; typedef int size_type; inline void push_back(const T &t) { append(t); } -#if defined(Q_COMPILER_RVALUE_REFS) || defined(Q_CLANG_QDOC) void push_back(T &&t) { append(std::move(t)); } void push_front(T &&t) { prepend(std::move(t)); } -#endif inline void push_front(const T &t) { prepend(t); } void pop_back() { removeLast(); } void pop_front() { removeFirst(); } @@ -799,7 +793,6 @@ void QVector::append(const T &t) ++d->size; } -#ifdef Q_COMPILER_RVALUE_REFS template void QVector::append(T &&t) { @@ -813,7 +806,6 @@ void QVector::append(T &&t) ++d->size; } -#endif template void QVector::removeLast() diff --git a/src/corelib/tools/qversionnumber.h b/src/corelib/tools/qversionnumber.h index d51947c091..1488014d38 100644 --- a/src/corelib/tools/qversionnumber.h +++ b/src/corelib/tools/qversionnumber.h @@ -119,7 +119,6 @@ class QVersionNumber return *this; } -#ifdef Q_COMPILER_RVALUE_REFS SegmentStorage(SegmentStorage &&other) noexcept : dummy(other.dummy) { @@ -139,7 +138,6 @@ class QVersionNumber else pointer_segments = new QVector(std::move(seg)); } -#endif #ifdef Q_COMPILER_INITIALIZER_LISTS SegmentStorage(std::initializer_list args) { @@ -227,11 +225,9 @@ public: // compiler-generated copy/move ctor/assignment operators and the destructor are ok -#ifdef Q_COMPILER_RVALUE_REFS explicit QVersionNumber(QVector &&seg) : m_segments(std::move(seg)) {} -#endif #ifdef Q_COMPILER_INITIALIZER_LISTS inline QVersionNumber(std::initializer_list args) diff --git a/src/dbus/qdbusargument.h b/src/dbus/qdbusargument.h index 7f4bd269a9..b7cd4c8989 100644 --- a/src/dbus/qdbusargument.h +++ b/src/dbus/qdbusargument.h @@ -76,10 +76,8 @@ public: QDBusArgument(); QDBusArgument(const QDBusArgument &other); -#ifdef Q_COMPILER_RVALUE_REFS QDBusArgument(QDBusArgument &&other) noexcept : d(other.d) { other.d = nullptr; } QDBusArgument &operator=(QDBusArgument &&other) noexcept { swap(other); return *this; } -#endif QDBusArgument &operator=(const QDBusArgument &other); ~QDBusArgument(); diff --git a/src/dbus/qdbusconnection.h b/src/dbus/qdbusconnection.h index a880a7a939..368f811602 100644 --- a/src/dbus/qdbusconnection.h +++ b/src/dbus/qdbusconnection.h @@ -131,10 +131,8 @@ public: explicit QDBusConnection(const QString &name); QDBusConnection(const QDBusConnection &other); -#ifdef Q_COMPILER_RVALUE_REFS QDBusConnection(QDBusConnection &&other) noexcept : d(other.d) { other.d = nullptr; } QDBusConnection &operator=(QDBusConnection &&other) noexcept { swap(other); return *this; } -#endif QDBusConnection &operator=(const QDBusConnection &other); ~QDBusConnection(); diff --git a/src/dbus/qdbuserror.h b/src/dbus/qdbuserror.h index 5a68a417c4..bcf68dbcdc 100644 --- a/src/dbus/qdbuserror.h +++ b/src/dbus/qdbuserror.h @@ -98,12 +98,10 @@ public: #endif QDBusError(ErrorType error, const QString &message); QDBusError(const QDBusError &other); -#ifdef Q_COMPILER_RVALUE_REFS QDBusError(QDBusError &&other) noexcept : code(other.code), msg(std::move(other.msg)), nm(std::move(other.nm)) {} QDBusError &operator=(QDBusError &&other) noexcept { swap(other); return *this; } -#endif QDBusError &operator=(const QDBusError &other); #ifndef QT_BOOTSTRAPPED QDBusError &operator=(const QDBusMessage &msg); diff --git a/src/dbus/qdbusextratypes.h b/src/dbus/qdbusextratypes.h index e2430ad6f2..fdac917947 100644 --- a/src/dbus/qdbusextratypes.h +++ b/src/dbus/qdbusextratypes.h @@ -66,9 +66,7 @@ public: inline explicit QDBusObjectPath(const char *path); inline explicit QDBusObjectPath(QLatin1String path); inline explicit QDBusObjectPath(const QString &path); -#ifdef Q_COMPILER_RVALUE_REFS explicit QDBusObjectPath(QString &&p) : m_path(std::move(p)) { doCheck(); } -#endif void swap(QDBusObjectPath &other) noexcept { qSwap(m_path, other.m_path); } @@ -121,9 +119,7 @@ public: inline explicit QDBusSignature(const char *signature); inline explicit QDBusSignature(QLatin1String signature); inline explicit QDBusSignature(const QString &signature); -#ifdef Q_COMPILER_RVALUE_REFS explicit QDBusSignature(QString &&sig) : m_signature(std::move(sig)) { doCheck(); } -#endif void swap(QDBusSignature &other) noexcept { qSwap(m_signature, other.m_signature); } @@ -173,9 +169,7 @@ public: // compiler-generated destructor is ok! inline explicit QDBusVariant(const QVariant &variant); -#ifdef Q_COMPILER_RVALUE_REFS explicit QDBusVariant(QVariant &&v) noexcept : m_variant(std::move(v)) {} -#endif void swap(QDBusVariant &other) noexcept { qSwap(m_variant, other.m_variant); } diff --git a/src/dbus/qdbusmessage.h b/src/dbus/qdbusmessage.h index 3e73db70de..41845317c4 100644 --- a/src/dbus/qdbusmessage.h +++ b/src/dbus/qdbusmessage.h @@ -68,9 +68,7 @@ public: QDBusMessage(); QDBusMessage(const QDBusMessage &other); -#ifdef Q_COMPILER_RVALUE_REFS QDBusMessage &operator=(QDBusMessage &&other) noexcept { swap(other); return *this; } -#endif QDBusMessage &operator=(const QDBusMessage &other); ~QDBusMessage(); diff --git a/src/dbus/qdbuspendingcall.h b/src/dbus/qdbuspendingcall.h index c521b7d163..dd99346301 100644 --- a/src/dbus/qdbuspendingcall.h +++ b/src/dbus/qdbuspendingcall.h @@ -60,9 +60,7 @@ class Q_DBUS_EXPORT QDBusPendingCall public: QDBusPendingCall(const QDBusPendingCall &other); ~QDBusPendingCall(); -#ifdef Q_COMPILER_RVALUE_REFS QDBusPendingCall &operator=(QDBusPendingCall &&other) noexcept { swap(other); return *this; } -#endif QDBusPendingCall &operator=(const QDBusPendingCall &other); void swap(QDBusPendingCall &other) noexcept { qSwap(d, other.d); } diff --git a/src/dbus/qdbusunixfiledescriptor.h b/src/dbus/qdbusunixfiledescriptor.h index 6b264a6b86..fcd73b2ec5 100644 --- a/src/dbus/qdbusunixfiledescriptor.h +++ b/src/dbus/qdbusunixfiledescriptor.h @@ -46,9 +46,7 @@ #ifndef QT_NO_DBUS -#ifdef Q_COMPILER_RVALUE_REFS -# include -#endif +#include QT_BEGIN_NAMESPACE @@ -61,9 +59,7 @@ public: QDBusUnixFileDescriptor(); explicit QDBusUnixFileDescriptor(int fileDescriptor); QDBusUnixFileDescriptor(const QDBusUnixFileDescriptor &other); -#if defined(Q_COMPILER_RVALUE_REFS) QDBusUnixFileDescriptor &operator=(QDBusUnixFileDescriptor &&other) noexcept { swap(other); return *this; } -#endif QDBusUnixFileDescriptor &operator=(const QDBusUnixFileDescriptor &other); ~QDBusUnixFileDescriptor(); diff --git a/src/gui/image/qicon.h b/src/gui/image/qicon.h index 0f834fc2cb..735a3e134d 100644 --- a/src/gui/image/qicon.h +++ b/src/gui/image/qicon.h @@ -61,19 +61,15 @@ public: QIcon() noexcept; QIcon(const QPixmap &pixmap); QIcon(const QIcon &other); -#ifdef Q_COMPILER_RVALUE_REFS QIcon(QIcon &&other) noexcept : d(other.d) { other.d = nullptr; } -#endif explicit QIcon(const QString &fileName); // file or resource name explicit QIcon(QIconEngine *engine); ~QIcon(); QIcon &operator=(const QIcon &other); -#ifdef Q_COMPILER_RVALUE_REFS inline QIcon &operator=(QIcon &&other) noexcept { swap(other); return *this; } -#endif inline void swap(QIcon &other) noexcept { qSwap(d, other.d); } diff --git a/src/gui/image/qimage.h b/src/gui/image/qimage.h index 9d177142d9..7c68168be8 100644 --- a/src/gui/image/qimage.h +++ b/src/gui/image/qimage.h @@ -151,18 +151,14 @@ public: explicit QImage(const QString &fileName, const char *format = nullptr); QImage(const QImage &); -#ifdef Q_COMPILER_RVALUE_REFS inline QImage(QImage &&other) noexcept : QPaintDevice(), d(nullptr) { qSwap(d, other.d); } -#endif ~QImage(); QImage &operator=(const QImage &); -#ifdef Q_COMPILER_RVALUE_REFS inline QImage &operator=(QImage &&other) noexcept { qSwap(d, other.d); return *this; } -#endif inline void swap(QImage &other) noexcept { qSwap(d, other.d); } diff --git a/src/gui/image/qpicture.h b/src/gui/image/qpicture.h index cac2ef5dfc..189e57b9a3 100644 --- a/src/gui/image/qpicture.h +++ b/src/gui/image/qpicture.h @@ -78,10 +78,8 @@ public: void setBoundingRect(const QRect &r); QPicture& operator=(const QPicture &p); -#ifdef Q_COMPILER_RVALUE_REFS inline QPicture &operator=(QPicture &&other) noexcept { qSwap(d_ptr, other.d_ptr); return *this; } -#endif inline void swap(QPicture &other) noexcept { d_ptr.swap(other.d_ptr); } void detach(); diff --git a/src/gui/image/qpixmap.h b/src/gui/image/qpixmap.h index 2103fcc58c..8c1395857e 100644 --- a/src/gui/image/qpixmap.h +++ b/src/gui/image/qpixmap.h @@ -73,10 +73,8 @@ public: ~QPixmap(); QPixmap &operator=(const QPixmap &); -#ifdef Q_COMPILER_RVALUE_REFS inline QPixmap &operator=(QPixmap &&other) noexcept { qSwap(data, other.data); return *this; } -#endif inline void swap(QPixmap &other) noexcept { qSwap(data, other.data); } @@ -139,12 +137,10 @@ public: QImage toImage() const; static QPixmap fromImage(const QImage &image, Qt::ImageConversionFlags flags = Qt::AutoColor); static QPixmap fromImageReader(QImageReader *imageReader, Qt::ImageConversionFlags flags = Qt::AutoColor); -#ifdef Q_COMPILER_RVALUE_REFS static QPixmap fromImage(QImage &&image, Qt::ImageConversionFlags flags = Qt::AutoColor) { return fromImageInPlace(image, flags); } -#endif bool load(const QString& fileName, const char *format = nullptr, Qt::ImageConversionFlags flags = Qt::AutoColor); bool loadFromData(const uchar *buf, uint len, const char* format = nullptr, Qt::ImageConversionFlags flags = Qt::AutoColor); diff --git a/src/gui/image/qpixmapcache.h b/src/gui/image/qpixmapcache.h index c5bedb27ab..55af35a5d9 100644 --- a/src/gui/image/qpixmapcache.h +++ b/src/gui/image/qpixmapcache.h @@ -55,10 +55,8 @@ public: public: Key(); Key(const Key &other); -#ifdef Q_COMPILER_RVALUE_REFS Key(Key &&other) noexcept : d(other.d) { other.d = nullptr; } Key &operator =(Key &&other) noexcept { swap(other); return *this; } -#endif ~Key(); bool operator ==(const Key &key) const; inline bool operator !=(const Key &key) const diff --git a/src/gui/kernel/qcursor.h b/src/gui/kernel/qcursor.h index ced166dc29..7966e35840 100644 --- a/src/gui/kernel/qcursor.h +++ b/src/gui/kernel/qcursor.h @@ -86,11 +86,9 @@ public: QCursor(const QCursor &cursor); ~QCursor(); QCursor &operator=(const QCursor &cursor); -#ifdef Q_COMPILER_RVALUE_REFS QCursor(QCursor &&other) noexcept : d(other.d) { other.d = nullptr; } inline QCursor &operator=(QCursor &&other) noexcept { swap(other); return *this; } -#endif void swap(QCursor &other) noexcept { qSwap(d, other.d); } diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index aeefb53819..eb0a6208a9 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -855,13 +855,11 @@ public: explicit TouchPoint(int id = -1); TouchPoint(const TouchPoint &other); -#ifdef Q_COMPILER_RVALUE_REFS TouchPoint(TouchPoint &&other) noexcept : d(nullptr) { qSwap(d, other.d); } TouchPoint &operator=(TouchPoint &&other) noexcept { qSwap(d, other.d); return *this; } -#endif ~TouchPoint(); TouchPoint &operator=(const TouchPoint &other) diff --git a/src/gui/kernel/qkeysequence.h b/src/gui/kernel/qkeysequence.h index 5630bdda58..3dcbbe5941 100644 --- a/src/gui/kernel/qkeysequence.h +++ b/src/gui/kernel/qkeysequence.h @@ -186,9 +186,7 @@ public: operator QVariant() const; int operator[](uint i) const; QKeySequence &operator=(const QKeySequence &other); -#ifdef Q_COMPILER_RVALUE_REFS QKeySequence &operator=(QKeySequence &&other) noexcept { swap(other); return *this; } -#endif void swap(QKeySequence &other) noexcept { qSwap(d, other.d); } bool operator==(const QKeySequence &other) const; diff --git a/src/gui/kernel/qpalette.h b/src/gui/kernel/qpalette.h index a463245d4d..d3a840d9ad 100644 --- a/src/gui/kernel/qpalette.h +++ b/src/gui/kernel/qpalette.h @@ -67,7 +67,6 @@ public: QPalette(const QPalette &palette); ~QPalette(); QPalette &operator=(const QPalette &palette); -#ifdef Q_COMPILER_RVALUE_REFS QPalette(QPalette &&other) noexcept : d(other.d), data(other.data) { other.d = nullptr; } @@ -76,7 +75,6 @@ public: for_faster_swapping_dont_use = other.for_faster_swapping_dont_use; qSwap(d, other.d); return *this; } -#endif void swap(QPalette &other) noexcept { diff --git a/src/gui/opengl/qopengldebug.h b/src/gui/opengl/qopengldebug.h index 1ba3ef91ac..7363985d60 100644 --- a/src/gui/opengl/qopengldebug.h +++ b/src/gui/opengl/qopengldebug.h @@ -110,9 +110,7 @@ public: QOpenGLDebugMessage(const QOpenGLDebugMessage &debugMessage); QOpenGLDebugMessage &operator=(const QOpenGLDebugMessage &debugMessage); -#ifdef Q_COMPILER_RVALUE_REFS QOpenGLDebugMessage &operator=(QOpenGLDebugMessage &&other) noexcept { swap(other); return *this; } -#endif ~QOpenGLDebugMessage(); void swap(QOpenGLDebugMessage &other) noexcept { qSwap(d, other.d); } diff --git a/src/gui/opengl/qopenglpixeltransferoptions.h b/src/gui/opengl/qopenglpixeltransferoptions.h index be60e66e71..195543ae90 100644 --- a/src/gui/opengl/qopenglpixeltransferoptions.h +++ b/src/gui/opengl/qopenglpixeltransferoptions.h @@ -55,10 +55,8 @@ class Q_GUI_EXPORT QOpenGLPixelTransferOptions public: QOpenGLPixelTransferOptions(); QOpenGLPixelTransferOptions(const QOpenGLPixelTransferOptions &); -#ifdef Q_COMPILER_RVALUE_REFS QOpenGLPixelTransferOptions &operator=(QOpenGLPixelTransferOptions &&other) noexcept { swap(other); return *this; } -#endif QOpenGLPixelTransferOptions &operator=(const QOpenGLPixelTransferOptions &); ~QOpenGLPixelTransferOptions(); diff --git a/src/gui/painting/qbrush.h b/src/gui/painting/qbrush.h index 27d710eca6..ef8f7a18de 100644 --- a/src/gui/painting/qbrush.h +++ b/src/gui/painting/qbrush.h @@ -79,10 +79,8 @@ public: ~QBrush(); QBrush &operator=(const QBrush &brush); -#ifdef Q_COMPILER_RVALUE_REFS inline QBrush &operator=(QBrush &&other) noexcept { qSwap(d, other.d); return *this; } -#endif inline void swap(QBrush &other) noexcept { qSwap(d, other.d); } diff --git a/src/gui/painting/qcolor.h b/src/gui/painting/qcolor.h index 77b2d43c40..e3c267f97d 100644 --- a/src/gui/painting/qcolor.h +++ b/src/gui/painting/qcolor.h @@ -82,11 +82,9 @@ public: #if QT_VERSION < QT_VERSION_CHECK(6,0,0) inline QColor(const QColor &color) noexcept; // ### Qt 6: remove all of these, the trivial ones are fine. -# ifdef Q_COMPILER_RVALUE_REFS QColor(QColor &&other) noexcept : cspec(other.cspec), ct(other.ct) {} QColor &operator=(QColor &&other) noexcept { cspec = other.cspec; ct = other.ct; return *this; } -# endif QColor &operator=(const QColor &) noexcept; #endif // Qt < 6 diff --git a/src/gui/painting/qpagelayout.h b/src/gui/painting/qpagelayout.h index faf0827c1a..7ee0ce7a76 100644 --- a/src/gui/painting/qpagelayout.h +++ b/src/gui/painting/qpagelayout.h @@ -82,9 +82,7 @@ public: const QMarginsF &margins, Unit units = Point, const QMarginsF &minMargins = QMarginsF(0, 0, 0, 0)); QPageLayout(const QPageLayout &other); -#ifdef Q_COMPILER_RVALUE_REFS QPageLayout &operator=(QPageLayout &&other) noexcept { swap(other); return *this; } -#endif QPageLayout &operator=(const QPageLayout &other); ~QPageLayout(); diff --git a/src/gui/painting/qpagesize.h b/src/gui/painting/qpagesize.h index a2ea691677..133274760f 100644 --- a/src/gui/painting/qpagesize.h +++ b/src/gui/painting/qpagesize.h @@ -236,9 +236,7 @@ public: const QString &name = QString(), SizeMatchPolicy matchPolicy = FuzzyMatch); QPageSize(const QPageSize &other); -#ifdef Q_COMPILER_RVALUE_REFS QPageSize &operator=(QPageSize &&other) noexcept { swap(other); return *this; } -#endif QPageSize &operator=(const QPageSize &other); ~QPageSize(); diff --git a/src/gui/painting/qpainterpath.h b/src/gui/painting/qpainterpath.h index 2785669260..ed5be667b7 100644 --- a/src/gui/painting/qpainterpath.h +++ b/src/gui/painting/qpainterpath.h @@ -92,10 +92,8 @@ public: explicit QPainterPath(const QPointF &startPoint); QPainterPath(const QPainterPath &other); QPainterPath &operator=(const QPainterPath &other); -#ifdef Q_COMPILER_RVALUE_REFS inline QPainterPath &operator=(QPainterPath &&other) noexcept { qSwap(d_ptr, other.d_ptr); return *this; } -#endif ~QPainterPath(); inline void swap(QPainterPath &other) noexcept { d_ptr.swap(other.d_ptr); } diff --git a/src/gui/painting/qpen.h b/src/gui/painting/qpen.h index 884ec8cdfa..10b11d1d85 100644 --- a/src/gui/painting/qpen.h +++ b/src/gui/painting/qpen.h @@ -70,12 +70,10 @@ public: ~QPen(); QPen &operator=(const QPen &pen) noexcept; -#ifdef Q_COMPILER_RVALUE_REFS QPen(QPen &&other) noexcept : d(other.d) { other.d = nullptr; } QPen &operator=(QPen &&other) noexcept { qSwap(d, other.d); return *this; } -#endif void swap(QPen &other) noexcept { qSwap(d, other.d); } Qt::PenStyle style() const; diff --git a/src/gui/painting/qpolygon.h b/src/gui/painting/qpolygon.h index 118861c0f2..93fab55aa1 100644 --- a/src/gui/painting/qpolygon.h +++ b/src/gui/painting/qpolygon.h @@ -60,16 +60,12 @@ public: inline ~QPolygon() {} inline explicit QPolygon(int size); inline /*implicit*/ QPolygon(const QVector &v) : QVector(v) {} -#ifdef Q_COMPILER_RVALUE_REFS /*implicit*/ QPolygon(QVector &&v) noexcept : QVector(std::move(v)) {} -#endif QPolygon(const QRect &r, bool closed=false); QPolygon(int nPoints, const int *points); QPolygon(const QPolygon &other) : QVector(other) {} -#ifdef Q_COMPILER_RVALUE_REFS QPolygon(QPolygon &&other) noexcept : QVector(std::move(other)) {} QPolygon &operator=(QPolygon &&other) noexcept { swap(other); return *this; } -#endif QPolygon &operator=(const QPolygon &other) { QVector::operator=(other); return *this; } void swap(QPolygon &other) noexcept { QVector::swap(other); } // prevent QVector<->QPolygon swaps @@ -145,16 +141,12 @@ public: inline ~QPolygonF() {} inline explicit QPolygonF(int size); inline /*implicit*/ QPolygonF(const QVector &v) : QVector(v) {} -#ifdef Q_COMPILER_RVALUE_REFS /* implicit */ QPolygonF(QVector &&v) noexcept : QVector(std::move(v)) {} -#endif QPolygonF(const QRectF &r); /*implicit*/ QPolygonF(const QPolygon &a); inline QPolygonF(const QPolygonF &a) : QVector(a) {} -#ifdef Q_COMPILER_RVALUE_REFS QPolygonF(QPolygonF &&other) noexcept : QVector(std::move(other)) {} QPolygonF &operator=(QPolygonF &&other) noexcept { swap(other); return *this; } -#endif QPolygonF &operator=(const QPolygonF &other) { QVector::operator=(other); return *this; } inline void swap(QPolygonF &other) { QVector::swap(other); } // prevent QVector<->QPolygonF swaps diff --git a/src/gui/painting/qregion.h b/src/gui/painting/qregion.h index 9b6b25d743..54de916198 100644 --- a/src/gui/painting/qregion.h +++ b/src/gui/painting/qregion.h @@ -74,10 +74,8 @@ public: QRegion(const QBitmap &bitmap); ~QRegion(); QRegion &operator=(const QRegion &); -#ifdef Q_COMPILER_RVALUE_REFS inline QRegion &operator=(QRegion &&other) noexcept { qSwap(d, other.d); return *this; } -#endif inline void swap(QRegion &other) noexcept { qSwap(d, other.d); } bool isEmpty() const; bool isNull() const; diff --git a/src/gui/text/qfont.h b/src/gui/text/qfont.h index 16685ed9e8..683aa3bf65 100644 --- a/src/gui/text/qfont.h +++ b/src/gui/text/qfont.h @@ -261,10 +261,8 @@ public: bool operator<(const QFont &) const; operator QVariant() const; bool isCopyOf(const QFont &) const; -#ifdef Q_COMPILER_RVALUE_REFS inline QFont &operator=(QFont &&other) noexcept { qSwap(d, other.d); qSwap(resolve_mask, other.resolve_mask); return *this; } -#endif #if QT_DEPRECATED_SINCE(5, 3) // needed for X11 diff --git a/src/gui/text/qfontmetrics.h b/src/gui/text/qfontmetrics.h index 761cadde47..a92ee9ed2f 100644 --- a/src/gui/text/qfontmetrics.h +++ b/src/gui/text/qfontmetrics.h @@ -76,10 +76,8 @@ public: ~QFontMetrics(); QFontMetrics &operator=(const QFontMetrics &); -#ifdef Q_COMPILER_RVALUE_REFS inline QFontMetrics &operator=(QFontMetrics &&other) noexcept { qSwap(d, other.d); return *this; } -#endif void swap(QFontMetrics &other) noexcept { qSwap(d, other.d); } @@ -172,10 +170,8 @@ public: QFontMetricsF &operator=(const QFontMetricsF &); QFontMetricsF &operator=(const QFontMetrics &); -#ifdef Q_COMPILER_RVALUE_REFS inline QFontMetricsF &operator=(QFontMetricsF &&other) { qSwap(d, other.d); return *this; } -#endif void swap(QFontMetricsF &other) { qSwap(d, other.d); } diff --git a/src/gui/text/qglyphrun.h b/src/gui/text/qglyphrun.h index 9bb1d3c820..15e315bea2 100644 --- a/src/gui/text/qglyphrun.h +++ b/src/gui/text/qglyphrun.h @@ -66,9 +66,7 @@ public: QGlyphRun(); QGlyphRun(const QGlyphRun &other); -#ifdef Q_COMPILER_RVALUE_REFS QGlyphRun &operator=(QGlyphRun &&other) noexcept { swap(other); return *this; } -#endif QGlyphRun &operator=(const QGlyphRun &other); ~QGlyphRun(); diff --git a/src/gui/text/qrawfont.h b/src/gui/text/qrawfont.h index 3b84f642d3..c6289d6c93 100644 --- a/src/gui/text/qrawfont.h +++ b/src/gui/text/qrawfont.h @@ -79,9 +79,7 @@ public: qreal pixelSize, QFont::HintingPreference hintingPreference = QFont::PreferDefaultHinting); QRawFont(const QRawFont &other); -#ifdef Q_COMPILER_RVALUE_REFS QRawFont &operator=(QRawFont &&other) noexcept { swap(other); return *this; } -#endif QRawFont &operator=(const QRawFont &other); ~QRawFont(); diff --git a/src/gui/text/qstatictext.h b/src/gui/text/qstatictext.h index c6a0d158c1..e8c94a6add 100644 --- a/src/gui/text/qstatictext.h +++ b/src/gui/text/qstatictext.h @@ -64,9 +64,7 @@ public: QStaticText(); explicit QStaticText(const QString &text); QStaticText(const QStaticText &other); -#ifdef Q_COMPILER_RVALUE_REFS QStaticText &operator=(QStaticText &&other) noexcept { swap(other); return *this; } -#endif QStaticText &operator=(const QStaticText &); ~QStaticText(); diff --git a/src/gui/text/qtextcursor.h b/src/gui/text/qtextcursor.h index 4a9c614887..7cad3cc5e8 100644 --- a/src/gui/text/qtextcursor.h +++ b/src/gui/text/qtextcursor.h @@ -73,9 +73,7 @@ public: explicit QTextCursor(QTextFrame *frame); explicit QTextCursor(const QTextBlock &block); QTextCursor(const QTextCursor &cursor); -#ifdef Q_COMPILER_RVALUE_REFS QTextCursor &operator=(QTextCursor &&other) noexcept { swap(other); return *this; } -#endif QTextCursor &operator=(const QTextCursor &other); ~QTextCursor(); diff --git a/src/network/access/qabstractnetworkcache.h b/src/network/access/qabstractnetworkcache.h index b604323c41..e357dfe58f 100644 --- a/src/network/access/qabstractnetworkcache.h +++ b/src/network/access/qabstractnetworkcache.h @@ -67,9 +67,7 @@ public: QNetworkCacheMetaData(const QNetworkCacheMetaData &other); ~QNetworkCacheMetaData(); -#ifdef Q_COMPILER_RVALUE_REFS QNetworkCacheMetaData &operator=(QNetworkCacheMetaData &&other) noexcept { swap(other); return *this; } -#endif QNetworkCacheMetaData &operator=(const QNetworkCacheMetaData &other); void swap(QNetworkCacheMetaData &other) noexcept diff --git a/src/network/access/qhttpmultipart.h b/src/network/access/qhttpmultipart.h index f718d51d0c..56db83779a 100644 --- a/src/network/access/qhttpmultipart.h +++ b/src/network/access/qhttpmultipart.h @@ -60,9 +60,7 @@ public: QHttpPart(); QHttpPart(const QHttpPart &other); ~QHttpPart(); -#ifdef Q_COMPILER_RVALUE_REFS QHttpPart &operator=(QHttpPart &&other) noexcept { swap(other); return *this; } -#endif QHttpPart &operator=(const QHttpPart &other); void swap(QHttpPart &other) noexcept { qSwap(d, other.d); } diff --git a/src/network/access/qnetworkcookie.h b/src/network/access/qnetworkcookie.h index 58c504f9ae..b712b63849 100644 --- a/src/network/access/qnetworkcookie.h +++ b/src/network/access/qnetworkcookie.h @@ -66,9 +66,7 @@ public: explicit QNetworkCookie(const QByteArray &name = QByteArray(), const QByteArray &value = QByteArray()); QNetworkCookie(const QNetworkCookie &other); ~QNetworkCookie(); -#ifdef Q_COMPILER_RVALUE_REFS QNetworkCookie &operator=(QNetworkCookie &&other) noexcept { swap(other); return *this; } -#endif QNetworkCookie &operator=(const QNetworkCookie &other); void swap(QNetworkCookie &other) noexcept { qSwap(d, other.d); } diff --git a/src/network/access/qnetworkrequest.h b/src/network/access/qnetworkrequest.h index 2515ff6ead..de27b9fede 100644 --- a/src/network/access/qnetworkrequest.h +++ b/src/network/access/qnetworkrequest.h @@ -130,9 +130,7 @@ public: explicit QNetworkRequest(const QUrl &url = QUrl()); QNetworkRequest(const QNetworkRequest &other); ~QNetworkRequest(); -#ifdef Q_COMPILER_RVALUE_REFS QNetworkRequest &operator=(QNetworkRequest &&other) noexcept { swap(other); return *this; } -#endif QNetworkRequest &operator=(const QNetworkRequest &other); void swap(QNetworkRequest &other) noexcept { qSwap(d, other.d); } diff --git a/src/network/bearer/qnetworkconfiguration.h b/src/network/bearer/qnetworkconfiguration.h index 41b6e6f020..048abc2fc8 100644 --- a/src/network/bearer/qnetworkconfiguration.h +++ b/src/network/bearer/qnetworkconfiguration.h @@ -55,9 +55,7 @@ class Q_NETWORK_EXPORT QNetworkConfiguration public: QNetworkConfiguration(); QNetworkConfiguration(const QNetworkConfiguration& other); -#ifdef Q_COMPILER_RVALUE_REFS QNetworkConfiguration &operator=(QNetworkConfiguration &&other) noexcept { swap(other); return *this; } -#endif QNetworkConfiguration &operator=(const QNetworkConfiguration &other); ~QNetworkConfiguration(); diff --git a/src/network/kernel/qdnslookup.h b/src/network/kernel/qdnslookup.h index 79a476b98f..110a74da44 100644 --- a/src/network/kernel/qdnslookup.h +++ b/src/network/kernel/qdnslookup.h @@ -64,9 +64,7 @@ class Q_NETWORK_EXPORT QDnsDomainNameRecord public: QDnsDomainNameRecord(); QDnsDomainNameRecord(const QDnsDomainNameRecord &other); -#ifdef Q_COMPILER_RVALUE_REFS QDnsDomainNameRecord &operator=(QDnsDomainNameRecord &&other) noexcept { swap(other); return *this; } -#endif QDnsDomainNameRecord &operator=(const QDnsDomainNameRecord &other); ~QDnsDomainNameRecord(); @@ -88,9 +86,7 @@ class Q_NETWORK_EXPORT QDnsHostAddressRecord public: QDnsHostAddressRecord(); QDnsHostAddressRecord(const QDnsHostAddressRecord &other); -#ifdef Q_COMPILER_RVALUE_REFS QDnsHostAddressRecord &operator=(QDnsHostAddressRecord &&other) noexcept { swap(other); return *this; } -#endif QDnsHostAddressRecord &operator=(const QDnsHostAddressRecord &other); ~QDnsHostAddressRecord(); @@ -112,9 +108,7 @@ class Q_NETWORK_EXPORT QDnsMailExchangeRecord public: QDnsMailExchangeRecord(); QDnsMailExchangeRecord(const QDnsMailExchangeRecord &other); -#ifdef Q_COMPILER_RVALUE_REFS QDnsMailExchangeRecord &operator=(QDnsMailExchangeRecord &&other) noexcept { swap(other); return *this; } -#endif QDnsMailExchangeRecord &operator=(const QDnsMailExchangeRecord &other); ~QDnsMailExchangeRecord(); @@ -137,9 +131,7 @@ class Q_NETWORK_EXPORT QDnsServiceRecord public: QDnsServiceRecord(); QDnsServiceRecord(const QDnsServiceRecord &other); -#ifdef Q_COMPILER_RVALUE_REFS QDnsServiceRecord &operator=(QDnsServiceRecord &&other) noexcept { swap(other); return *this; } -#endif QDnsServiceRecord &operator=(const QDnsServiceRecord &other); ~QDnsServiceRecord(); @@ -164,9 +156,7 @@ class Q_NETWORK_EXPORT QDnsTextRecord public: QDnsTextRecord(); QDnsTextRecord(const QDnsTextRecord &other); -#ifdef Q_COMPILER_RVALUE_REFS QDnsTextRecord &operator=(QDnsTextRecord &&other) noexcept { swap(other); return *this; } -#endif QDnsTextRecord &operator=(const QDnsTextRecord &other); ~QDnsTextRecord(); diff --git a/src/network/kernel/qhostaddress.h b/src/network/kernel/qhostaddress.h index f20da3304f..799247695e 100644 --- a/src/network/kernel/qhostaddress.h +++ b/src/network/kernel/qhostaddress.h @@ -102,11 +102,8 @@ public: QHostAddress(SpecialAddress address); ~QHostAddress(); -#ifdef Q_COMPILER_RVALUE_REFS QHostAddress &operator=(QHostAddress &&other) noexcept { swap(other); return *this; } -#endif - QHostAddress &operator=(const QHostAddress &other); #if QT_DEPRECATED_SINCE(5, 8) QT_DEPRECATED_X("use = QHostAddress(string) instead") diff --git a/src/network/kernel/qnetworkinterface.h b/src/network/kernel/qnetworkinterface.h index 1d3286118e..4caedaa38f 100644 --- a/src/network/kernel/qnetworkinterface.h +++ b/src/network/kernel/qnetworkinterface.h @@ -64,9 +64,7 @@ public: QNetworkAddressEntry(); QNetworkAddressEntry(const QNetworkAddressEntry &other); -#ifdef Q_COMPILER_RVALUE_REFS QNetworkAddressEntry &operator=(QNetworkAddressEntry &&other) noexcept { swap(other); return *this; } -#endif QNetworkAddressEntry &operator=(const QNetworkAddressEntry &other); ~QNetworkAddressEntry(); @@ -142,9 +140,7 @@ public: QNetworkInterface(); QNetworkInterface(const QNetworkInterface &other); -#ifdef Q_COMPILER_RVALUE_REFS QNetworkInterface &operator=(QNetworkInterface &&other) noexcept { swap(other); return *this; } -#endif QNetworkInterface &operator=(const QNetworkInterface &other); ~QNetworkInterface(); diff --git a/src/network/kernel/qnetworkproxy.h b/src/network/kernel/qnetworkproxy.h index 0b1bc02695..302a2ce6ca 100644 --- a/src/network/kernel/qnetworkproxy.h +++ b/src/network/kernel/qnetworkproxy.h @@ -89,9 +89,7 @@ public: QueryType queryType = TcpServer); #endif QNetworkProxyQuery(const QNetworkProxyQuery &other); -#ifdef Q_COMPILER_RVALUE_REFS QNetworkProxyQuery &operator=(QNetworkProxyQuery &&other) noexcept { swap(other); return *this; } -#endif QNetworkProxyQuery &operator=(const QNetworkProxyQuery &other); ~QNetworkProxyQuery(); @@ -161,9 +159,7 @@ public: QNetworkProxy(ProxyType type, const QString &hostName = QString(), quint16 port = 0, const QString &user = QString(), const QString &password = QString()); QNetworkProxy(const QNetworkProxy &other); -#ifdef Q_COMPILER_RVALUE_REFS QNetworkProxy &operator=(QNetworkProxy &&other) noexcept { swap(other); return *this; } -#endif QNetworkProxy &operator=(const QNetworkProxy &other); ~QNetworkProxy(); diff --git a/src/network/ssl/qsslcertificate.h b/src/network/ssl/qsslcertificate.h index a6acfa2cc3..69901b526c 100644 --- a/src/network/ssl/qsslcertificate.h +++ b/src/network/ssl/qsslcertificate.h @@ -88,9 +88,7 @@ public: explicit QSslCertificate(const QByteArray &data = QByteArray(), QSsl::EncodingFormat format = QSsl::Pem); QSslCertificate(const QSslCertificate &other); ~QSslCertificate(); -#ifdef Q_COMPILER_RVALUE_REFS QSslCertificate &operator=(QSslCertificate &&other) noexcept { swap(other); return *this; } -#endif QSslCertificate &operator=(const QSslCertificate &other); void swap(QSslCertificate &other) noexcept diff --git a/src/network/ssl/qsslcertificateextension.h b/src/network/ssl/qsslcertificateextension.h index f862015312..7cc8a888be 100644 --- a/src/network/ssl/qsslcertificateextension.h +++ b/src/network/ssl/qsslcertificateextension.h @@ -55,9 +55,7 @@ class Q_NETWORK_EXPORT QSslCertificateExtension public: QSslCertificateExtension(); QSslCertificateExtension(const QSslCertificateExtension &other); -#ifdef Q_COMPILER_RVALUE_REFS QSslCertificateExtension &operator=(QSslCertificateExtension &&other) noexcept { swap(other); return *this; } -#endif QSslCertificateExtension &operator=(const QSslCertificateExtension &other); ~QSslCertificateExtension(); diff --git a/src/network/ssl/qsslcipher.h b/src/network/ssl/qsslcipher.h index 430fe9aa7c..6994f590ae 100644 --- a/src/network/ssl/qsslcipher.h +++ b/src/network/ssl/qsslcipher.h @@ -59,9 +59,7 @@ public: explicit QSslCipher(const QString &name); QSslCipher(const QString &name, QSsl::SslProtocol protocol); QSslCipher(const QSslCipher &other); -#ifdef Q_COMPILER_RVALUE_REFS QSslCipher &operator=(QSslCipher &&other) noexcept { swap(other); return *this; } -#endif QSslCipher &operator=(const QSslCipher &other); ~QSslCipher(); diff --git a/src/network/ssl/qsslconfiguration.h b/src/network/ssl/qsslconfiguration.h index 16704ba17b..c25c2686de 100644 --- a/src/network/ssl/qsslconfiguration.h +++ b/src/network/ssl/qsslconfiguration.h @@ -85,9 +85,7 @@ public: QSslConfiguration(); QSslConfiguration(const QSslConfiguration &other); ~QSslConfiguration(); -#ifdef Q_COMPILER_RVALUE_REFS QSslConfiguration &operator=(QSslConfiguration &&other) noexcept { swap(other); return *this; } -#endif QSslConfiguration &operator=(const QSslConfiguration &other); void swap(QSslConfiguration &other) noexcept diff --git a/src/network/ssl/qsslerror.h b/src/network/ssl/qsslerror.h index a9c46c8571..c4a0d52193 100644 --- a/src/network/ssl/qsslerror.h +++ b/src/network/ssl/qsslerror.h @@ -107,9 +107,7 @@ public: { qSwap(d, other.d); } ~QSslError(); -#ifdef Q_COMPILER_RVALUE_REFS QSslError &operator=(QSslError &&other) noexcept { swap(other); return *this; } -#endif QSslError &operator=(const QSslError &other); bool operator==(const QSslError &other) const; inline bool operator!=(const QSslError &other) const diff --git a/src/network/ssl/qsslpresharedkeyauthenticator.h b/src/network/ssl/qsslpresharedkeyauthenticator.h index 29d647b121..5d714dc34e 100644 --- a/src/network/ssl/qsslpresharedkeyauthenticator.h +++ b/src/network/ssl/qsslpresharedkeyauthenticator.h @@ -59,9 +59,7 @@ public: Q_NETWORK_EXPORT QSslPreSharedKeyAuthenticator(const QSslPreSharedKeyAuthenticator &authenticator); Q_NETWORK_EXPORT QSslPreSharedKeyAuthenticator &operator=(const QSslPreSharedKeyAuthenticator &authenticator); -#ifdef Q_COMPILER_RVALUE_REFS QSslPreSharedKeyAuthenticator &operator=(QSslPreSharedKeyAuthenticator &&other) noexcept { swap(other); return *this; } -#endif void swap(QSslPreSharedKeyAuthenticator &other) noexcept { qSwap(d, other.d); } diff --git a/src/printsupport/kernel/qprintdevice_p.h b/src/printsupport/kernel/qprintdevice_p.h index a2b18f08cf..9e76c37617 100644 --- a/src/printsupport/kernel/qprintdevice_p.h +++ b/src/printsupport/kernel/qprintdevice_p.h @@ -76,9 +76,7 @@ public: ~QPrintDevice(); QPrintDevice &operator=(const QPrintDevice &other); - #ifdef Q_COMPILER_RVALUE_REFS QPrintDevice &operator=(QPrintDevice &&other) { swap(other); return *this; } -#endif void swap(QPrintDevice &other) { d.swap(other.d); } -- cgit v1.2.3 From 75256d62d2462103180b368aa79b933acf71f444 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Wed, 6 Feb 2019 17:10:42 +0100 Subject: Render markdown task lists (checkboxes instead of bullets) in QTextEdit Checkboxes are right-aligned with any bullets that are in the same QTextList so that there is enough space to make them larger than bullets. But hopefully mixing bullets and checkboxes will be a rarely-used feature. Change-Id: I28e274d1f7883aa093df29eb4988e99641e87a71 Reviewed-by: Gatis Paeglis --- src/gui/text/qtextdocumentlayout.cpp | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/gui/text/qtextdocumentlayout.cpp b/src/gui/text/qtextdocumentlayout.cpp index bed0a2c450..7873faf2cb 100644 --- a/src/gui/text/qtextdocumentlayout.cpp +++ b/src/gui/text/qtextdocumentlayout.cpp @@ -1436,6 +1436,21 @@ void QTextDocumentLayoutPrivate::drawListItem(const QPointF &offset, QPainter *p QBrush brush = context.palette.brush(QPalette::Text); + bool marker = bl.blockFormat().marker() != QTextBlockFormat::NoMarker; + if (marker) { + int adj = fontMetrics.lineSpacing() / 6; + r.adjust(-adj, 0, -adj, 0); + if (bl.blockFormat().marker() == QTextBlockFormat::Checked) { + // ### Qt6: render with QStyle / PE_IndicatorCheckBox. We don't currently + // have access to that here, because it would be a widget dependency. + painter->setPen(QPen(painter->pen().color(), 2)); + painter->drawLine(r.topLeft(), r.bottomRight()); + painter->drawLine(r.topRight(), r.bottomLeft()); + painter->setPen(QPen(painter->pen().color(), 0)); + } + painter->drawRect(r.adjusted(-adj, -adj, adj, adj)); + } + switch (style) { case QTextListFormat::ListDecimal: case QTextListFormat::ListLowerAlpha: @@ -1456,16 +1471,21 @@ void QTextDocumentLayoutPrivate::drawListItem(const QPointF &offset, QPainter *p break; } case QTextListFormat::ListSquare: - painter->fillRect(r, brush); + if (!marker) + painter->fillRect(r, brush); break; case QTextListFormat::ListCircle: - painter->setPen(QPen(brush, 0)); - painter->drawEllipse(r.translated(0.5, 0.5)); // pixel align for sharper rendering + if (!marker) { + painter->setPen(QPen(brush, 0)); + painter->drawEllipse(r.translated(0.5, 0.5)); // pixel align for sharper rendering + } break; case QTextListFormat::ListDisc: - painter->setBrush(brush); - painter->setPen(Qt::NoPen); - painter->drawEllipse(r); + if (!marker) { + painter->setBrush(brush); + painter->setPen(Qt::NoPen); + painter->drawEllipse(r); + } break; case QTextListFormat::ListStyleUndefined: break; -- cgit v1.2.3 From 355ecfb11c838b4c9facc9a631e04a52531a2127 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Tue, 18 Dec 2018 00:56:37 +0100 Subject: Add QTextMarkdownWriter::writeTable(QAbstractTableModel) This provides the ability to write live data from a table to Markdown, which can be useful to load it into a text document or a wiki. But so far QTextMarkdownWriter is still a private class, intended to be used experimentally from QtQuick and perhaps later exposed in other ways. Change-Id: I0de4673987e4172178604e49b5a024a05d4486ba Reviewed-by: Richard Moe Gustavsen --- src/gui/text/qtextmarkdownwriter.cpp | 31 +++++++++++++++++++++++++++++++ src/gui/text/qtextmarkdownwriter_p.h | 2 ++ 2 files changed, 33 insertions(+) (limited to 'src') diff --git a/src/gui/text/qtextmarkdownwriter.cpp b/src/gui/text/qtextmarkdownwriter.cpp index c91248757a..fed4a7b766 100644 --- a/src/gui/text/qtextmarkdownwriter.cpp +++ b/src/gui/text/qtextmarkdownwriter.cpp @@ -64,6 +64,37 @@ bool QTextMarkdownWriter::writeAll(const QTextDocument &document) return true; } +void QTextMarkdownWriter::writeTable(const QAbstractTableModel &table) +{ + QVector tableColumnWidths(table.columnCount()); + for (int col = 0; col < table.columnCount(); ++col) { + tableColumnWidths[col] = table.headerData(col, Qt::Horizontal).toString().length(); + for (int row = 0; row < table.rowCount(); ++row) { + tableColumnWidths[col] = qMax(tableColumnWidths[col], + table.data(table.index(row, col)).toString().length()); + } + } + + // write the header and separator + for (int col = 0; col < table.columnCount(); ++col) { + QString s = table.headerData(col, Qt::Horizontal).toString(); + m_stream << "|" << s << QString(tableColumnWidths[col] - s.length(), Space); + } + m_stream << "|" << endl; + for (int col = 0; col < tableColumnWidths.length(); ++col) + m_stream << '|' << QString(tableColumnWidths[col], QLatin1Char('-')); + m_stream << '|'<< endl; + + // write the body + for (int row = 0; row < table.rowCount(); ++row) { + for (int col = 0; col < table.columnCount(); ++col) { + QString s = table.data(table.index(row, col)).toString(); + m_stream << "|" << s << QString(tableColumnWidths[col] - s.length(), Space); + } + m_stream << '|'<< endl; + } +} + void QTextMarkdownWriter::writeFrame(const QTextFrame *frame) { Q_ASSERT(frame); diff --git a/src/gui/text/qtextmarkdownwriter_p.h b/src/gui/text/qtextmarkdownwriter_p.h index 9845355259..2a9388ca2d 100644 --- a/src/gui/text/qtextmarkdownwriter_p.h +++ b/src/gui/text/qtextmarkdownwriter_p.h @@ -56,6 +56,7 @@ #include "qtextdocument_p.h" #include "qtextdocumentwriter.h" +#include "QAbstractTableModel" QT_BEGIN_NAMESPACE @@ -64,6 +65,7 @@ class Q_GUI_EXPORT QTextMarkdownWriter public: QTextMarkdownWriter(QTextStream &stream, QTextDocument::MarkdownFeatures features); bool writeAll(const QTextDocument &document); + void writeTable(const QAbstractTableModel &table); int writeBlock(const QTextBlock &block, bool table, bool ignoreFormat); void writeFrame(const QTextFrame *frame); -- cgit v1.2.3 From 402cb62d5db7516e4d8d77d972e55e90cb855679 Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Fri, 15 Mar 2019 12:05:38 +0100 Subject: Introduce QNetworkConnection/Status/Monitor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Private classes to replace broken or even not working at all 'session management' and 'bearer manager' (on at least two major platforms we support). This implementation is macOS/iOS-specific and uses SystemConfiguration framework, or more precisely SCNetworkReachability's part of it. Task-number: QTBUG-40332 Change-Id: Iac5f44c4063c4092b93b8cf2bde3fb2c524855b3 Reviewed-by: Mårten Nordheim --- src/network/access/qhttpnetworkconnection.cpp | 38 +- src/network/access/qhttpnetworkconnection_p.h | 13 + .../access/qhttpnetworkconnectionchannel.cpp | 12 + src/network/access/qnetworkaccessmanager.cpp | 153 ++++++-- src/network/access/qnetworkaccessmanager.h | 2 +- src/network/access/qnetworkaccessmanager_p.h | 8 +- src/network/access/qnetworkreplyhttpimpl.cpp | 15 +- src/network/access/qnetworkreplyimpl.cpp | 2 - src/network/access/qnetworkreplyimpl_p.h | 2 - src/network/kernel/kernel.pri | 12 +- src/network/kernel/qnetconmonitor_darwin.mm | 434 +++++++++++++++++++++ src/network/kernel/qnetconmonitor_p.h | 126 ++++++ src/network/kernel/qnetconmonitor_stub.cpp | 141 +++++++ 13 files changed, 903 insertions(+), 55 deletions(-) create mode 100644 src/network/kernel/qnetconmonitor_darwin.mm create mode 100644 src/network/kernel/qnetconmonitor_p.h create mode 100644 src/network/kernel/qnetconmonitor_stub.cpp (limited to 'src') diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp index 0a37122fc6..cb4c722eb5 100644 --- a/src/network/access/qhttpnetworkconnection.cpp +++ b/src/network/access/qhttpnetworkconnection.cpp @@ -1320,6 +1320,10 @@ QHttpNetworkConnection::QHttpNetworkConnection(const QString &hostName, quint16 Q_D(QHttpNetworkConnection); d->networkSession = std::move(networkSession); d->init(); + if (QNetworkStatusMonitor::isEnabled()) { + connect(&d->connectionMonitor, &QNetworkConnectionMonitor::reachabilityChanged, + this, &QHttpNetworkConnection::onlineStateChanged, Qt::QueuedConnection); + } } QHttpNetworkConnection::QHttpNetworkConnection(quint16 connectionCount, const QString &hostName, @@ -1332,6 +1336,10 @@ QHttpNetworkConnection::QHttpNetworkConnection(quint16 connectionCount, const QS Q_D(QHttpNetworkConnection); d->networkSession = std::move(networkSession); d->init(); + if (QNetworkStatusMonitor::isEnabled()) { + connect(&d->connectionMonitor, &QNetworkConnectionMonitor::reachabilityChanged, + this, &QHttpNetworkConnection::onlineStateChanged, Qt::QueuedConnection); + } } #else QHttpNetworkConnection::QHttpNetworkConnection(const QString &hostName, quint16 port, bool encrypt, @@ -1340,6 +1348,10 @@ QHttpNetworkConnection::QHttpNetworkConnection(const QString &hostName, quint16 { Q_D(QHttpNetworkConnection); d->init(); + if (QNetworkStatusMonitor::isEnabled()) { + connect(&d->connectionMonitor, &QNetworkConnectionMonitor::reachabilityChanged, + this, &QHttpNetworkConnection::onlineStateChanged, Qt::QueuedConnection); + } } QHttpNetworkConnection::QHttpNetworkConnection(quint16 connectionCount, const QString &hostName, @@ -1350,8 +1362,12 @@ QHttpNetworkConnection::QHttpNetworkConnection(quint16 connectionCount, const QS { Q_D(QHttpNetworkConnection); d->init(); + if (QNetworkStatusMonitor::isEnabled()) { + connect(&d->connectionMonitor, &QNetworkConnectionMonitor::reachabilityChanged, + this, &QHttpNetworkConnection::onlineStateChanged, Qt::QueuedConnection); + } } -#endif +#endif // QT_NO_BEARERMANAGEMENT QHttpNetworkConnection::~QHttpNetworkConnection() { @@ -1531,6 +1547,26 @@ void QHttpNetworkConnection::setPeerVerifyName(const QString &peerName) d->peerVerifyName = peerName; } +void QHttpNetworkConnection::onlineStateChanged(bool isOnline) +{ + Q_D(QHttpNetworkConnection); + + if (isOnline) { + // If we did not have any 'isOffline' previously - well, good + // to know, we are 'online' apparently. + return; + } + + for (int i = 0; i < d->activeChannelCount; i++) { + auto &channel = d->channels[i]; + channel.emitFinishedWithError(QNetworkReply::TemporaryNetworkFailureError, "Temporary network failure."); + channel.close(); + } + + // We don't care, this connection is broken from our POV. + d->connectionMonitor.stopMonitoring(); +} + #ifndef QT_NO_NETWORKPROXY // only called from QHttpNetworkConnectionChannel::_q_proxyAuthenticationRequired, not // from QHttpNetworkConnectionChannel::handleAuthenticationChallenge diff --git a/src/network/access/qhttpnetworkconnection_p.h b/src/network/access/qhttpnetworkconnection_p.h index 2f3c334248..85d89f20c2 100644 --- a/src/network/access/qhttpnetworkconnection_p.h +++ b/src/network/access/qhttpnetworkconnection_p.h @@ -67,6 +67,7 @@ #include #include #include +#include #include #include @@ -156,6 +157,10 @@ public: QString peerVerifyName() const; void setPeerVerifyName(const QString &peerName); + +public slots: + void onlineStateChanged(bool isOnline); + private: Q_DECLARE_PRIVATE(QHttpNetworkConnection) Q_DISABLE_COPY_MOVE(QHttpNetworkConnection) @@ -292,6 +297,14 @@ public: Http2::ProtocolParameters http2Parameters; QString peerVerifyName; + // If network status monitoring is enabled, we activate connectionMonitor + // as soons as one of channels managed to connect to host (and we + // have a pair of addresses (us,peer). + // NETMONTODO: consider activating a monitor on a change from + // HostLookUp state to ConnectingState (means we have both + // local/remote addresses known and can start monitoring this + // early). + QNetworkConnectionMonitor connectionMonitor; friend class QHttpNetworkConnectionChannel; }; diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index f79a4d1dc6..9309d718e4 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -59,6 +59,8 @@ #include "private/qnetworksession_p.h" #endif +#include "private/qnetconmonitor_p.h" + QT_BEGIN_NAMESPACE namespace @@ -896,6 +898,16 @@ void QHttpNetworkConnectionChannel::_q_connected() pipeliningSupported = QHttpNetworkConnectionChannel::PipeliningSupportUnknown; + if (QNetworkStatusMonitor::isEnabled()) { + auto connectionPrivate = connection->d_func(); + if (!connectionPrivate->connectionMonitor.isMonitoring()) { + // Now that we have a pair of addresses, we can start monitoring the + // connection status to handle its loss properly. + if (connectionPrivate->connectionMonitor.setTargets(socket->localAddress(), socket->peerAddress())) + connectionPrivate->connectionMonitor.startMonitoring(); + } + } + // ### FIXME: if the server closes the connection unexpectedly, we shouldn't send the same broken request again! //channels[i].reconnectAttempts = 2; if (ssl || pendingEncrypt) { // FIXME: Didn't work properly with pendingEncrypt only, we should refactor this into an EncrypingState diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index 50b9488594..8bd630ad9d 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -90,6 +90,8 @@ #include "qnetworkreplywasmimpl_p.h" #endif +#include "qnetconmonitor_p.h" + QT_BEGIN_NAMESPACE Q_GLOBAL_STATIC(QNetworkAccessFileBackendFactory, fileBackend) @@ -486,18 +488,25 @@ QNetworkAccessManager::QNetworkAccessManager(QObject *parent) qRegisterMetaType(); qRegisterMetaType >(); -#ifndef QT_NO_BEARERMANAGEMENT Q_D(QNetworkAccessManager); - // if a session is required, we track online state through - // the QNetworkSession's signals if a request is already made. - // we need to track current accessibility state by default - // - connect(&d->networkConfigurationManager, SIGNAL(onlineStateChanged(bool)), - SLOT(_q_onlineStateChanged(bool))); - connect(&d->networkConfigurationManager, SIGNAL(configurationChanged(QNetworkConfiguration)), - SLOT(_q_configurationChanged(QNetworkConfiguration))); - -#endif + if (QNetworkStatusMonitor::isEnabled()) { + connect(&d->statusMonitor, SIGNAL(onlineStateChanged(bool)), + SLOT(_q_onlineStateChanged(bool))); +#ifdef QT_NO_BEARERMANAGEMENT + d->networkAccessible = d->statusMonitor.isNetworkAccesible(); +#else + d->networkAccessible = d->statusMonitor.isNetworkAccesible() ? Accessible : NotAccessible; + } else { + // if a session is required, we track online state through + // the QNetworkSession's signals if a request is already made. + // we need to track current accessibility state by default + // + connect(&d->networkConfigurationManager, SIGNAL(onlineStateChanged(bool)), + SLOT(_q_onlineStateChanged(bool))); + connect(&d->networkConfigurationManager, SIGNAL(configurationChanged(QNetworkConfiguration)), + SLOT(_q_configurationChanged(QNetworkConfiguration))); +#endif // QT_NO_BEARERMANAGEMENT + } } /*! @@ -1030,9 +1039,13 @@ QNetworkReply *QNetworkAccessManager::deleteResource(const QNetworkRequest &requ void QNetworkAccessManager::setConfiguration(const QNetworkConfiguration &config) { Q_D(QNetworkAccessManager); - d->networkConfiguration = config; - d->customNetworkConfiguration = true; - d->createSession(config); + if (!d->statusMonitor.isEnabled()) { + d->networkConfiguration = config; + d->customNetworkConfiguration = true; + d->createSession(config); + } else { + qWarning(lcNetMon, "No network configuration can be set with network status monitor enabled"); + } } /*! @@ -1048,7 +1061,7 @@ QNetworkConfiguration QNetworkAccessManager::configuration() const Q_D(const QNetworkAccessManager); QSharedPointer session(d->getNetworkSession()); - if (session) { + if (session && !d->statusMonitor.isEnabled()) { return session->configuration(); } else { return d->networkConfigurationManager.defaultConfiguration(); @@ -1075,7 +1088,7 @@ QNetworkConfiguration QNetworkAccessManager::activeConfiguration() const Q_D(const QNetworkAccessManager); QSharedPointer networkSession(d->getNetworkSession()); - if (networkSession) { + if (networkSession && !d->statusMonitor.isEnabled()) { return d->networkConfigurationManager.configurationFromIdentifier( networkSession->sessionProperty(QLatin1String("ActiveConfiguration")).toString()); } else { @@ -1094,6 +1107,11 @@ void QNetworkAccessManager::setNetworkAccessible(QNetworkAccessManager::NetworkA { Q_D(QNetworkAccessManager); + if (d->statusMonitor.isEnabled()) { + qWarning(lcNetMon, "Can not manually set network accessibility with the network status monitor enabled"); + return; + } + d->defaultAccessControl = accessible == NotAccessible ? false : true; if (d->networkAccessible != accessible) { @@ -1114,6 +1132,12 @@ QNetworkAccessManager::NetworkAccessibility QNetworkAccessManager::networkAccess { Q_D(const QNetworkAccessManager); + if (d->statusMonitor.isEnabled()) { + if (!d->statusMonitor.isMonitoring()) + d->statusMonitor.start(); + return d->networkAccessible; + } + if (d->customNetworkConfiguration && d->networkConfiguration.state().testFlag(QNetworkConfiguration::Undefined)) return UnknownAccessibility; @@ -1434,35 +1458,57 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera } } -#ifndef QT_NO_BEARERMANAGEMENT + if (d->statusMonitor.isEnabled()) { + // See the code in ctor - QNetworkStatusMonitor allows us to + // immediately set 'networkAccessible' even before we start + // the monitor. +#ifdef QT_NO_BEARERMANAGEMENT + if (d->networkAccessible +#else + if (d->networkAccessible == NotAccessible +#endif // QT_NO_BEARERMANAGEMENT + && !isLocalFile) { + QHostAddress dest; + QString host = req.url().host().toLower(); + if (!(dest.setAddress(host) && dest.isLoopback()) + && host != QLatin1String("localhost") + && host != QHostInfo::localHostName().toLower()) { + return new QDisabledNetworkReply(this, req, op); + } + } - // Return a disabled network reply if network access is disabled. - // Except if the scheme is empty or file:// or if the host resolves to a loopback address. - if (d->networkAccessible == NotAccessible && !isLocalFile) { - QHostAddress dest; - QString host = req.url().host().toLower(); - if (!(dest.setAddress(host) && dest.isLoopback()) && host != QLatin1String("localhost") + if (!d->statusMonitor.isMonitoring() && !d->statusMonitor.start()) + qWarning(lcNetMon, "failed to start network status monitoring"); + } else { +#ifndef QT_NO_BEARERMANAGEMENT + // Return a disabled network reply if network access is disabled. + // Except if the scheme is empty or file:// or if the host resolves to a loopback address. + if (d->networkAccessible == NotAccessible && !isLocalFile) { + QHostAddress dest; + QString host = req.url().host().toLower(); + if (!(dest.setAddress(host) && dest.isLoopback()) && host != QLatin1String("localhost") && host != QHostInfo::localHostName().toLower()) { - return new QDisabledNetworkReply(this, req, op); + return new QDisabledNetworkReply(this, req, op); + } } - } - if (!d->networkSessionStrongRef && (d->initializeSession || !d->networkConfiguration.identifier().isEmpty())) { - if (!d->networkConfiguration.identifier().isEmpty()) { - if ((d->networkConfiguration.state() & QNetworkConfiguration::Defined) - && d->networkConfiguration != d->networkConfigurationManager.defaultConfiguration()) - d->createSession(d->networkConfigurationManager.defaultConfiguration()); - else - d->createSession(d->networkConfiguration); + if (!d->networkSessionStrongRef && (d->initializeSession || !d->networkConfiguration.identifier().isEmpty())) { + if (!d->networkConfiguration.identifier().isEmpty()) { + if ((d->networkConfiguration.state() & QNetworkConfiguration::Defined) + && d->networkConfiguration != d->networkConfigurationManager.defaultConfiguration()) + d->createSession(d->networkConfigurationManager.defaultConfiguration()); + else + d->createSession(d->networkConfiguration); - } else { - if (d->networkSessionRequired) - d->createSession(d->networkConfigurationManager.defaultConfiguration()); - else - d->initializeSession = false; + } else { + if (d->networkSessionRequired) + d->createSession(d->networkConfigurationManager.defaultConfiguration()); + else + d->initializeSession = false; + } } - } #endif + } QNetworkRequest request = req; if (!request.header(QNetworkRequest::ContentLengthHeader).isValid() && @@ -1509,8 +1555,10 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera #endif QNetworkReplyHttpImpl *reply = new QNetworkReplyHttpImpl(this, request, op, outgoingData); #ifndef QT_NO_BEARERMANAGEMENT - connect(this, SIGNAL(networkSessionConnected()), - reply, SLOT(_q_networkSessionConnected())); + if (!d->statusMonitor.isEnabled()) { + connect(this, SIGNAL(networkSessionConnected()), + reply, SLOT(_q_networkSessionConnected())); + } #endif return reply; } @@ -1519,7 +1567,9 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera // first step: create the reply QNetworkReplyImpl *reply = new QNetworkReplyImpl(this); #ifndef QT_NO_BEARERMANAGEMENT - if (!isLocalFile) { + // NETMONTODO: network reply impl must be augmented to use the same monitoring + // capabilities as http network reply impl does. + if (!isLocalFile && !d->statusMonitor.isEnabled()) { connect(this, SIGNAL(networkSessionConnected()), reply, SLOT(_q_networkSessionConnected())); } @@ -1988,7 +2038,13 @@ void QNetworkAccessManagerPrivate::_q_networkSessionStateChanged(QNetworkSession void QNetworkAccessManagerPrivate::_q_onlineStateChanged(bool isOnline) { - Q_Q(QNetworkAccessManager); + Q_Q(QNetworkAccessManager); + + if (statusMonitor.isEnabled()) { + networkAccessible = isOnline ? QNetworkAccessManager::Accessible : QNetworkAccessManager::NotAccessible; + return; + } + // if the user set a config, we only care whether this one is active. // Otherwise, this QNAM is online if there is an online config. @@ -2018,6 +2074,9 @@ void QNetworkAccessManagerPrivate::_q_onlineStateChanged(bool isOnline) void QNetworkAccessManagerPrivate::_q_configurationChanged(const QNetworkConfiguration &configuration) { + if (statusMonitor.isEnabled()) + return; + const QString id = configuration.identifier(); if (configuration.state().testFlag(QNetworkConfiguration::Active)) { if (!onlineConfigurations.contains(id)) { @@ -2050,6 +2109,9 @@ void QNetworkAccessManagerPrivate::_q_configurationChanged(const QNetworkConfigu void QNetworkAccessManagerPrivate::_q_networkSessionFailed(QNetworkSession::SessionError) { + if (statusMonitor.isEnabled()) + return; + const auto cfgs = networkConfigurationManager.allConfigurations(); for (const QNetworkConfiguration &cfg : cfgs) { if (cfg.state().testFlag(QNetworkConfiguration::Active)) { @@ -2061,6 +2123,13 @@ void QNetworkAccessManagerPrivate::_q_networkSessionFailed(QNetworkSession::Sess } } +#else + +void QNetworkAccessManagerPrivate::_q_onlineStateChanged(bool isOnline) +{ + networkAccessible = isOnline; +} + #endif // QT_NO_BEARERMANAGEMENT #if QT_CONFIG(http) diff --git a/src/network/access/qnetworkaccessmanager.h b/src/network/access/qnetworkaccessmanager.h index 7e2f7683d0..fa23537c68 100644 --- a/src/network/access/qnetworkaccessmanager.h +++ b/src/network/access/qnetworkaccessmanager.h @@ -209,10 +209,10 @@ private: #ifndef QT_NO_BEARERMANAGEMENT Q_PRIVATE_SLOT(d_func(), void _q_networkSessionClosed()) Q_PRIVATE_SLOT(d_func(), void _q_networkSessionStateChanged(QNetworkSession::State)) - Q_PRIVATE_SLOT(d_func(), void _q_onlineStateChanged(bool)) Q_PRIVATE_SLOT(d_func(), void _q_configurationChanged(const QNetworkConfiguration &)) Q_PRIVATE_SLOT(d_func(), void _q_networkSessionFailed(QNetworkSession::SessionError)) #endif + Q_PRIVATE_SLOT(d_func(), void _q_onlineStateChanged(bool)) }; QT_END_NAMESPACE diff --git a/src/network/access/qnetworkaccessmanager_p.h b/src/network/access/qnetworkaccessmanager_p.h index 5cab4928e4..d3a3936533 100644 --- a/src/network/access/qnetworkaccessmanager_p.h +++ b/src/network/access/qnetworkaccessmanager_p.h @@ -55,6 +55,7 @@ #include "qnetworkaccessmanager.h" #include "qnetworkaccesscache_p.h" #include "qnetworkaccessbackend_p.h" +#include "qnetconmonitor_p.h" #include "qnetworkrequest.h" #include "qhsts_p.h" #include "private/qobject_p.h" @@ -151,6 +152,7 @@ public: QNetworkAccessBackend *findBackend(QNetworkAccessManager::Operation op, const QNetworkRequest &request); QStringList backendSupportedSchemes() const; + void _q_onlineStateChanged(bool isOnline); #ifndef QT_NO_BEARERMANAGEMENT void createSession(const QNetworkConfiguration &config); QSharedPointer getNetworkSession() const; @@ -160,12 +162,11 @@ public: void _q_networkSessionPreferredConfigurationChanged(const QNetworkConfiguration &config, bool isSeamless); void _q_networkSessionStateChanged(QNetworkSession::State state); - void _q_onlineStateChanged(bool isOnline); + void _q_configurationChanged(const QNetworkConfiguration &configuration); void _q_networkSessionFailed(QNetworkSession::SessionError error); QSet onlineConfigurations; - #endif #if QT_CONFIG(http) @@ -199,6 +200,8 @@ public: int activeReplyCount; bool online; bool initializeSession; +#else + bool networkAccessible = true; #endif bool cookieJarCreated; @@ -222,6 +225,7 @@ public: QScopedPointer stsStore; #endif // QT_CONFIG(settings) bool stsEnabled = false; + mutable QNetworkStatusMonitor statusMonitor; #ifndef QT_NO_BEARERMANAGEMENT Q_AUTOTEST_EXPORT static const QWeakPointer getNetworkSession(const QNetworkAccessManager *manager); diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp index f801ef0c88..b9651b35d2 100644 --- a/src/network/access/qnetworkreplyhttpimpl.cpp +++ b/src/network/access/qnetworkreplyhttpimpl.cpp @@ -59,6 +59,7 @@ #include #include "qnetworkcookiejar.h" +#include "qnetconmonitor_p.h" #include // for strchr @@ -166,6 +167,11 @@ static QHash parseHttpOptionHeader(const QByteArray &hea #if QT_CONFIG(bearermanagement) static bool isSessionNeeded(const QUrl &url) { + if (QNetworkStatusMonitor::isEnabled()) { + // In case QNetworkStatus/QNetConManager are in business, + // no session, no bearer manager are involved. + return false; + } // Connections to the local machine does not require a session QString host = url.host().toLower(); return !QHostAddress(host).isLoopback() && host != QLatin1String("localhost") @@ -796,7 +802,8 @@ void QNetworkReplyHttpImplPrivate::postRequest(const QNetworkRequest &newHttpReq if (blob.isValid() && blob.canConvert()) delegate->http2Parameters = blob.value(); #ifndef QT_NO_BEARERMANAGEMENT - delegate->networkSession = managerPrivate->getNetworkSession(); + if (!QNetworkStatusMonitor::isEnabled()) + delegate->networkSession = managerPrivate->getNetworkSession(); #endif // For the synchronous HTTP, this is the normal way the delegate gets deleted @@ -1807,7 +1814,7 @@ bool QNetworkReplyHttpImplPrivate::start(const QNetworkRequest &newHttpRequest) { #ifndef QT_NO_BEARERMANAGEMENT QSharedPointer networkSession(managerPrivate->getNetworkSession()); - if (!networkSession) { + if (!networkSession || QNetworkStatusMonitor::isEnabled()) { #endif postRequest(newHttpRequest); return true; @@ -1895,7 +1902,7 @@ void QNetworkReplyHttpImplPrivate::_q_startOperation() // state changes. if (!startWaitForSession(session)) return; - } else if (session) { + } else if (session && !QNetworkStatusMonitor::isEnabled()) { QObject::connect(session.data(), SIGNAL(stateChanged(QNetworkSession::State)), q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State)), Qt::QueuedConnection); @@ -2184,7 +2191,7 @@ void QNetworkReplyHttpImplPrivate::finished() #ifndef QT_NO_BEARERMANAGEMENT Q_ASSERT(managerPrivate); QSharedPointer session = managerPrivate->getNetworkSession(); - if (session && session->state() == QNetworkSession::Roaming && + if (!QNetworkStatusMonitor::isEnabled() && session && session->state() == QNetworkSession::Roaming && state == Working && errorCode != QNetworkReply::OperationCanceledError) { // only content with a known size will fail with a temporary network failure error if (!totalSize.isNull()) { diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp index f5bb4d5887..1a02938de9 100644 --- a/src/network/access/qnetworkreplyimpl.cpp +++ b/src/network/access/qnetworkreplyimpl.cpp @@ -1117,7 +1117,6 @@ bool QNetworkReplyImplPrivate::migrateBackend() return true; } -#ifndef QT_NO_BEARERMANAGEMENT QDisabledNetworkReply::QDisabledNetworkReply(QObject *parent, const QNetworkRequest &req, QNetworkAccessManager::Operation op) @@ -1142,7 +1141,6 @@ QDisabledNetworkReply::QDisabledNetworkReply(QObject *parent, QDisabledNetworkReply::~QDisabledNetworkReply() { } -#endif QT_END_NAMESPACE diff --git a/src/network/access/qnetworkreplyimpl_p.h b/src/network/access/qnetworkreplyimpl_p.h index 4881e84e9c..85f5b862a8 100644 --- a/src/network/access/qnetworkreplyimpl_p.h +++ b/src/network/access/qnetworkreplyimpl_p.h @@ -209,7 +209,6 @@ public: }; Q_DECLARE_TYPEINFO(QNetworkReplyImplPrivate::InternalNotifications, Q_PRIMITIVE_TYPE); -#ifndef QT_NO_BEARERMANAGEMENT class QDisabledNetworkReply : public QNetworkReply { Q_OBJECT @@ -223,7 +222,6 @@ public: protected: qint64 readData(char *, qint64) override { return -1; } }; -#endif QT_END_NAMESPACE diff --git a/src/network/kernel/kernel.pri b/src/network/kernel/kernel.pri index b86119b200..0e4cef5e74 100644 --- a/src/network/kernel/kernel.pri +++ b/src/network/kernel/kernel.pri @@ -16,7 +16,8 @@ HEADERS += kernel/qtnetworkglobal.h \ kernel/qnetworkinterface.h \ kernel/qnetworkinterface_p.h \ kernel/qnetworkinterface_unix_p.h \ - kernel/qnetworkproxy.h + kernel/qnetworkproxy.h \ + kernel/qnetconmonitor_p.h SOURCES += kernel/qauthenticator.cpp \ kernel/qhostaddress.cpp \ @@ -71,6 +72,15 @@ mac { !uikit: LIBS_PRIVATE += -framework CoreServices -framework SystemConfiguration } +macos | ios { + OBJECTIVE_SOURCES += \ + kernel/qnetconmonitor_darwin.mm + + LIBS_PRIVATE += -framework SystemConfiguration +} else { + SOURCES += kernel/qnetconmonitor_stub.cpp +} + qtConfig(gssapi): LIBS_PRIVATE += -lgssapi_krb5 uikit:HEADERS += kernel/qnetworkinterface_uikit_p.h diff --git a/src/network/kernel/qnetconmonitor_darwin.mm b/src/network/kernel/qnetconmonitor_darwin.mm new file mode 100644 index 0000000000..322c87cb4b --- /dev/null +++ b/src/network/kernel/qnetconmonitor_darwin.mm @@ -0,0 +1,434 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtNetwork module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "private/qnativesocketengine_p.h" +#include "private/qnetconmonitor_p.h" + +#include "private/qobject_p.h" + +#include +#include + +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +Q_LOGGING_CATEGORY(lcNetMon, "qt.network.monitor"); + +namespace { + +class ReachabilityDispatchQueue +{ +public: + ReachabilityDispatchQueue() + { + queue = dispatch_queue_create("qt-network-reachability-queue", nullptr); + if (!queue) + qCWarning(lcNetMon, "Failed to create a dispatch queue for reachability probes"); + } + + ~ReachabilityDispatchQueue() + { + if (queue) + dispatch_release(queue); + } + + dispatch_queue_t data() const + { + return queue; + } + +private: + dispatch_queue_t queue = nullptr; + + Q_DISABLE_COPY_MOVE(ReachabilityDispatchQueue) +}; + +dispatch_queue_t qt_reachability_queue() +{ + static const ReachabilityDispatchQueue reachabilityQueue; + return reachabilityQueue.data(); +} + +qt_sockaddr qt_hostaddress_to_sockaddr(const QHostAddress &src) +{ + if (src.isNull()) + return {}; + + qt_sockaddr dst; + if (src.protocol() == QAbstractSocket::IPv4Protocol) { + dst.a4 = sockaddr_in{}; + dst.a4.sin_family = AF_INET; + dst.a4.sin_addr.s_addr = htonl(src.toIPv4Address()); + dst.a4.sin_len = sizeof(sockaddr_in); + } else if (src.protocol() == QAbstractSocket::IPv6Protocol) { + dst.a6 = sockaddr_in6{}; + dst.a6.sin6_family = AF_INET6; + dst.a6.sin6_len = sizeof(sockaddr_in6); + const Q_IPV6ADDR ipv6 = src.toIPv6Address(); + std::memcpy(&dst.a6.sin6_addr, &ipv6, sizeof ipv6); + } else { + Q_UNREACHABLE(); + } + + return dst; +} + +} // unnamed namespace + +class QNetworkConnectionMonitorPrivate : public QObjectPrivate +{ +public: + SCNetworkReachabilityRef probe = nullptr; + SCNetworkReachabilityFlags state = kSCNetworkReachabilityFlagsIsLocalAddress; + bool scheduled = false; + + void updateState(SCNetworkReachabilityFlags newState); + void reset(); + bool isReachable() const; + + static void probeCallback(SCNetworkReachabilityRef probe, SCNetworkReachabilityFlags flags, void *info); + + Q_DECLARE_PUBLIC(QNetworkConnectionMonitor) +}; + +void QNetworkConnectionMonitorPrivate::updateState(SCNetworkReachabilityFlags newState) +{ + // To be executed only on the reachability queue. + Q_Q(QNetworkConnectionMonitor); + + // NETMONTODO: for now, 'online' for us means kSCNetworkReachabilityFlagsReachable + // is set. There are more possible flags that require more tests/some special + // setup. So in future this part and related can change/be extended. + const bool wasReachable = isReachable(); + state = newState; + if (wasReachable != isReachable()) + emit q->reachabilityChanged(isReachable()); +} + +void QNetworkConnectionMonitorPrivate::reset() +{ + if (probe) { + CFRelease(probe); + probe = nullptr; + } + + state = kSCNetworkReachabilityFlagsIsLocalAddress; + scheduled = false; +} + +bool QNetworkConnectionMonitorPrivate::isReachable() const +{ + return !!(state & kSCNetworkReachabilityFlagsReachable); +} + +void QNetworkConnectionMonitorPrivate::probeCallback(SCNetworkReachabilityRef probe, SCNetworkReachabilityFlags flags, void *info) +{ + // To be executed only on the reachability queue. + Q_UNUSED(probe); + + auto monitorPrivate = static_cast(info); + Q_ASSERT(monitorPrivate); + monitorPrivate->updateState(flags); +} + +QNetworkConnectionMonitor::QNetworkConnectionMonitor() + : QObject(*new QNetworkConnectionMonitorPrivate) +{ +} + +QNetworkConnectionMonitor::QNetworkConnectionMonitor(const QHostAddress &local, const QHostAddress &remote) + : QObject(*new QNetworkConnectionMonitorPrivate) +{ + setTargets(local, remote); +} + +QNetworkConnectionMonitor::~QNetworkConnectionMonitor() +{ + Q_D(QNetworkConnectionMonitor); + + stopMonitoring(); + d->reset(); +} + +bool QNetworkConnectionMonitor::setTargets(const QHostAddress &local, const QHostAddress &remote) +{ + Q_D(QNetworkConnectionMonitor); + + if (isMonitoring()) { + qCWarning(lcNetMon, "Monitor is already active, call stopMonitoring() first"); + return false; + } + + if (local.isNull()) { + qCWarning(lcNetMon, "Invalid (null) local address, cannot create a reachability target"); + return false; + } + + // Clear the old target if needed: + d->reset(); + + qt_sockaddr client = qt_hostaddress_to_sockaddr(local); + if (remote.isNull()) { + // That's a special case our QNetworkStatusMonitor is using (AnyIpv4/6 address to check an overall status). + d->probe = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, reinterpret_cast(&client)); + } else { + qt_sockaddr target = qt_hostaddress_to_sockaddr(remote); + d->probe = SCNetworkReachabilityCreateWithAddressPair(kCFAllocatorDefault, + reinterpret_cast(&client), + reinterpret_cast(&target)); + } + + if (d->probe) { + // Let's read the initial state so that callback coming later can + // see a difference. Ignore errors though. + SCNetworkReachabilityGetFlags(d->probe, &d->state); + }else { + qCWarning(lcNetMon, "Failed to create network reachability probe"); + return false; + } + + return true; +} + +bool QNetworkConnectionMonitor::startMonitoring() +{ + Q_D(QNetworkConnectionMonitor); + + if (isMonitoring()) { + qCWarning(lcNetMon, "Monitor is already active, call stopMonitoring() first"); + return false; + } + + if (!d->probe) { + qCWarning(lcNetMon, "Can not start monitoring, set targets first"); + return false; + } + + auto queue = qt_reachability_queue(); + if (!queue) { + qWarning(lcNetMon, "Failed to create a dispatch queue to schedule a probe on"); + return false; + } + + SCNetworkReachabilityContext context = {}; + context.info = d; + if (!SCNetworkReachabilitySetCallback(d->probe, QNetworkConnectionMonitorPrivate::probeCallback, &context)) { + qWarning(lcNetMon, "Failed to set a reachability callback"); + return false; + } + + + if (!SCNetworkReachabilitySetDispatchQueue(d->probe, queue)) { + qWarning(lcNetMon, "Failed to schedule a reachability callback on a queue"); + return false; + } + + return d->scheduled = true; +} + +bool QNetworkConnectionMonitor::isMonitoring() const +{ + Q_D(const QNetworkConnectionMonitor); + + return d->scheduled; +} + +void QNetworkConnectionMonitor::stopMonitoring() +{ + Q_D(QNetworkConnectionMonitor); + + if (d->scheduled) { + Q_ASSERT(d->probe); + SCNetworkReachabilitySetDispatchQueue(d->probe, nullptr); + SCNetworkReachabilitySetCallback(d->probe, nullptr, nullptr); + d->scheduled = false; + } +} + +bool QNetworkConnectionMonitor::isReachable() +{ + Q_D(QNetworkConnectionMonitor); + + if (isMonitoring()) { + qCWarning(lcNetMon, "Calling isReachable() is unsafe after the monitoring started"); + return false; + } + + if (!d->probe) { + qCWarning(lcNetMon, "Reachability is unknown, set the target first"); + return false; + } + + return d->isReachable(); +} + +class QNetworkStatusMonitorPrivate : public QObjectPrivate +{ +public: + QNetworkConnectionMonitor ipv4Probe; + bool isOnlineIpv4 = false; + QNetworkConnectionMonitor ipv6Probe; + bool isOnlineIpv6 = false; + + static bool enabled; + static void readEnv(); +}; + +bool QNetworkStatusMonitorPrivate::enabled = false; + +void QNetworkStatusMonitorPrivate::readEnv() +{ + bool envOk = false; + const int env = qEnvironmentVariableIntValue("QT_USE_NETWORK_MONITOR", &envOk); + enabled = envOk && env > 0; +} + +QNetworkStatusMonitor::QNetworkStatusMonitor() + : QObject(*new QNetworkStatusMonitorPrivate) +{ + Q_D(QNetworkStatusMonitor); + + if (d->ipv4Probe.setTargets(QHostAddress::AnyIPv4, {})) { + // We manage to create SCNetworkReachabilityRef for IPv4, let's + // read the last known state then! + d->isOnlineIpv4 = d->ipv4Probe.isReachable(); + } + + if (d->ipv6Probe.setTargets(QHostAddress::AnyIPv6, {})) { + // We manage to create SCNetworkReachability ref for IPv6, let's + // read the last known state then! + d->isOnlineIpv6 = d->ipv6Probe.isReachable(); + } + + + connect(&d->ipv4Probe, &QNetworkConnectionMonitor::reachabilityChanged, this, + &QNetworkStatusMonitor::reachabilityChanged, Qt::QueuedConnection); + connect(&d->ipv6Probe, &QNetworkConnectionMonitor::reachabilityChanged, this, + &QNetworkStatusMonitor::reachabilityChanged, Qt::QueuedConnection); +} + +QNetworkStatusMonitor::~QNetworkStatusMonitor() +{ + Q_D(QNetworkStatusMonitor); + + d->ipv4Probe.disconnect(); + d->ipv4Probe.stopMonitoring(); + d->ipv6Probe.disconnect(); + d->ipv6Probe.stopMonitoring(); +} + +bool QNetworkStatusMonitor::start() +{ + Q_D(QNetworkStatusMonitor); + + if (isMonitoring()) { + qCWarning(lcNetMon, "Network status monitor is already active"); + return true; + } + + d->ipv4Probe.startMonitoring(); + d->ipv6Probe.startMonitoring(); + + return isMonitoring(); +} + +void QNetworkStatusMonitor::stop() +{ + Q_D(QNetworkStatusMonitor); + + if (d->ipv4Probe.isMonitoring()) + d->ipv4Probe.stopMonitoring(); + if (d->ipv6Probe.isMonitoring()) + d->ipv6Probe.stopMonitoring(); +} + +bool QNetworkStatusMonitor::isMonitoring() const +{ + Q_D(const QNetworkStatusMonitor); + + return d->ipv4Probe.isMonitoring() || d->ipv6Probe.isMonitoring(); +} + +bool QNetworkStatusMonitor::isNetworkAccesible() +{ + // This function is to be executed on the thread that created + // and uses 'this'. + Q_D(QNetworkStatusMonitor); + + return d->isOnlineIpv4 || d->isOnlineIpv6; +} + +bool QNetworkStatusMonitor::isEnabled() +{ + static std::once_flag envRead = {}; + std::call_once(envRead, QNetworkStatusMonitorPrivate::readEnv); + return QNetworkStatusMonitorPrivate::enabled; +} + +void QNetworkStatusMonitor::reachabilityChanged(bool online) +{ + // This function is executed on the thread that created/uses 'this', + // not on the reachability queue. + Q_D(QNetworkStatusMonitor); + + auto probe = qobject_cast(sender()); + if (!probe) + return; + + const bool isIpv4 = probe == &d->ipv4Probe; + bool &probeOnline = isIpv4 ? d->isOnlineIpv4 : d->isOnlineIpv6; + bool otherOnline = isIpv4 ? d->isOnlineIpv6 : d->isOnlineIpv4; + + if (probeOnline == online) { + // We knew this already? + return; + } + + probeOnline = online; + if (!otherOnline) { + // We either just lost or got a network access. + emit onlineStateChanged(probeOnline); + } +} + +QT_END_NAMESPACE diff --git a/src/network/kernel/qnetconmonitor_p.h b/src/network/kernel/qnetconmonitor_p.h new file mode 100644 index 0000000000..74ee56d422 --- /dev/null +++ b/src/network/kernel/qnetconmonitor_p.h @@ -0,0 +1,126 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtNetwork module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QNETCONMONITOR_P_H +#define QNETCONMONITOR_P_H + +#include + +#include +#include +#include +#include + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +QT_BEGIN_NAMESPACE + +class QNetworkConnectionMonitorPrivate; +class QNetworkConnectionMonitor : public QObject +{ + Q_OBJECT + +public: + QNetworkConnectionMonitor(); + QNetworkConnectionMonitor(const QHostAddress &local, const QHostAddress &remote = {}); + ~QNetworkConnectionMonitor(); + + bool setTargets(const QHostAddress &local, const QHostAddress &remote); + bool isReachable(); + + // Important: on Darwin you should not call isReachable() after + // startMonitoring(), you have to listen to reachabilityChanged() + // signal instead. + bool startMonitoring(); + bool isMonitoring() const; + void stopMonitoring(); + +Q_SIGNALS: + // Important: connect to this using QueuedConnection. On Darwin + // callback is coming on a special dispatch queue. + void reachabilityChanged(bool isOnline); + +private: + Q_DECLARE_PRIVATE(QNetworkConnectionMonitor) + Q_DISABLE_COPY_MOVE(QNetworkConnectionMonitor) +}; + +class QNetworkStatusMonitorPrivate; +class QNetworkStatusMonitor : public QObject +{ + Q_OBJECT + +public: + QNetworkStatusMonitor(); + ~QNetworkStatusMonitor(); + + bool isNetworkAccesible(); + + bool start(); + void stop(); + bool isMonitoring() const; + + static bool isEnabled(); + +Q_SIGNALS: + // Unlike QNetworkConnectionMonitor, this can be connected to directly. + void onlineStateChanged(bool isOnline); + +private slots: + void reachabilityChanged(bool isOnline); + +private: + Q_DECLARE_PRIVATE(QNetworkStatusMonitor) + Q_DISABLE_COPY_MOVE(QNetworkStatusMonitor) +}; + +Q_DECLARE_LOGGING_CATEGORY(lcNetMon) + +QT_END_NAMESPACE + +#endif // QNETCONMONITOR_P_H diff --git a/src/network/kernel/qnetconmonitor_stub.cpp b/src/network/kernel/qnetconmonitor_stub.cpp new file mode 100644 index 0000000000..7f3a0c44c6 --- /dev/null +++ b/src/network/kernel/qnetconmonitor_stub.cpp @@ -0,0 +1,141 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtNetwork module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qnetconmonitor_p.h" + +#include "private/qobject_p.h" + +QT_BEGIN_NAMESPACE + +Q_LOGGING_CATEGORY(lcNetMon, "qt.network.monitor"); + +// Note: this 'stub' version is never enabled (see QNetworkStatusMonitor::isEnabled below) +// and thus should never affect QNAM in any unusuall way. Having this 'stub' version is similar +// to building Qt with bearer management configured out. + +class QNetworkConnectionMonitorPrivate : public QObjectPrivate +{ +}; + +QNetworkConnectionMonitor::QNetworkConnectionMonitor() + : QObject(*new QNetworkConnectionMonitorPrivate) +{ +} + +QNetworkConnectionMonitor::QNetworkConnectionMonitor(const QHostAddress &local, const QHostAddress &remote) + : QObject(*new QNetworkConnectionMonitorPrivate) +{ + Q_UNUSED(local) + Q_UNUSED(remote) +} + +QNetworkConnectionMonitor::~QNetworkConnectionMonitor() +{ +} + +bool QNetworkConnectionMonitor::setTargets(const QHostAddress &local, const QHostAddress &remote) +{ + Q_UNUSED(local) + Q_UNUSED(remote) + + return false; +} + +bool QNetworkConnectionMonitor::startMonitoring() +{ + return false; +} + +bool QNetworkConnectionMonitor::isMonitoring() const +{ + return false; +} + +void QNetworkConnectionMonitor::stopMonitoring() +{ +} + +bool QNetworkConnectionMonitor::isReachable() +{ + return false; +} + +class QNetworkStatusMonitorPrivate : public QObjectPrivate +{ +}; + +QNetworkStatusMonitor::QNetworkStatusMonitor() + : QObject(*new QNetworkStatusMonitorPrivate) +{ +} + +QNetworkStatusMonitor::~QNetworkStatusMonitor() +{ +} + +bool QNetworkStatusMonitor::start() +{ + return false; +} + +void QNetworkStatusMonitor::stop() +{ +} + +bool QNetworkStatusMonitor::isMonitoring() const +{ + return false; +} + +bool QNetworkStatusMonitor::isNetworkAccesible() +{ + return false; +} + +bool QNetworkStatusMonitor::isEnabled() +{ + return false; +} + +void QNetworkStatusMonitor::reachabilityChanged(bool online) +{ + Q_UNUSED(online) +} + +QT_END_NAMESPACE -- cgit v1.2.3 From c940ca50ce0db76e12b06eb9cefd13c0876c0938 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Tue, 30 Apr 2019 11:55:55 +0200 Subject: Remove spurious class-name prefixes in its own methods Change-Id: I13093e02b251a084e468a50471cf1b9256555e40 Reviewed-by: Jesus Fernandez Reviewed-by: Thiago Macieira --- src/corelib/tools/qlocale_p.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/corelib/tools/qlocale_p.h b/src/corelib/tools/qlocale_p.h index 16ded7650c..15398ded32 100644 --- a/src/corelib/tools/qlocale_p.h +++ b/src/corelib/tools/qlocale_p.h @@ -359,9 +359,9 @@ public: QByteArray bcp47Name(char separator = '-') const; - inline QLatin1String languageCode() const { return QLocalePrivate::languageToCode(QLocale::Language(m_data->m_language_id)); } - inline QLatin1String scriptCode() const { return QLocalePrivate::scriptToCode(QLocale::Script(m_data->m_script_id)); } - inline QLatin1String countryCode() const { return QLocalePrivate::countryToCode(QLocale::Country(m_data->m_country_id)); } + inline QLatin1String languageCode() const { return languageToCode(QLocale::Language(m_data->m_language_id)); } + inline QLatin1String scriptCode() const { return scriptToCode(QLocale::Script(m_data->m_script_id)); } + inline QLatin1String countryCode() const { return countryToCode(QLocale::Country(m_data->m_country_id)); } static QLatin1String languageToCode(QLocale::Language language); static QLatin1String scriptToCode(QLocale::Script script); -- cgit v1.2.3 From 7a0d4b39daa1beed7070ceb43414eb55934f1266 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Tue, 30 Apr 2019 16:58:38 +0200 Subject: Doc-fix: mention FP_ZERO as a possible return of qFpClassify() This follows up on commit 84aea6c091d020a37c2b452a6f56ca27b3b2c7cb, in which I forgot to mention this possible return value. Change-Id: I109bed66bc0fd63d7ee289bfaea65b3d05c6560c Reviewed-by: Giuseppe D'Angelo Reviewed-by: Thiago Macieira --- src/corelib/global/qnumeric.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/corelib/global/qnumeric.cpp b/src/corelib/global/qnumeric.cpp index e6ba62f530..11440f40a4 100644 --- a/src/corelib/global/qnumeric.cpp +++ b/src/corelib/global/qnumeric.cpp @@ -110,6 +110,7 @@ Q_CORE_EXPORT double qInf() { return qt_inf(); } \list \li FP_NAN not a number \li FP_INFINITE infinities (positive or negative) + \li FP_ZERO zero (positive or negative) \li FP_NORMAL finite with a full mantissa \li FP_SUBNORMAL finite with a reduced mantissa \endlist -- cgit v1.2.3 From a2b38f64e6def1538b9d153ec4c6589fa9b6d3c0 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Tue, 30 Apr 2019 17:53:53 +0200 Subject: Remove handling of missing =delete and =default support Change-Id: I006dfd0b7cfa3bda5e5ab01bcefa851f031dfe0e Reviewed-by: Thiago Macieira --- src/corelib/global/qglobal.h | 6 +++--- src/corelib/kernel/qmetaobject.h | 2 +- src/corelib/kernel/qmetatype.h | 2 +- src/corelib/kernel/qvariant.h | 14 +++++++------- src/corelib/thread/qatomic_cxx11.h | 2 +- src/corelib/thread/qbasicatomic.h | 2 +- src/corelib/thread/qthread.h | 2 -- src/corelib/tools/qmap.h | 2 +- src/corelib/tools/qsharedpointer_impl.h | 12 ++++-------- src/corelib/tools/qstringbuilder.h | 4 ++-- src/gui/image/qiconengine.h | 2 +- src/widgets/kernel/qtooltip.h | 2 +- src/widgets/kernel/qwhatsthis.h | 2 +- src/xml/sax/qxml.h | 2 -- 14 files changed, 24 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index ceae0583ee..4817acb48f 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -422,8 +422,8 @@ typedef double qreal; operator to disable copying (the compiler gives an error message). */ #define Q_DISABLE_COPY(Class) \ - Class(const Class &) Q_DECL_EQ_DELETE;\ - Class &operator=(const Class &) Q_DECL_EQ_DELETE; + Class(const Class &) = delete;\ + Class &operator=(const Class &) = delete; #define Q_DISABLE_MOVE(Class) \ Class(Class &&) = delete; \ @@ -1021,7 +1021,7 @@ template Q_DECL_CONSTEXPR typename std::add_const::type &qAsConst(T &t) noexcept { return t; } // prevent rvalue arguments: template -void qAsConst(const T &&) Q_DECL_EQ_DELETE; +void qAsConst(const T &&) = delete; #ifndef QT_NO_FOREACH diff --git a/src/corelib/kernel/qmetaobject.h b/src/corelib/kernel/qmetaobject.h index 6c5f78d208..10b14a7e03 100644 --- a/src/corelib/kernel/qmetaobject.h +++ b/src/corelib/kernel/qmetaobject.h @@ -183,7 +183,7 @@ private: // signature() has been renamed to methodSignature() in Qt 5. // Warning, that function returns a QByteArray; check the life time if // you convert to char*. - char *signature(struct renamedInQt5_warning_checkTheLifeTime * = nullptr) Q_DECL_EQ_DELETE; + char *signature(struct renamedInQt5_warning_checkTheLifeTime * = nullptr) = delete; #endif static QMetaMethod fromSignalImpl(const QMetaObject *, void **); diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index a47fbfe28d..79ee5eec11 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -849,7 +849,7 @@ struct VariantData const uint flags; private: // copy constructor allowed to be implicit to silence level 4 warning from MSVC - VariantData &operator=(const VariantData &) Q_DECL_EQ_DELETE; + VariantData &operator=(const VariantData &) = delete; }; template diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index 2247c7adc8..924cfa1e1a 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -483,27 +483,27 @@ public: private: // force compile error, prevent QVariant(bool) to be called - inline QVariant(void *) Q_DECL_EQ_DELETE; + inline QVariant(void *) = delete; // QVariant::Type is marked as \obsolete, but we don't want to // provide a constructor from its intended replacement, // QMetaType::Type, instead, because the idea behind these // constructors is flawed in the first place. But we also don't // want QVariant(QMetaType::String) to compile and falsely be an // int variant, so delete this constructor: - QVariant(QMetaType::Type) Q_DECL_EQ_DELETE; + QVariant(QMetaType::Type) = delete; // These constructors don't create QVariants of the type associcated // with the enum, as expected, but they would create a QVariant of // type int with the value of the enum value. // Use QVariant v = QColor(Qt::red) instead of QVariant v = Qt::red for // example. - QVariant(Qt::GlobalColor) Q_DECL_EQ_DELETE; - QVariant(Qt::BrushStyle) Q_DECL_EQ_DELETE; - QVariant(Qt::PenStyle) Q_DECL_EQ_DELETE; - QVariant(Qt::CursorShape) Q_DECL_EQ_DELETE; + QVariant(Qt::GlobalColor) = delete; + QVariant(Qt::BrushStyle) = delete; + QVariant(Qt::PenStyle) = delete; + QVariant(Qt::CursorShape) = delete; #ifdef QT_NO_CAST_FROM_ASCII // force compile error when implicit conversion is not wanted - inline QVariant(const char *) Q_DECL_EQ_DELETE; + inline QVariant(const char *) = delete; #endif public: typedef Private DataPtr; diff --git a/src/corelib/thread/qatomic_cxx11.h b/src/corelib/thread/qatomic_cxx11.h index 32d27734fc..2851bae73e 100644 --- a/src/corelib/thread/qatomic_cxx11.h +++ b/src/corelib/thread/qatomic_cxx11.h @@ -462,7 +462,7 @@ template struct QAtomicOps } }; -#if defined(Q_COMPILER_CONSTEXPR) && defined(Q_COMPILER_DEFAULT_MEMBERS) && defined(Q_COMPILER_DELETE_MEMBERS) +#if defined(Q_COMPILER_CONSTEXPR) # define Q_BASIC_ATOMIC_INITIALIZER(a) { a } #else # define Q_BASIC_ATOMIC_INITIALIZER(a) { ATOMIC_VAR_INIT(a) } diff --git a/src/corelib/thread/qbasicatomic.h b/src/corelib/thread/qbasicatomic.h index 4c3c1fc01f..7d2e06a499 100644 --- a/src/corelib/thread/qbasicatomic.h +++ b/src/corelib/thread/qbasicatomic.h @@ -75,7 +75,7 @@ QT_END_NAMESPACE // New atomics -#if defined(Q_COMPILER_CONSTEXPR) && defined(Q_COMPILER_DEFAULT_MEMBERS) && defined(Q_COMPILER_DELETE_MEMBERS) +#if defined(Q_COMPILER_CONSTEXPR) # if defined(Q_CC_CLANG) && Q_CC_CLANG < 303 /* Do not define QT_BASIC_ATOMIC_HAS_CONSTRUCTORS for Clang before version 3.3. diff --git a/src/corelib/thread/qthread.h b/src/corelib/thread/qthread.h index 8e92d75401..c7a6dc8f1a 100644 --- a/src/corelib/thread/qthread.h +++ b/src/corelib/thread/qthread.h @@ -209,7 +209,6 @@ struct Callable { } -#if defined(Q_COMPILER_DEFAULT_MEMBERS) && defined(Q_COMPILER_DELETE_MEMBERS) // Apply the same semantics of a lambda closure type w.r.t. the special // member functions, if possible: delete the copy assignment operator, // bring back all the others as per the RO5 (cf. §8.1.5.1/11 [expr.prim.lambda.closure]) @@ -218,7 +217,6 @@ struct Callable Callable(Callable &&) = default; Callable &operator=(const Callable &) = delete; Callable &operator=(Callable &&) = default; -#endif void operator()() { diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h index 3b8aad9a33..2d01a75a42 100644 --- a/src/corelib/tools/qmap.h +++ b/src/corelib/tools/qmap.h @@ -142,7 +142,7 @@ private: rightNode()->destroySubTree(); } - QMapNode() Q_DECL_EQ_DELETE; + QMapNode() = delete; Q_DISABLE_COPY(QMapNode) }; diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h index 9fb452da6b..c219d310dc 100644 --- a/src/corelib/tools/qsharedpointer_impl.h +++ b/src/corelib/tools/qsharedpointer_impl.h @@ -235,8 +235,8 @@ namespace QtSharedPointer { } private: // prevent construction - ExternalRefCountWithCustomDeleter() Q_DECL_EQ_DELETE; - ~ExternalRefCountWithCustomDeleter() Q_DECL_EQ_DELETE; + ExternalRefCountWithCustomDeleter() = delete; + ~ExternalRefCountWithCustomDeleter() = delete; Q_DISABLE_COPY(ExternalRefCountWithCustomDeleter) }; @@ -280,8 +280,8 @@ namespace QtSharedPointer { private: // prevent construction - ExternalRefCountWithContiguousData() Q_DECL_EQ_DELETE; - ~ExternalRefCountWithContiguousData() Q_DECL_EQ_DELETE; + ExternalRefCountWithContiguousData() = delete; + ~ExternalRefCountWithContiguousData() = delete; Q_DISABLE_COPY(ExternalRefCountWithContiguousData) }; @@ -705,11 +705,7 @@ template class QEnableSharedFromThis { protected: -#ifdef Q_COMPILER_DEFAULT_MEMBERS QEnableSharedFromThis() = default; -#else - Q_DECL_CONSTEXPR QEnableSharedFromThis() {} -#endif QEnableSharedFromThis(const QEnableSharedFromThis &) {} QEnableSharedFromThis &operator=(const QEnableSharedFromThis &) { return *this; } diff --git a/src/corelib/tools/qstringbuilder.h b/src/corelib/tools/qstringbuilder.h index 79ed10c7a8..b3cf2f695e 100644 --- a/src/corelib/tools/qstringbuilder.h +++ b/src/corelib/tools/qstringbuilder.h @@ -150,7 +150,7 @@ class QStringBuilder : public QStringBuilderBase @@ -167,7 +167,7 @@ class QStringBuilder : public QStringBuilderBase Date: Wed, 24 Apr 2019 18:03:59 +0200 Subject: Increase entityCharacterLimit to 4096 The previous fix to decrease the limit to 1024 breaks the parsing for some files. The limit is arbitrary, so increasing it to 4096, which is what some linux distros have been working with. Change-Id: I131f15278aa99c3f91db2e1ec2d14156ceed4775 Fixes: QTBUG-35459 Reviewed-by: Mitch Curtis Reviewed-by: David Faure --- src/xml/sax/qxml_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/xml/sax/qxml_p.h b/src/xml/sax/qxml_p.h index 98dc2aea0c..eb6135db04 100644 --- a/src/xml/sax/qxml_p.h +++ b/src/xml/sax/qxml_p.h @@ -229,7 +229,7 @@ private: // for the DTD currently being parsed. static const int dtdRecursionLimit = 2; // The maximum amount of characters an entity value may contain, after expansion. - static const int entityCharacterLimit = 1024; + static const int entityCharacterLimit = 4096; const QString &string(); void stringClear(); -- cgit v1.2.3 From 343528841e72adf36a37d9afd7260e260a9342eb Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 30 Apr 2019 12:51:36 +0200 Subject: Prefix textstream operators with Qt:: As the non prefixed variants are deprecated Change-Id: I2ba09d71b9cea5203b54297a3f2332e6d44fedcf Reviewed-by: Allan Sandfeld Jensen --- src/3rdparty/harfbuzz/src/harfbuzz-indic.cpp | 2 +- src/3rdparty/harfbuzz/tests/shaping/main.cpp | 4 +- src/corelib/doc/snippets/code/doc_src_qset.cpp | 4 +- .../snippets/code/src_corelib_io_qtextstream.cpp | 4 +- .../snippets/code/src_corelib_thread_qfuture.cpp | 2 +- .../snippets/code/src_corelib_tools_qbytearray.cpp | 6 +- .../doc/snippets/code/src_corelib_tools_qhash.cpp | 28 +- .../code/src_corelib_tools_qlinkedlist.cpp | 8 +- .../snippets/code/src_corelib_tools_qlistdata.cpp | 8 +- .../doc/snippets/code/src_corelib_tools_qmap.cpp | 30 +- .../doc/snippets/code/src_corelib_tools_qqueue.cpp | 2 +- .../code/src_corelib_tools_qstringiterator.cpp | 6 +- .../snippets/code/src_corelib_tools_qvector.cpp | 4 +- src/corelib/doc/snippets/qstack/main.cpp | 2 +- src/corelib/doc/snippets/qstringlist/main.cpp | 6 +- src/corelib/io/qdebug.cpp | 6 +- src/corelib/io/qdebug.h | 2 +- src/corelib/io/qfilesystemwatcher_inotify.cpp | 2 +- src/corelib/io/qfilesystemwatcher_win.cpp | 4 +- src/corelib/kernel/qeventdispatcher_cf.mm | 2 +- src/corelib/kernel/qtimerinfo_unix.cpp | 8 +- src/corelib/plugin/qfactoryloader.cpp | 2 +- src/corelib/serialization/qcborvalue.cpp | 2 +- src/corelib/serialization/qjsonparser.cpp | 2 +- src/corelib/serialization/qtextstream.cpp | 4 +- src/corelib/tools/qstring.cpp | 6 +- src/gui/accessible/qaccessible.cpp | 4 +- src/gui/doc/snippets/textdocumentendsnippet.cpp | 2 +- src/gui/image/qicon.cpp | 2 +- src/gui/image/qpixmap.cpp | 2 +- src/gui/image/qxpmhandler.cpp | 10 +- src/gui/kernel/qevent.cpp | 10 +- src/gui/kernel/qpalette.cpp | 4 +- src/gui/kernel/qscreen.cpp | 2 +- src/gui/kernel/qwindow.cpp | 4 +- src/gui/math3d/qgenericmatrix.h | 4 +- src/gui/math3d/qmatrix4x4.cpp | 10 +- src/gui/opengl/qopengl.cpp | 2 +- src/gui/painting/qblendfunctions_p.h | 16 +- src/gui/painting/qpaintengine_raster.cpp | 4 +- src/gui/painting/qpaintengineex.cpp | 2 +- src/gui/painting/qpainterpath.cpp | 4 +- src/gui/text/qfontengine.cpp | 2 +- src/gui/text/qfontengine_qpf2.cpp | 6 +- src/gui/text/qtextengine.cpp | 8 +- .../freetype/qfreetypefontdatabase.cpp | 2 +- src/plugins/bearer/nla/qnlaengine.cpp | 30 +- src/plugins/platforms/android/androidjnimain.cpp | 2 +- src/plugins/platforms/cocoa/qcocoaaccessibility.mm | 2 +- src/plugins/platforms/cocoa/qnsview_gestures.mm | 10 +- src/plugins/platforms/cocoa/qnsview_touch.mm | 8 +- .../eglfs_kms/qeglfskmsgbmscreen.cpp | 2 +- src/plugins/platforms/windows/qwindowscontext.cpp | 4 +- .../platforms/windows/qwindowsdialoghelpers.cpp | 6 +- src/plugins/platforms/windows/qwindowsdrag.cpp | 8 +- .../platforms/windows/qwindowsglcontext.cpp | 8 +- .../platforms/windows/qwindowsinputcontext.cpp | 4 +- .../platforms/windows/qwindowsintegration.cpp | 6 +- .../platforms/windows/qwindowskeymapper.cpp | 6 +- src/plugins/platforms/windows/qwindowsmenu.cpp | 6 +- .../platforms/windows/qwindowsmousehandler.cpp | 4 +- src/plugins/platforms/windows/qwindowsole.cpp | 6 +- .../platforms/windows/qwindowsopengltester.cpp | 8 +- .../platforms/windows/qwindowspointerhandler.cpp | 20 +- .../platforms/windows/qwindowstabletsupport.cpp | 12 +- src/plugins/platforms/windows/qwindowswindow.cpp | 6 +- src/plugins/platforms/xcb/qxcbnativeinterface.cpp | 8 +- src/plugins/platforms/xcb/qxcbscreen.cpp | 6 +- src/sql/doc/snippets/sqldatabase/sqldatabase.cpp | 4 +- src/sql/kernel/qsqlrecord.cpp | 2 +- src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp | 330 ++++++++++----------- src/tools/qlalr/cppgenerator.cpp | 188 ++++++------ src/tools/qlalr/dotgraph.cpp | 22 +- src/tools/qlalr/lalr.cpp | 20 +- src/tools/qlalr/lalr.g | 12 +- src/tools/qlalr/main.cpp | 24 +- src/tools/qlalr/parsetable.cpp | 26 +- src/tools/qlalr/recognizer.cpp | 12 +- src/tools/uic/cpp/cppwriteinitialization.cpp | 10 +- src/widgets/itemviews/qtableview.cpp | 8 +- src/widgets/kernel/qwidget.cpp | 4 +- src/widgets/widgets/qsplitter.cpp | 2 +- src/xml/doc/snippets/code/src_xml_dom_qdom.cpp | 8 +- src/xml/dom/qdom.cpp | 18 +- 84 files changed, 559 insertions(+), 559 deletions(-) (limited to 'src') diff --git a/src/3rdparty/harfbuzz/src/harfbuzz-indic.cpp b/src/3rdparty/harfbuzz/src/harfbuzz-indic.cpp index 704ea9774a..de3bcb2bbf 100644 --- a/src/3rdparty/harfbuzz/src/harfbuzz-indic.cpp +++ b/src/3rdparty/harfbuzz/src/harfbuzz-indic.cpp @@ -1471,7 +1471,7 @@ static bool indic_shape_syllable(HB_Bool openType, HB_ShaperItem *item, bool inv while (finalOrder[toMove].form && fixed < len-1) { IDEBUG(" fixed = %d, toMove=%d, moving form %d with pos %d", fixed, toMove, finalOrder[toMove].form, finalOrder[toMove].position); for (i = fixed; i < len; i++) { -// IDEBUG() << " i=" << i << "uc=" << hex << uc[i] << "form=" << form(uc[i]) +// IDEBUG() << " i=" << i << "uc=" << Qt::hex << uc[i] << "form=" << form(uc[i]) // << "position=" << position[i]; if (form(uc[i]) == finalOrder[toMove].form && position[i] == finalOrder[toMove].position) { diff --git a/src/3rdparty/harfbuzz/tests/shaping/main.cpp b/src/3rdparty/harfbuzz/tests/shaping/main.cpp index 10818c565c..16f469029b 100644 --- a/src/3rdparty/harfbuzz/tests/shaping/main.cpp +++ b/src/3rdparty/harfbuzz/tests/shaping/main.cpp @@ -370,7 +370,7 @@ void tst_QScriptEngine::greek() QString str; str.append(uc); if (str.normalized(QString::NormalizationForm_D).normalized(QString::NormalizationForm_C) != str) { - //qDebug() << "skipping" << hex << uc; + //qDebug() << "skipping" << Qt::hex << uc; continue; } if (uc == 0x1fc1 || uc == 0x1fed) @@ -389,7 +389,7 @@ void tst_QScriptEngine::greek() QString str; str.append(uc); if (str.normalized(QString::NormalizationForm_D).normalized(QString::NormalizationForm_C) != str) { - //qDebug() << "skipping" << hex << uc; + //qDebug() << "skipping" << Qt::hex << uc; continue; } if (uc == 0x1fc1 || uc == 0x1fed) diff --git a/src/corelib/doc/snippets/code/doc_src_qset.cpp b/src/corelib/doc/snippets/code/doc_src_qset.cpp index 4cd84d7330..7f7cec8b45 100644 --- a/src/corelib/doc/snippets/code/doc_src_qset.cpp +++ b/src/corelib/doc/snippets/code/doc_src_qset.cpp @@ -133,7 +133,7 @@ QSet set; ... QSet::iterator it = qFind(set.begin(), set.end(), "Jeanette"); if (it != set.end()) - cout << "Found Jeanette" << endl; + cout << "Found Jeanette" << Qt::endl; //! [10] @@ -152,7 +152,7 @@ QSet set; ... QSet::iterator it = qFind(set.begin(), set.end(), "Jeanette"); if (it != set.constEnd()) - cout << "Found Jeanette" << endl; + cout << "Found Jeanette" << Qt::endl; //! [12] diff --git a/src/corelib/doc/snippets/code/src_corelib_io_qtextstream.cpp b/src/corelib/doc/snippets/code/src_corelib_io_qtextstream.cpp index 625c1cf9bc..c30f13df5a 100644 --- a/src/corelib/doc/snippets/code/src_corelib_io_qtextstream.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_io_qtextstream.cpp @@ -124,12 +124,12 @@ in >> ch1 >> ch2 >> ch3; //! [8] QTextStream out(stdout); -out << "Qt rocks!" << endl; +out << "Qt rocks!" << Qt::endl; //! [8] //! [9] -stream << '\n' << flush; +stream << '\n' << Qt::flush; //! [9] diff --git a/src/corelib/doc/snippets/code/src_corelib_thread_qfuture.cpp b/src/corelib/doc/snippets/code/src_corelib_thread_qfuture.cpp index 382b08fdb7..dfa9b670e7 100644 --- a/src/corelib/doc/snippets/code/src_corelib_thread_qfuture.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_thread_qfuture.cpp @@ -53,7 +53,7 @@ QFuture future = ...; QFuture::const_iterator i; for (i = future.constBegin(); i != future.constEnd(); ++i) - cout << *i << endl; + cout << *i << Qt::endl; //! [0] diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp index 32fccbefbf..ec63e64fe9 100644 --- a/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp @@ -71,7 +71,7 @@ ba[4] = 0xca; //! [2] for (int i = 0; i < ba.size(); ++i) { if (ba.at(i) >= 'a' && ba.at(i) <= 'f') - cout << "Found character in range [a-f]" << endl; + cout << "Found character in range [a-f]" << Qt::endl; } //! [2] @@ -88,7 +88,7 @@ x.replace(5, 3, "&"); // x == "rock & roll" QByteArray ba("We must be bold, very bold"); int j = 0; while ((j = ba.indexOf("", j)) != -1) { - cout << "Found tag at index position " << j << endl; + cout << "Found tag at index position " << j << Qt::endl; ++j; } //! [4] @@ -126,7 +126,7 @@ QByteArray("abc").isEmpty(); // returns false QByteArray ba("Hello world"); char *data = ba.data(); while (*data) { - cout << "[" << *data << "]" << endl; + cout << "[" << *data << "]" << Qt::endl; ++data; } //! [8] diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp index a3d2dd7f9e..9813cc98d5 100644 --- a/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp @@ -89,7 +89,7 @@ QHash hash; ... for (int i = 0; i < 1000; ++i) { if (hash[i] == okButton) - cout << "Found button at index " << i << endl; + cout << "Found button at index " << i << Qt::endl; } //! [6] @@ -98,7 +98,7 @@ for (int i = 0; i < 1000; ++i) { QHashIterator i(hash); while (i.hasNext()) { i.next(); - cout << i.key() << ": " << i.value() << endl; + cout << i.key() << ": " << i.value() << Qt::endl; } //! [7] @@ -106,7 +106,7 @@ while (i.hasNext()) { //! [8] QHash::const_iterator i = hash.constBegin(); while (i != hash.constEnd()) { - cout << i.key() << ": " << i.value() << endl; + cout << i.key() << ": " << i.value() << Qt::endl; ++i; } //! [8] @@ -122,14 +122,14 @@ hash.insert("plenty", 2000); //! [10] QList values = hash.values("plenty"); for (int i = 0; i < values.size(); ++i) - cout << values.at(i) << endl; + cout << values.at(i) << Qt::endl; //! [10] //! [11] QHash::iterator i = hash.find("plenty"); while (i != hash.end() && i.key() == "plenty") { - cout << i.value() << endl; + cout << i.value() << Qt::endl; ++i; } //! [11] @@ -139,7 +139,7 @@ while (i != hash.end() && i.key() == "plenty") { QHash hash; ... foreach (int value, hash) - cout << value << endl; + cout << value << Qt::endl; //! [12] @@ -201,7 +201,7 @@ QHash hash; ... QHash::const_iterator i = hash.find("HDR"); while (i != hash.end() && i.key() == "HDR") { - cout << i.value() << endl; + cout << i.value() << Qt::endl; ++i; } //! [16] @@ -216,7 +216,7 @@ hash.insert("December", 12); QHash::iterator i; for (i = hash.begin(); i != hash.end(); ++i) - cout << i.key() << ": " << i.value() << endl; + cout << i.key() << ": " << i.value() << Qt::endl; //! [17] @@ -274,7 +274,7 @@ hash.insert("December", 12); QHash::const_iterator i; for (i = hash.constBegin(); i != hash.constEnd(); ++i) - cout << i.key() << ": " << i.value() << endl; + cout << i.key() << ": " << i.value() << Qt::endl; //! [23] @@ -296,23 +296,23 @@ hash3 = hash1 + hash2; //! [25] QList values = hash.values("plenty"); for (int i = 0; i < values.size(); ++i) - cout << values.at(i) << endl; + cout << values.at(i) << Qt::endl; //! [25] //! [26] QMultiHash::iterator i = hash.find("plenty"); while (i != hash.end() && i.key() == "plenty") { - cout << i.value() << endl; + cout << i.value() << Qt::endl; ++i; } //! [26] //! [27] for (QHash::const_iterator it = hash.cbegin(), end = hash.cend(); it != end; ++it) { - cout << "The key: " << it.key() << endl - cout << "The value: " << it.value() << endl; - cout << "Also the value: " << (*it) << endl; + cout << "The key: " << it.key() << Qt::endl + cout << "The value: " << it.value() << Qt::endl; + cout << "Also the value: " << (*it) << Qt::endl; } //! [27] diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qlinkedlist.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qlinkedlist.cpp index 7f743bbd25..e0d3c71dc5 100644 --- a/src/corelib/doc/snippets/code/src_corelib_tools_qlinkedlist.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_tools_qlinkedlist.cpp @@ -112,7 +112,7 @@ list.append("December"); QLinkedList::iterator i; for (i = list.begin(); i != list.end(); ++i) - cout << *i << endl; + cout << *i << Qt::endl; //! [7] @@ -122,7 +122,7 @@ QLinkedList list; QLinkedList::iterator it = qFind(list.begin(), list.end(), "Joel"); if (it != list.end()) - cout << "Found Joel" << endl; + cout << "Found Joel" << Qt::endl; //! [8] @@ -182,7 +182,7 @@ list.append("December"); QLinkedList::const_iterator i; for (i = list.constBegin(); i != list.constEnd(); ++i) - cout << *i << endl; + cout << *i << Qt::endl; //! [14] @@ -192,7 +192,7 @@ QLinkedList list; QLinkedList::iterator it = qFind(list.constBegin(), list.constEnd(), "Joel"); if (it != list.constEnd()) - cout << "Found Joel" << endl; + cout << "Found Joel" << Qt::endl; //! [15] diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qlistdata.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qlistdata.cpp index 0e746cd6e6..a24e599f2f 100644 --- a/src/corelib/doc/snippets/code/src_corelib_tools_qlistdata.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_tools_qlistdata.cpp @@ -73,7 +73,7 @@ if (list[0] == "Bob") //! [3] for (int i = 0; i < list.size(); ++i) { if (list.at(i) == "Jane") - cout << "Found Jane at position " << i << endl; + cout << "Found Jane at position " << i << Qt::endl; } //! [3] @@ -89,7 +89,7 @@ while (!list.isEmpty()) //! [5] int i = list.indexOf("Jane"); if (i != -1) - cout << "First occurrence of Jane is at position " << i << endl; + cout << "First occurrence of Jane is at position " << i << Qt::endl; //! [5] @@ -180,7 +180,7 @@ list.append("December"); QList::iterator i; for (i = list.begin(); i != list.end(); ++i) - cout << *i << endl; + cout << *i << Qt::endl; //! [15] @@ -213,7 +213,7 @@ list.append("December"); QList::const_iterator i; for (i = list.constBegin(); i != list.constEnd(); ++i) - cout << *i << endl; + cout << *i << Qt::endl; //! [19] diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qmap.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qmap.cpp index bd59758f71..506022f082 100644 --- a/src/corelib/doc/snippets/code/src_corelib_tools_qmap.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_tools_qmap.cpp @@ -89,7 +89,7 @@ QMap map; ... for (int i = 0; i < 1000; ++i) { if (map[i] == okButton) - cout << "Found button at index " << i << endl; + cout << "Found button at index " << i << Qt::endl; } //! [6] @@ -98,7 +98,7 @@ for (int i = 0; i < 1000; ++i) { QMapIterator i(map); while (i.hasNext()) { i.next(); - cout << i.key() << ": " << i.value() << endl; + cout << i.key() << ": " << i.value() << Qt::endl; } //! [7] @@ -106,7 +106,7 @@ while (i.hasNext()) { //! [8] QMap::const_iterator i = map.constBegin(); while (i != map.constEnd()) { - cout << i.key() << ": " << i.value() << endl; + cout << i.key() << ": " << i.value() << Qt::endl; ++i; } //! [8] @@ -122,14 +122,14 @@ map.insert("plenty", 2000); //! [10] QList values = map.values("plenty"); for (int i = 0; i < values.size(); ++i) - cout << values.at(i) << endl; + cout << values.at(i) << Qt::endl; //! [10] //! [11] QMap::iterator i = map.find("plenty"); while (i != map.end() && i.key() == "plenty") { - cout << i.value() << endl; + cout << i.value() << Qt::endl; ++i; } //! [11] @@ -139,7 +139,7 @@ while (i != map.end() && i.key() == "plenty") { QMap map; ... foreach (int value, map) - cout << value << endl; + cout << value << Qt::endl; //! [12] @@ -175,7 +175,7 @@ QMap map; ... QMap::const_iterator i = map.find("HDR"); while (i != map.end() && i.key() == "HDR") { - cout << i.value() << endl; + cout << i.value() << Qt::endl; ++i; } //! [14] @@ -201,7 +201,7 @@ QMap map; QMap::const_iterator i = map.lowerBound("HDR"); QMap::const_iterator upperBound = map.upperBound("HDR"); while (i != upperBound) { - cout << i.value() << endl; + cout << i.value() << Qt::endl; ++i; } //! [16] @@ -230,7 +230,7 @@ map.insert("December", 12); QMap::iterator i; for (i = map.begin(); i != map.end(); ++i) - cout << i.key() << ": " << i.value() << endl; + cout << i.key() << ": " << i.value() << Qt::endl; //! [18] @@ -288,7 +288,7 @@ map.insert("December", 12); QMap::const_iterator i; for (i = map.constBegin(); i != map.constEnd(); ++i) - cout << i.key() << ": " << i.value() << endl; + cout << i.key() << ": " << i.value() << Qt::endl; //! [24] @@ -310,23 +310,23 @@ map3 = map1 + map2; //! [26] QList values = map.values("plenty"); for (int i = 0; i < values.size(); ++i) - cout << values.at(i) << endl; + cout << values.at(i) << Qt::endl; //! [26] //! [27] QMultiMap::iterator i = map.find("plenty"); while (i != map.end() && i.key() == "plenty") { - cout << i.value() << endl; + cout << i.value() << Qt::endl; ++i; } //! [27] //! [keyiterator1] for (QMap::const_iterator it = map.cbegin(), end = map.cend(); it != end; ++it) { - cout << "The key: " << it.key() << endl - cout << "The value: " << it.value() << endl; - cout << "Also the value: " << (*it) << endl; + cout << "The key: " << it.key() << Qt::endl + cout << "The value: " << it.value() << Qt::endl; + cout << "Also the value: " << (*it) << Qt::endl; } //! [keyiterator1] diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qqueue.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qqueue.cpp index b74ac31933..6046c73b0f 100644 --- a/src/corelib/doc/snippets/code/src_corelib_tools_qqueue.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_tools_qqueue.cpp @@ -54,5 +54,5 @@ queue.enqueue(1); queue.enqueue(2); queue.enqueue(3); while (!queue.isEmpty()) - cout << queue.dequeue() << endl; + cout << queue.dequeue() << Qt::endl; //! [0] diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qstringiterator.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qstringiterator.cpp index 7a2b4812ef..eb09fb99e2 100644 --- a/src/corelib/doc/snippets/code/src_corelib_tools_qstringiterator.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_tools_qstringiterator.cpp @@ -72,9 +72,9 @@ while (i.hasNext()) { //! [2] QStringIterator i(u"𝄞 is the G clef"); -qDebug() << hex << i.next(); // will print 1d11e (U+1D11E, MUSICAL SYMBOL G CLEF) -qDebug() << hex << i.next(); // will print 20 (U+0020, SPACE) -qDebug() << hex << i.next(); // will print 69 (U+0069, LATIN SMALL LETTER I) +qDebug() << Qt::hex << i.next(); // will print 1d11e (U+1D11E, MUSICAL SYMBOL G CLEF) +qDebug() << Qt::hex << i.next(); // will print 20 (U+0020, SPACE) +qDebug() << Qt::hex << i.next(); // will print 69 (U+0069, LATIN SMALL LETTER I) //! [2] } diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qvector.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qvector.cpp index 1f2af4a408..a05233049f 100644 --- a/src/corelib/doc/snippets/code/src_corelib_tools_qvector.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_tools_qvector.cpp @@ -73,7 +73,7 @@ if (vector[0] == "Liz") //! [4] for (int i = 0; i < vector.size(); ++i) { if (vector.at(i) == "Alfonso") - cout << "Found Alfonso at position " << i << endl; + cout << "Found Alfonso at position " << i << Qt::endl; } //! [4] @@ -81,7 +81,7 @@ for (int i = 0; i < vector.size(); ++i) { //! [5] int i = vector.indexOf("Harumi"); if (i != -1) - cout << "First occurrence of Harumi is at position " << i << endl; + cout << "First occurrence of Harumi is at position " << i << Qt::endl; //! [5] diff --git a/src/corelib/doc/snippets/qstack/main.cpp b/src/corelib/doc/snippets/qstack/main.cpp index af6b960e57..66823bcb59 100644 --- a/src/corelib/doc/snippets/qstack/main.cpp +++ b/src/corelib/doc/snippets/qstack/main.cpp @@ -60,6 +60,6 @@ int main(int argc, char *argv[]) stack.push(2); stack.push(3); while (!stack.isEmpty()) - cout << stack.pop() << endl; + cout << stack.pop() << Qt::endl; //! [0] } diff --git a/src/corelib/doc/snippets/qstringlist/main.cpp b/src/corelib/doc/snippets/qstringlist/main.cpp index 55c60650fe..80788ccd76 100644 --- a/src/corelib/doc/snippets/qstringlist/main.cpp +++ b/src/corelib/doc/snippets/qstringlist/main.cpp @@ -71,20 +71,20 @@ Widget::Widget(QWidget *parent) //! [1] for (int i = 0; i < fonts.size(); ++i) - cout << fonts.at(i).toLocal8Bit().constData() << endl; + cout << fonts.at(i).toLocal8Bit().constData() << Qt::endl; //! [1] //! [2] QStringListIterator javaStyleIterator(fonts); while (javaStyleIterator.hasNext()) - cout << javaStyleIterator.next().toLocal8Bit().constData() << endl; + cout << javaStyleIterator.next().toLocal8Bit().constData() << Qt::endl; //! [2] //! [3] QStringList::const_iterator constIterator; for (constIterator = fonts.constBegin(); constIterator != fonts.constEnd(); ++constIterator) - cout << (*constIterator).toLocal8Bit().constData() << endl; + cout << (*constIterator).toLocal8Bit().constData() << Qt::endl; //! [3] //! [4] diff --git a/src/corelib/io/qdebug.cpp b/src/corelib/io/qdebug.cpp index 15c5e0ce96..6dc12cd83f 100644 --- a/src/corelib/io/qdebug.cpp +++ b/src/corelib/io/qdebug.cpp @@ -166,7 +166,7 @@ void QDebug::putUcs4(uint ucs4) { maybeQuote('\''); if (ucs4 < 0x20) { - stream->ts << "\\x" << hex << ucs4 << reset; + stream->ts << "\\x" << Qt::hex << ucs4 << Qt::reset; } else if (ucs4 < 0x80) { stream->ts << char(ucs4); } else { @@ -174,7 +174,7 @@ void QDebug::putUcs4(uint ucs4) stream->ts << "\\u" << qSetFieldWidth(4); else stream->ts << "\\U" << qSetFieldWidth(8); - stream->ts << hex << qSetPadChar(QLatin1Char('0')) << ucs4 << reset; + stream->ts << Qt::hex << qSetPadChar(QLatin1Char('0')) << ucs4 << Qt::reset; } maybeQuote('\''); } @@ -834,7 +834,7 @@ QDebug &QDebug::resetFormat() that QDebugStateSaver stores for the duration of the current block. The settings of the internal QTextStream are also saved and restored, - so that using << hex in a QDebug operator doesn't affect other QDebug + so that using << Qt::hex in a QDebug operator doesn't affect other QDebug operators. \since 5.1 diff --git a/src/corelib/io/qdebug.h b/src/corelib/io/qdebug.h index f9dc4203db..889fb6b571 100644 --- a/src/corelib/io/qdebug.h +++ b/src/corelib/io/qdebug.h @@ -350,7 +350,7 @@ void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, Int value) { const QDebugStateSaver saver(debug); debug.resetFormat(); - debug.nospace() << "QFlags(" << hex << showbase; + debug.nospace() << "QFlags(" << Qt::hex << Qt::showbase; bool needSeparator = false; for (uint i = 0; i < sizeofT * 8; ++i) { if (value & (Int(1) << i)) { diff --git a/src/corelib/io/qfilesystemwatcher_inotify.cpp b/src/corelib/io/qfilesystemwatcher_inotify.cpp index a5e629b646..9d008947ba 100644 --- a/src/corelib/io/qfilesystemwatcher_inotify.cpp +++ b/src/corelib/io/qfilesystemwatcher_inotify.cpp @@ -388,7 +388,7 @@ void QInotifyFileSystemWatcherEngine::readFromInotify() const inotify_event &event = **it; ++it; - // qDebug() << "inotify event, wd" << event.wd << "mask" << hex << event.mask; + // qDebug() << "inotify event, wd" << event.wd << "mask" << Qt::hex << event.mask; int id = event.wd; QString path = getPathFromID(id); diff --git a/src/corelib/io/qfilesystemwatcher_win.cpp b/src/corelib/io/qfilesystemwatcher_win.cpp index 7f4f9d345b..eb626fd541 100644 --- a/src/corelib/io/qfilesystemwatcher_win.cpp +++ b/src/corelib/io/qfilesystemwatcher_win.cpp @@ -79,7 +79,7 @@ static Qt::HANDLE createChangeNotification(const QString &path, uint flags) nativePath.append(QLatin1Char('\\')); const HANDLE result = FindFirstChangeNotification(reinterpret_cast(nativePath.utf16()), FALSE, flags); - DEBUG() << __FUNCTION__ << nativePath << hex <" << flags; const Qt::HANDLE fileHandle = createChangeNotification(absolutePath, flags); if (fileHandle != INVALID_HANDLE_VALUE) { diff --git a/src/corelib/kernel/qeventdispatcher_cf.mm b/src/corelib/kernel/qeventdispatcher_cf.mm index b7b379e2c1..33c231987f 100644 --- a/src/corelib/kernel/qeventdispatcher_cf.mm +++ b/src/corelib/kernel/qeventdispatcher_cf.mm @@ -190,7 +190,7 @@ Q_ENUM_PRINTER(Result); QDebug operator<<(QDebug s, timespec tv) { - s << tv.tv_sec << "." << qSetFieldWidth(9) << qSetPadChar(QChar(48)) << tv.tv_nsec << reset; + s << tv.tv_sec << "." << qSetFieldWidth(9) << qSetPadChar(QChar(48)) << tv.tv_nsec << Qt::reset; return s; } diff --git a/src/corelib/kernel/qtimerinfo_unix.cpp b/src/corelib/kernel/qtimerinfo_unix.cpp index c3b8c86063..39010c19cb 100644 --- a/src/corelib/kernel/qtimerinfo_unix.cpp +++ b/src/corelib/kernel/qtimerinfo_unix.cpp @@ -215,7 +215,7 @@ static timespec roundToMillisecond(timespec val) QDebug operator<<(QDebug s, timeval tv) { QDebugStateSaver saver(s); - s.nospace() << tv.tv_sec << "." << qSetFieldWidth(6) << qSetPadChar(QChar(48)) << tv.tv_usec << reset; + s.nospace() << tv.tv_sec << "." << qSetFieldWidth(6) << qSetPadChar(QChar(48)) << tv.tv_usec << Qt::reset; return s; } QDebug operator<<(QDebug s, Qt::TimerType t) @@ -373,7 +373,7 @@ static void calculateNextTimeout(QTimerInfo *t, timespec currentTime) #ifdef QTIMERINFO_DEBUG if (t->timerType != Qt::PreciseTimer) - qDebug() << "timer" << t->timerType << hex << t->id << dec << "interval" << t->interval + qDebug() << "timer" << t->timerType << Qt::hex << t->id << Qt::dec << "interval" << t->interval << "originally expected at" << t->expected << "will fire at" << t->timeout << "or" << (t->timeout - t->expected) << "s late"; #endif @@ -500,7 +500,7 @@ void QTimerInfoList::registerTimer(int timerId, int interval, Qt::TimerType time t->cumulativeError = 0; t->count = 0; if (t->timerType != Qt::PreciseTimer) - qDebug() << "timer" << t->timerType << hex <id << dec << "interval" << t->interval << "expected at" + qDebug() << "timer" << t->timerType << Qt::hex <id << Qt::dec << "interval" << t->interval << "expected at" << t->expected << "will fire first at" << t->timeout; #endif } @@ -620,7 +620,7 @@ int QTimerInfoList::activateTimers() currentTimerInfo->cumulativeError += diff; ++currentTimerInfo->count; if (currentTimerInfo->timerType != Qt::PreciseTimer) - qDebug() << "timer" << currentTimerInfo->timerType << hex << currentTimerInfo->id << dec << "interval" + qDebug() << "timer" << currentTimerInfo->timerType << Qt::hex << currentTimerInfo->id << Qt::dec << "interval" << currentTimerInfo->interval << "firing at" << currentTime << "(orig" << currentTimerInfo->expected << "scheduled at" << currentTimerInfo->timeout << ") off by" << diff << "activation" << currentTimerInfo->count diff --git a/src/corelib/plugin/qfactoryloader.cpp b/src/corelib/plugin/qfactoryloader.cpp index 35c64180d4..8e349f23ce 100644 --- a/src/corelib/plugin/qfactoryloader.cpp +++ b/src/corelib/plugin/qfactoryloader.cpp @@ -239,7 +239,7 @@ void QFactoryLoader::update() library = QLibraryPrivate::findOrCreate(QFileInfo(fileName).canonicalFilePath()); if (!library->isPlugin()) { if (qt_debug_component()) { - qDebug() << library->errorString << endl + qDebug() << library->errorString << Qt::endl << " not a plugin"; } library->release(); diff --git a/src/corelib/serialization/qcborvalue.cpp b/src/corelib/serialization/qcborvalue.cpp index d469735ae9..b2e0ba6d53 100644 --- a/src/corelib/serialization/qcborvalue.cpp +++ b/src/corelib/serialization/qcborvalue.cpp @@ -2941,7 +2941,7 @@ static QDebug debugContents(QDebug &dbg, const QCborValue &v) } if (v.isSimpleType()) return dbg << v.toSimpleType(); - return dbg << "'; + return dbg << "'; } QDebug operator<<(QDebug dbg, const QCborValue &v) { diff --git a/src/corelib/serialization/qjsonparser.cpp b/src/corelib/serialization/qjsonparser.cpp index bfba95520e..f29348d593 100644 --- a/src/corelib/serialization/qjsonparser.cpp +++ b/src/corelib/serialization/qjsonparser.cpp @@ -316,7 +316,7 @@ QJsonDocument Parser::parse(QJsonParseError *error) eatBOM(); char token = nextToken(); - DEBUG << hex << (uint)token; + DEBUG << Qt::hex << (uint)token; if (token == BeginArray) { if (!parseArray()) goto error; diff --git a/src/corelib/serialization/qtextstream.cpp b/src/corelib/serialization/qtextstream.cpp index 0d83bb6cd4..ef2a9c97ee 100644 --- a/src/corelib/serialization/qtextstream.cpp +++ b/src/corelib/serialization/qtextstream.cpp @@ -2356,7 +2356,7 @@ void QTextStreamPrivate::putNumber(qulonglong number, bool negative) } else if (negative) { // Workaround for backward compatibility for writing negative // numbers in octal and hex: - // QTextStream(result) << showbase << hex << -1 << oct << -1 + // QTextStream(result) << Qt::showbase << Qt::hex << -1 << oct << -1 // should output: -0x1 -0b1 result = dd->unsLongLongToString(number, -1, base, -1, flags); result.prepend(locale.negativeSign()); @@ -2978,7 +2978,7 @@ QTextStream ¢er(QTextStream &stream) */ QTextStream &endl(QTextStream &stream) { - return stream << QLatin1Char('\n') << flush; + return stream << QLatin1Char('\n') << Qt::flush; } /*! diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 029499039c..93d81b89b6 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -826,9 +826,9 @@ static int ucstricmp(const QChar *a, const QChar *ae, const QChar *b, const QCha uint alast = 0; uint blast = 0; while (a < e) { -// qDebug() << hex << alast << blast; -// qDebug() << hex << "*a=" << *a << "alast=" << alast << "folded=" << foldCase (*a, alast); -// qDebug() << hex << "*b=" << *b << "blast=" << blast << "folded=" << foldCase (*b, blast); +// qDebug() << Qt::hex << alast << blast; +// qDebug() << Qt::hex << "*a=" << *a << "alast=" << alast << "folded=" << foldCase (*a, alast); +// qDebug() << Qt::hex << "*b=" << *b << "blast=" << blast << "folded=" << foldCase (*b, blast); int diff = foldCase(a->unicode(), alast) - foldCase(b->unicode(), blast); if ((diff)) return diff; diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp index 46dec7f28d..de76d12a5e 100644 --- a/src/gui/accessible/qaccessible.cpp +++ b/src/gui/accessible/qaccessible.cpp @@ -1858,7 +1858,7 @@ Q_GUI_EXPORT QDebug operator<<(QDebug d, const QAccessibleInterface *iface) return d; } d.nospace(); - d << "QAccessibleInterface(" << hex << (const void *) iface << dec; + d << "QAccessibleInterface(" << Qt::hex << (const void *) iface << Qt::dec; if (iface->isValid()) { d << " name=" << iface->text(QAccessible::Name) << ' '; d << "role=" << qAccessibleRoleString(iface->role()) << ' '; @@ -1897,7 +1897,7 @@ QDebug operator<<(QDebug d, const QAccessibleEvent &ev) QDebugStateSaver saver(d); d.nospace() << "QAccessibleEvent("; if (ev.object()) { - d.nospace() << "object=" << hex << ev.object() << dec; + d.nospace() << "object=" << Qt::hex << ev.object() << Qt::dec; d.nospace() << "child=" << ev.child(); } else { d.nospace() << "no object, uniqueId=" << ev.uniqueId(); diff --git a/src/gui/doc/snippets/textdocumentendsnippet.cpp b/src/gui/doc/snippets/textdocumentendsnippet.cpp index c8de501838..cb7abd5ca7 100644 --- a/src/gui/doc/snippets/textdocumentendsnippet.cpp +++ b/src/gui/doc/snippets/textdocumentendsnippet.cpp @@ -59,7 +59,7 @@ int main(int argv, char **args) //! [0] for (QTextBlock it = doc->begin(); it != doc->end(); it = it.next()) - cout << it.text().toStdString() << endl; + cout << it.text().toStdString() << Qt::endl; //! [0] return 0; diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp index 892a686c89..2b47fb536b 100644 --- a/src/gui/image/qicon.cpp +++ b/src/gui/image/qicon.cpp @@ -1496,7 +1496,7 @@ QDebug operator<<(QDebug dbg, const QIcon &i) if (!i.name().isEmpty()) dbg << i.name() << ','; dbg << "availableSizes[normal,Off]=" << i.availableSizes() - << ",cacheKey=" << showbase << hex << i.cacheKey() << dec << noshowbase; + << ",cacheKey=" << Qt::showbase << Qt::hex << i.cacheKey() << Qt::dec << Qt::noshowbase; } dbg << ')'; return dbg; diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp index 5b4d218603..399ad7453d 100644 --- a/src/gui/image/qpixmap.cpp +++ b/src/gui/image/qpixmap.cpp @@ -1689,7 +1689,7 @@ QDebug operator<<(QDebug dbg, const QPixmap &r) } else { dbg << r.size() << ",depth=" << r.depth() << ",devicePixelRatio=" << r.devicePixelRatio() - << ",cacheKey=" << showbase << hex << r.cacheKey() << dec << noshowbase; + << ",cacheKey=" << Qt::showbase << Qt::hex << r.cacheKey() << Qt::dec << Qt::noshowbase; } dbg << ')'; return dbg; diff --git a/src/gui/image/qxpmhandler.cpp b/src/gui/image/qxpmhandler.cpp index 7349a400a6..deff56aa58 100644 --- a/src/gui/image/qxpmhandler.cpp +++ b/src/gui/image/qxpmhandler.cpp @@ -1129,8 +1129,8 @@ static bool write_xpm_image(const QImage &sourceImage, QIODevice *device, const // write header QTextStream s(device); - s << "/* XPM */" << endl - << "static char *" << fbname(fileName) << "[]={" << endl + s << "/* XPM */" << Qt::endl + << "static char *" << fbname(fileName) << "[]={" << Qt::endl << '\"' << w << ' ' << h << ' ' << ncolors << ' ' << cpp << '\"'; // write palette @@ -1147,7 +1147,7 @@ static bool write_xpm_image(const QImage &sourceImage, QIODevice *device, const qGreen(color), qBlue(color)); ++c; - s << ',' << endl << line; + s << ',' << Qt::endl << line; } // write pixels, limit to 4 characters per pixel @@ -1169,9 +1169,9 @@ static bool write_xpm_image(const QImage &sourceImage, QIODevice *device, const } } } - s << ',' << endl << '\"' << line << '\"'; + s << ',' << Qt::endl << '\"' << line << '\"'; } - s << "};" << endl; + s << "};" << Qt::endl; return (s.status() == QTextStream::Ok); } diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index f6d1da45e3..563eab4655 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -3764,13 +3764,13 @@ static inline void formatTouchEvent(QDebug d, const QTouchEvent &t) static void formatUnicodeString(QDebug d, const QString &s) { - d << '"' << hex; + d << '"' << Qt::hex; for (int i = 0; i < s.size(); ++i) { if (i) d << ','; d << "U+" << s.at(i).unicode(); } - d << dec << '"'; + d << Qt::dec << '"'; } static inline void formatInputMethodEvent(QDebug d, const QInputMethodEvent *e) @@ -3807,8 +3807,8 @@ static inline void formatInputMethodQueryEvent(QDebug d, const QInputMethodQuery QDebugStateSaver saver(d); d.noquote(); const Qt::InputMethodQueries queries = e->queries(); - d << "QInputMethodQueryEvent(queries=" << showbase << hex << int(queries) - << noshowbase << dec << ", {"; + d << "QInputMethodQueryEvent(queries=" << Qt::showbase << Qt::hex << int(queries) + << Qt::noshowbase << Qt::dec << ", {"; for (unsigned mask = 1; mask <= Qt::ImInputItemClipRectangle; mask<<=1) { if (queries & mask) { const Qt::InputMethodQuery query = static_cast(mask); @@ -4001,7 +4001,7 @@ QDebug operator<<(QDebug dbg, const QTouchEvent::TouchPoint &tp) { QDebugStateSaver saver(dbg); dbg.nospace(); - dbg << "TouchPoint(" << hex << tp.id() << dec << " ("; + dbg << "TouchPoint(" << Qt::hex << tp.id() << Qt::dec << " ("; QtDebugUtils::formatQPoint(dbg, tp.pos()); dbg << ") "; QtDebugUtils::formatQEnum(dbg, tp.state()); diff --git a/src/gui/kernel/qpalette.cpp b/src/gui/kernel/qpalette.cpp index b4383c5bfc..f6e5fa0a52 100644 --- a/src/gui/kernel/qpalette.cpp +++ b/src/gui/kernel/qpalette.cpp @@ -1204,7 +1204,7 @@ QDebug operator<<(QDebug dbg, const QPalette &p) QDebugStateSaver saver(dbg); QDebug nospace = dbg.nospace(); const uint mask = p.resolve(); - nospace << "QPalette(resolve=" << hex << showbase << mask << ','; + nospace << "QPalette(resolve=" << Qt::hex << Qt::showbase << mask << ','; for (int role = 0; role < (int)QPalette::NColorRoles; ++role) { if (mask & (1<isTopLevel()) debug << ", toplevel"; debug << ", " << geometry.width() << 'x' << geometry.height() - << forcesign << geometry.x() << geometry.y() << noforcesign; + << Qt::forcesign << geometry.x() << geometry.y() << Qt::noforcesign; const QMargins margins = window->frameMargins(); if (!margins.isNull()) debug << ", margins=" << margins; debug << ", devicePixelRatio=" << window->devicePixelRatio(); if (const QPlatformWindow *platformWindow = window->handle()) - debug << ", winId=0x" << hex << platformWindow->winId() << dec; + debug << ", winId=0x" << Qt::hex << platformWindow->winId() << Qt::dec; if (const QScreen *screen = window->screen()) debug << ", on " << screen->name(); } diff --git a/src/gui/math3d/qgenericmatrix.h b/src/gui/math3d/qgenericmatrix.h index 6a2a9e5bae..692c29c996 100644 --- a/src/gui/math3d/qgenericmatrix.h +++ b/src/gui/math3d/qgenericmatrix.h @@ -351,11 +351,11 @@ QDebug operator<<(QDebug dbg, const QGenericMatrix &m) QDebugStateSaver saver(dbg); dbg.nospace() << "QGenericMatrix<" << N << ", " << M << ", " << QTypeInfo::name() - << ">(" << endl << qSetFieldWidth(10); + << ">(" << Qt::endl << qSetFieldWidth(10); for (int row = 0; row < M; ++row) { for (int col = 0; col < N; ++col) dbg << m(row, col); - dbg << endl; + dbg << Qt::endl; } dbg << qSetFieldWidth(0) << ')'; return dbg; diff --git a/src/gui/math3d/qmatrix4x4.cpp b/src/gui/math3d/qmatrix4x4.cpp index 045fa210c4..ad4cdfdbf4 100644 --- a/src/gui/math3d/qmatrix4x4.cpp +++ b/src/gui/math3d/qmatrix4x4.cpp @@ -2037,12 +2037,12 @@ QDebug operator<<(QDebug dbg, const QMatrix4x4 &m) } // Output in row-major order because it is more human-readable. - dbg.nospace() << "QMatrix4x4(type:" << bits.constData() << endl + dbg.nospace() << "QMatrix4x4(type:" << bits.constData() << Qt::endl << qSetFieldWidth(10) - << m(0, 0) << m(0, 1) << m(0, 2) << m(0, 3) << endl - << m(1, 0) << m(1, 1) << m(1, 2) << m(1, 3) << endl - << m(2, 0) << m(2, 1) << m(2, 2) << m(2, 3) << endl - << m(3, 0) << m(3, 1) << m(3, 2) << m(3, 3) << endl + << m(0, 0) << m(0, 1) << m(0, 2) << m(0, 3) << Qt::endl + << m(1, 0) << m(1, 1) << m(1, 2) << m(1, 3) << Qt::endl + << m(2, 0) << m(2, 1) << m(2, 2) << m(2, 3) << Qt::endl + << m(3, 0) << m(3, 1) << m(3, 2) << m(3, 3) << Qt::endl << qSetFieldWidth(0) << ')'; return dbg; } diff --git a/src/gui/opengl/qopengl.cpp b/src/gui/opengl/qopengl.cpp index 2b1e57a4bb..6b701fe52b 100644 --- a/src/gui/opengl/qopengl.cpp +++ b/src/gui/opengl/qopengl.cpp @@ -136,7 +136,7 @@ QDebug operator<<(QDebug d, const QOpenGLConfig::Gpu &g) d.nospace(); d << "Gpu("; if (g.isValid()) { - d << "vendor=" << hex << showbase <renderHints; + qDebug() << "QRasterPaintEngine::renderHintsChanged()" << Qt::hex << s->renderHints; #endif bool was_aa = s->flags.antialiased; @@ -1745,7 +1745,7 @@ void QRasterPaintEngine::fill(const QVectorPath &path, const QBrush &brush) QRectF rf = path.controlPointRect(); qDebug() << "QRasterPaintEngine::fill(): " << "size=" << path.elementCount() - << ", hints=" << hex << path.hints() + << ", hints=" << Qt::hex << path.hints() << rf << brush; #endif diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp index 22d3fb3001..8314e8bc8a 100644 --- a/src/gui/painting/qpaintengineex.cpp +++ b/src/gui/painting/qpaintengineex.cpp @@ -140,7 +140,7 @@ QDebug Q_GUI_EXPORT &operator<<(QDebug &s, const QVectorPath &path) QDebugStateSaver saver(s); QRectF rf = path.controlPointRect(); s << "QVectorPath(size:" << path.elementCount() - << " hints:" << hex << path.hints() + << " hints:" << Qt::hex << path.hints() << rf << ')'; return s; } diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp index 649cfd554b..7eaa4b6e3f 100644 --- a/src/gui/painting/qpainterpath.cpp +++ b/src/gui/painting/qpainterpath.cpp @@ -3576,10 +3576,10 @@ void QPainterPath::computeControlPointRect() const #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug s, const QPainterPath &p) { - s.nospace() << "QPainterPath: Element count=" << p.elementCount() << endl; + s.nospace() << "QPainterPath: Element count=" << p.elementCount() << Qt::endl; const char *types[] = {"MoveTo", "LineTo", "CurveTo", "CurveToData"}; for (int i=0; i " << types[p.elementAt(i).type] << "(x=" << p.elementAt(i).x << ", y=" << p.elementAt(i).y << ')' << endl; + s.nospace() << " -> " << types[p.elementAt(i).type] << "(x=" << p.elementAt(i).x << ", y=" << p.elementAt(i).y << ')' << Qt::endl; } return s; diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index 1719855e68..99c9e1bfdc 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -1213,7 +1213,7 @@ void QFontEngine::loadKerningPairs(QFixed scalingFactor) end: std::sort(kerning_pairs.begin(), kerning_pairs.end()); // for (int i = 0; i < kerning_pairs.count(); ++i) -// qDebug() << 'i' << i << "left_right" << hex << kerning_pairs.at(i).left_right; +// qDebug() << 'i' << i << "left_right" << Qt::hex << kerning_pairs.at(i).left_right; } diff --git a/src/gui/text/qfontengine_qpf2.cpp b/src/gui/text/qfontengine_qpf2.cpp index 110d512d39..409176d41b 100644 --- a/src/gui/text/qfontengine_qpf2.cpp +++ b/src/gui/text/qfontengine_qpf2.cpp @@ -140,9 +140,9 @@ static inline const uchar *verifyTag(const uchar *tagPtr, const uchar *endPtr) } #if defined(DEBUG_HEADER) if (length == 1) - qDebug() << "tag data" << hex << *tagPtr; + qDebug() << "tag data" << Qt::hex << *tagPtr; else if (length == 4) - qDebug() << "tag data" << hex << tagPtr[0] << tagPtr[1] << tagPtr[2] << tagPtr[3]; + qDebug() << "tag data" << Qt::hex << tagPtr[0] << tagPtr[1] << tagPtr[2] << tagPtr[3]; #endif } return tagPtr + length; @@ -367,7 +367,7 @@ bool QFontEngineQPF2::stringToCMap(const QChar *str, int len, QGlyphLayout *glyp #if 0 && defined(DEBUG_FONTENGINE) QChar c(uc); if (!findGlyph(glyphs[glyph_pos].glyph) && !seenGlyphs.contains(c)) - qDebug() << "glyph for character" << c << '/' << hex << uc << "is" << dec << glyphs[glyph_pos].glyph; + qDebug() << "glyph for character" << c << '/' << Qt::hex << uc << "is" << Qt::dec << glyphs[glyph_pos].glyph; seenGlyphs.insert(c); #endif diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 2616a42022..840448152f 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -990,7 +990,7 @@ struct QBidiAlgorithm { BIDI_DEBUG() << "before implicit level processing:"; IsolatedRunSequenceIterator it(runs, i); while (!it.atEnd()) { - BIDI_DEBUG() << " " << *it << hex << text[*it].unicode() << analysis[*it].bidiDirection; + BIDI_DEBUG() << " " << *it << Qt::hex << text[*it].unicode() << analysis[*it].bidiDirection; ++it; } } @@ -1003,7 +1003,7 @@ struct QBidiAlgorithm { BIDI_DEBUG() << "after W4/W5"; IsolatedRunSequenceIterator it(runs, i); while (!it.atEnd()) { - BIDI_DEBUG() << " " << *it << hex << text[*it].unicode() << analysis[*it].bidiDirection; + BIDI_DEBUG() << " " << *it << Qt::hex << text[*it].unicode() << analysis[*it].bidiDirection; ++it; } } @@ -1089,7 +1089,7 @@ struct QBidiAlgorithm { if (BidiDebugEnabled) { BIDI_DEBUG() << ">>>> start bidi, text length" << length; for (int i = 0; i < length; ++i) - BIDI_DEBUG() << hex << " (" << i << ")" << text[i].unicode() << text[i].direction(); + BIDI_DEBUG() << Qt::hex << " (" << i << ")" << text[i].unicode() << text[i].direction(); } { @@ -1158,7 +1158,7 @@ struct QBidiAlgorithm { if (BidiDebugEnabled) { BIDI_DEBUG() << "final resolved levels:"; for (int i = 0; i < length; ++i) - BIDI_DEBUG() << " " << i << hex << text[i].unicode() << dec << (int)analysis[i].bidiLevel; + BIDI_DEBUG() << " " << i << Qt::hex << text[i].unicode() << Qt::dec << (int)analysis[i].bidiLevel; } return true; diff --git a/src/platformsupport/fontdatabases/freetype/qfreetypefontdatabase.cpp b/src/platformsupport/fontdatabases/freetype/qfreetypefontdatabase.cpp index 4baba64de3..1028d8ec02 100644 --- a/src/platformsupport/fontdatabases/freetype/qfreetypefontdatabase.cpp +++ b/src/platformsupport/fontdatabases/freetype/qfreetypefontdatabase.cpp @@ -127,7 +127,7 @@ QStringList QFreeTypeFontDatabase::addTTFile(const QByteArray &fontData, const Q error = FT_New_Face(library, file.constData(), index, &face); } if (error != FT_Err_Ok) { - qDebug() << "FT_New_Face failed with index" << index << ':' << hex << error; + qDebug() << "FT_New_Face failed with index" << index << ':' << Qt::hex << error; break; } numFaces = face->num_faces; diff --git a/src/plugins/bearer/nla/qnlaengine.cpp b/src/plugins/bearer/nla/qnlaengine.cpp index 726e1efb92..bf10e0cc1f 100644 --- a/src/plugins/bearer/nla/qnlaengine.cpp +++ b/src/plugins/bearer/nla/qnlaengine.cpp @@ -75,38 +75,38 @@ QWindowsSockInit2::~QWindowsSockInit2() #ifdef BEARER_MANAGEMENT_DEBUG static void printBlob(NLA_BLOB *blob) { - qDebug() << "==== BEGIN NLA_BLOB ====" << endl + qDebug() << "==== BEGIN NLA_BLOB ====" << Qt::endl - << "type:" << blob->header.type << endl - << "size:" << blob->header.dwSize << endl + << "type:" << blob->header.type << Qt::endl + << "size:" << blob->header.dwSize << Qt::endl << "next offset:" << blob->header.nextOffset; switch (blob->header.type) { case NLA_RAW_DATA: - qDebug() << "Raw Data" << endl + qDebug() << "Raw Data" << Qt::endl << '\t' << blob->data.rawData; break; case NLA_INTERFACE: - qDebug() << "Interface" << endl - << "\ttype:" << blob->data.interfaceData.dwType << endl - << "\tspeed:" << blob->data.interfaceData.dwSpeed << endl + qDebug() << "Interface" << Qt::endl + << "\ttype:" << blob->data.interfaceData.dwType << Qt::endl + << "\tspeed:" << blob->data.interfaceData.dwSpeed << Qt::endl << "\tadapter:" << blob->data.interfaceData.adapterName; break; case NLA_802_1X_LOCATION: - qDebug() << "802.1x Location" << endl + qDebug() << "802.1x Location" << Qt::endl << '\t' << blob->data.locationData.information; break; case NLA_CONNECTIVITY: - qDebug() << "Connectivity" << endl - << "\ttype:" << blob->data.connectivity.type << endl + qDebug() << "Connectivity" << Qt::endl + << "\ttype:" << blob->data.connectivity.type << Qt::endl << "\tinternet:" << blob->data.connectivity.internet; break; case NLA_ICS: - qDebug() << "ICS" << endl - << "\tspeed:" << blob->data.ICS.remote.speed << endl - << "\ttype:" << blob->data.ICS.remote.type << endl - << "\tstate:" << blob->data.ICS.remote.state << endl - << "\tmachine name:" << blob->data.ICS.remote.machineName << endl + qDebug() << "ICS" << Qt::endl + << "\tspeed:" << blob->data.ICS.remote.speed << Qt::endl + << "\ttype:" << blob->data.ICS.remote.type << Qt::endl + << "\tstate:" << blob->data.ICS.remote.state << Qt::endl + << "\tmachine name:" << blob->data.ICS.remote.machineName << Qt::endl << "\tshared adapter name:" << blob->data.ICS.remote.sharedAdapterName; break; default: diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp index 6ae429b24e..70dde46ffa 100644 --- a/src/plugins/platforms/android/androidjnimain.cpp +++ b/src/plugins/platforms/android/androidjnimain.cpp @@ -485,7 +485,7 @@ static jboolean startQtAndroidPlugin(JNIEnv *env, jobject /*object*/, jstring pa } if (Q_UNLIKELY(!m_main)) { - qCritical() << "dlsym failed:" << dlerror() << endl + qCritical() << "dlsym failed:" << dlerror() << Qt::endl << "Could not find main method"; return false; } diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm index 368cf56c80..db4ec251ae 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm +++ b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm @@ -177,7 +177,7 @@ NSString *macRole(QAccessibleInterface *interface) if (roleMap.isEmpty()) populateRoleMap(); - // MAC_ACCESSIBILTY_DEBUG() << "role for" << interface.object() << "interface role" << hex << qtRole; + // MAC_ACCESSIBILTY_DEBUG() << "role for" << interface.object() << "interface role" << Qt::hex << qtRole; if (roleMap.contains(qtRole)) { // MAC_ACCESSIBILTY_DEBUG() << "return" << roleMap[qtRole]; diff --git a/src/plugins/platforms/cocoa/qnsview_gestures.mm b/src/plugins/platforms/cocoa/qnsview_gestures.mm index 61d551ee0e..f6cd3af4da 100644 --- a/src/plugins/platforms/cocoa/qnsview_gestures.mm +++ b/src/plugins/platforms/cocoa/qnsview_gestures.mm @@ -70,7 +70,7 @@ Q_LOGGING_CATEGORY(lcQpaGestures, "qt.qpa.input.gestures") if ([self handleGestureAsBeginEnd:event]) return; - qCDebug(lcQpaGestures) << "magnifyWithEvent" << [event magnification] << "from device" << hex << [event deviceID]; + qCDebug(lcQpaGestures) << "magnifyWithEvent" << [event magnification] << "from device" << Qt::hex << [event deviceID]; const NSTimeInterval timestamp = [event timestamp]; QPointF windowPoint; QPointF screenPoint; @@ -85,7 +85,7 @@ Q_LOGGING_CATEGORY(lcQpaGestures, "qt.qpa.input.gestures") return; static bool zoomIn = true; - qCDebug(lcQpaGestures) << "smartMagnifyWithEvent" << zoomIn << "from device" << hex << [event deviceID]; + qCDebug(lcQpaGestures) << "smartMagnifyWithEvent" << zoomIn << "from device" << Qt::hex << [event deviceID]; const NSTimeInterval timestamp = [event timestamp]; QPointF windowPoint; QPointF screenPoint; @@ -116,7 +116,7 @@ Q_LOGGING_CATEGORY(lcQpaGestures, "qt.qpa.input.gestures") if (!m_platformWindow) return; - qCDebug(lcQpaGestures) << "swipeWithEvent" << [event deltaX] << [event deltaY] << "from device" << hex << [event deviceID]; + qCDebug(lcQpaGestures) << "swipeWithEvent" << [event deltaX] << [event deltaY] << "from device" << Qt::hex << [event deviceID]; const NSTimeInterval timestamp = [event timestamp]; QPointF windowPoint; QPointF screenPoint; @@ -145,7 +145,7 @@ Q_LOGGING_CATEGORY(lcQpaGestures, "qt.qpa.input.gestures") QPointF windowPoint; QPointF screenPoint; [self convertFromScreen:[self screenMousePoint:event] toWindowPoint:&windowPoint andScreenPoint:&screenPoint]; - qCDebug(lcQpaGestures) << "beginGestureWithEvent @" << windowPoint << "from device" << hex << [event deviceID]; + qCDebug(lcQpaGestures) << "beginGestureWithEvent @" << windowPoint << "from device" << Qt::hex << [event deviceID]; QWindowSystemInterface::handleGestureEvent(m_platformWindow->window(), QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), timestamp, Qt::BeginNativeGesture, windowPoint, screenPoint); } @@ -155,7 +155,7 @@ Q_LOGGING_CATEGORY(lcQpaGestures, "qt.qpa.input.gestures") if (!m_platformWindow) return; - qCDebug(lcQpaGestures) << "endGestureWithEvent" << "from device" << hex << [event deviceID]; + qCDebug(lcQpaGestures) << "endGestureWithEvent" << "from device" << Qt::hex << [event deviceID]; const NSTimeInterval timestamp = [event timestamp]; QPointF windowPoint; QPointF screenPoint; diff --git a/src/plugins/platforms/cocoa/qnsview_touch.mm b/src/plugins/platforms/cocoa/qnsview_touch.mm index e789213f70..9330844aec 100644 --- a/src/plugins/platforms/cocoa/qnsview_touch.mm +++ b/src/plugins/platforms/cocoa/qnsview_touch.mm @@ -60,7 +60,7 @@ Q_LOGGING_CATEGORY(lcQpaTouch, "qt.qpa.input.touch") const NSTimeInterval timestamp = [event timestamp]; const QList points = QCocoaTouch::getCurrentTouchPointList(event, [self shouldSendSingleTouch]); - qCDebug(lcQpaTouch) << "touchesBeganWithEvent" << points << "from device" << hex << [event deviceID]; + qCDebug(lcQpaTouch) << "touchesBeganWithEvent" << points << "from device" << Qt::hex << [event deviceID]; QWindowSystemInterface::handleTouchEvent(m_platformWindow->window(), timestamp * 1000, QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), points); } @@ -71,7 +71,7 @@ Q_LOGGING_CATEGORY(lcQpaTouch, "qt.qpa.input.touch") const NSTimeInterval timestamp = [event timestamp]; const QList points = QCocoaTouch::getCurrentTouchPointList(event, [self shouldSendSingleTouch]); - qCDebug(lcQpaTouch) << "touchesMovedWithEvent" << points << "from device" << hex << [event deviceID]; + qCDebug(lcQpaTouch) << "touchesMovedWithEvent" << points << "from device" << Qt::hex << [event deviceID]; QWindowSystemInterface::handleTouchEvent(m_platformWindow->window(), timestamp * 1000, QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), points); } @@ -82,7 +82,7 @@ Q_LOGGING_CATEGORY(lcQpaTouch, "qt.qpa.input.touch") const NSTimeInterval timestamp = [event timestamp]; const QList points = QCocoaTouch::getCurrentTouchPointList(event, [self shouldSendSingleTouch]); - qCDebug(lcQpaTouch) << "touchesEndedWithEvent" << points << "from device" << hex << [event deviceID]; + qCDebug(lcQpaTouch) << "touchesEndedWithEvent" << points << "from device" << Qt::hex << [event deviceID]; QWindowSystemInterface::handleTouchEvent(m_platformWindow->window(), timestamp * 1000, QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), points); } @@ -93,7 +93,7 @@ Q_LOGGING_CATEGORY(lcQpaTouch, "qt.qpa.input.touch") const NSTimeInterval timestamp = [event timestamp]; const QList points = QCocoaTouch::getCurrentTouchPointList(event, [self shouldSendSingleTouch]); - qCDebug(lcQpaTouch) << "touchesCancelledWithEvent" << points << "from device" << hex << [event deviceID]; + qCDebug(lcQpaTouch) << "touchesCancelledWithEvent" << points << "from device" << Qt::hex << [event deviceID]; QWindowSystemInterface::handleTouchEvent(m_platformWindow->window(), timestamp * 1000, QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), points); } diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp index 24051c352e..09a10bcc9c 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp @@ -157,7 +157,7 @@ gbm_surface *QEglFSKmsGbmScreen::createSurface(EGLConfig eglConfig) const auto gbmDevice = static_cast(device())->gbmDevice(); EGLint native_format = -1; EGLBoolean success = eglGetConfigAttrib(display(), eglConfig, EGL_NATIVE_VISUAL_ID, &native_format); - qCDebug(qLcEglfsKmsDebug) << "Got native format" << hex << native_format << dec << "from eglGetConfigAttrib() with return code" << bool(success); + qCDebug(qLcEglfsKmsDebug) << "Got native format" << Qt::hex << native_format << Qt::dec << "from eglGetConfigAttrib() with return code" << bool(success); if (success) m_gbm_surface = gbm_surface_create(gbmDevice, diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index 073d6da536..9ab9c2708b 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -590,7 +590,7 @@ QString QWindowsContext::registerWindowClass(QString cname, d->m_registeredWindowClassNames.insert(cname); qCDebug(lcQpaWindows).nospace() << __FUNCTION__ << ' ' << cname - << " style=0x" << hex << style << dec + << " style=0x" << Qt::hex << style << Qt::dec << " brush=" << brush << " icon=" << icon << " atom=" << atom; return cname; } @@ -1570,7 +1570,7 @@ extern "C" LRESULT QT_WIN_CALLBACK qWindowsWndProc(HWND hwnd, UINT message, WPAR if (QWindowsContext::verbose > 1 && lcQpaEvents().isDebugEnabled()) { if (const char *eventName = QWindowsGuiEventDispatcher::windowsMessageName(message)) { qCDebug(lcQpaEvents).nospace() << "EVENT: hwd=" << hwnd << ' ' << eventName - << " msg=0x" << hex << message << " et=0x" << et << dec << " wp=" + << " msg=0x" << Qt::hex << message << " et=0x" << et << Qt::dec << " wp=" << int(wParam) << " at " << GET_X_LPARAM(lParam) << ',' << GET_Y_LPARAM(lParam) << " handled=" << handled; } diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp index 9de3268fc8..e0bd38c951 100644 --- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp +++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp @@ -736,7 +736,7 @@ QString QWindowsShellItem::libraryItemDefaultSaveFolder(IShellItem *item) #ifndef QT_NO_DEBUG_STREAM void QWindowsShellItem::format(QDebug &d) const { - d << "attributes=0x" << hex << attributes() << dec; + d << "attributes=0x" << Qt::hex << attributes() << Qt::dec; if (isFileSystem()) d << " [filesys]"; if (isDir()) @@ -972,7 +972,7 @@ void QWindowsNativeFileDialogBase::doExec(HWND owner) // gets a WM_CLOSE or the parent window is destroyed. const HRESULT hr = m_fileDialog->Show(owner); QWindowsDialogs::eatMouseMove(); - qCDebug(lcQpaDialogs) << '<' << __FUNCTION__ << " returns " << hex << hr; + qCDebug(lcQpaDialogs) << '<' << __FUNCTION__ << " returns " << Qt::hex << hr; // Emit accepted() only if there is a result as otherwise UI hangs occur. // For example, typing in invalid URLs results in empty result lists. if (hr == S_OK && !m_data.selectedFiles().isEmpty()) { @@ -1013,7 +1013,7 @@ void QWindowsNativeFileDialogBase::setMode(QFileDialogOptions::FileMode mode, } qCDebug(lcQpaDialogs) << __FUNCTION__ << "mode=" << mode << "acceptMode=" << acceptMode << "options=" << options - << "results in" << showbase << hex << flags; + << "results in" << Qt::showbase << Qt::hex << flags; if (FAILED(m_fileDialog->SetOptions(flags))) qErrnoWarning("%s: SetOptions() failed", __FUNCTION__); diff --git a/src/plugins/platforms/windows/qwindowsdrag.cpp b/src/plugins/platforms/windows/qwindowsdrag.cpp index 322865b0f3..502c92ef59 100644 --- a/src/plugins/platforms/windows/qwindowsdrag.cpp +++ b/src/plugins/platforms/windows/qwindowsdrag.cpp @@ -428,7 +428,7 @@ QWindowsOleDropSource::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState) if (QWindowsContext::verbose > 1 || result != S_OK) { qCDebug(lcQpaMime) << __FUNCTION__ << "fEscapePressed=" << fEscapePressed << "grfKeyState=" << grfKeyState << "buttons" << m_currentButtons - << "returns 0x" << hex << int(result) << dec; + << "returns 0x" << Qt::hex << int(result) << Qt::dec; } return ResultFromScode(result); } @@ -710,7 +710,7 @@ Qt::DropAction QWindowsDrag::drag(QDrag *drag) const Qt::DropActions possibleActions = drag->supportedActions(); const DWORD allowedEffects = translateToWinDragEffects(possibleActions); qCDebug(lcQpaMime) << '>' << __FUNCTION__ << "possible Actions=0x" - << hex << int(possibleActions) << "effects=0x" << allowedEffects << dec; + << Qt::hex << int(possibleActions) << "effects=0x" << allowedEffects << Qt::dec; // Indicate message handlers we are in DoDragDrop() event loop. QWindowsDrag::m_dragging = true; const HRESULT r = DoDragDrop(dropDataObject, windowDropSource, allowedEffects, &resultEffect); @@ -734,9 +734,9 @@ Qt::DropAction QWindowsDrag::drag(QDrag *drag) dropDataObject->releaseQt(); dropDataObject->Release(); // Will delete obj if refcount becomes 0 windowDropSource->Release(); // Will delete src if refcount becomes 0 - qCDebug(lcQpaMime) << '<' << __FUNCTION__ << hex << "allowedEffects=0x" << allowedEffects + qCDebug(lcQpaMime) << '<' << __FUNCTION__ << Qt::hex << "allowedEffects=0x" << allowedEffects << "reportedPerformedEffect=0x" << reportedPerformedEffect - << " resultEffect=0x" << resultEffect << "hr=0x" << int(r) << dec << "dropAction=" << dragResult; + << " resultEffect=0x" << resultEffect << "hr=0x" << int(r) << Qt::dec << "dropAction=" << dragResult; return dragResult; } diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp index e95eaef420..d534ce87cd 100644 --- a/src/plugins/platforms/windows/qwindowsglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp @@ -243,7 +243,7 @@ QDebug operator<<(QDebug d, const PIXELFORMATDESCRIPTOR &pd) QDebugStateSaver saver(d); d.nospace(); d << "PIXELFORMATDESCRIPTOR " - << "dwFlags=" << hex << showbase << pd.dwFlags << dec << noshowbase; + << "dwFlags=" << Qt::hex << Qt::showbase << pd.dwFlags << Qt::dec << Qt::noshowbase; if (pd.dwFlags & PFD_DRAW_TO_WINDOW) d << " PFD_DRAW_TO_WINDOW"; if (pd.dwFlags & PFD_DRAW_TO_BITMAP) d << " PFD_DRAW_TO_BITMAP"; if (pd.dwFlags & PFD_SUPPORT_GDI) d << " PFD_SUPPORT_GDI"; @@ -631,10 +631,10 @@ static int choosePixelFormat(HDC hdc, nsp << __FUNCTION__; if (sampleBuffersRequested) nsp << " samples=" << iAttributes[samplesValuePosition]; - nsp << " Attributes: " << hex << showbase; + nsp << " Attributes: " << Qt::hex << Qt::showbase; for (int ii = 0; ii < i; ++ii) nsp << iAttributes[ii] << ','; - nsp << noshowbase << dec << "\n obtained px #" << pixelFormat + nsp << Qt::noshowbase << Qt::dec << "\n obtained px #" << pixelFormat << " of " << numFormats << "\n " << *obtainedPfd; qCDebug(lcQpaGl) << message; } // Debug @@ -784,7 +784,7 @@ static HGLRC createContext(const QOpenGLStaticContext &staticContext, if (!result) { QString message; QDebug(&message).nospace() << __FUNCTION__ << ": wglCreateContextAttribsARB() failed (GL error code: 0x" - << hex << staticContext.opengl32.glGetError() << dec << ") for format: " << format << ", shared context: " << shared; + << Qt::hex << staticContext.opengl32.glGetError() << Qt::dec << ") for format: " << format << ", shared context: " << shared; qErrnoWarning("%s", qPrintable(message)); } return result; diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp index 878f55e56b..71ed33f85b 100644 --- a/src/plugins/platforms/windows/qwindowsinputcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsinputcontext.cpp @@ -657,9 +657,9 @@ void QWindowsInputContext::handleInputLanguageChanged(WPARAM wparam, LPARAM lpar m_locale = qt_localeFromLCID(m_languageId); emitLocaleChanged(); - qCDebug(lcQpaInputMethods) << __FUNCTION__ << hex << showbase + qCDebug(lcQpaInputMethods) << __FUNCTION__ << Qt::hex << Qt::showbase << oldLanguageId << "->" << newLanguageId << "Character set:" - << DWORD(wparam) << dec << noshowbase << m_locale; + << DWORD(wparam) << Qt::dec << Qt::noshowbase << m_locale; } /*! diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index 2c90b0484e..e896f9f0ee 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -324,7 +324,7 @@ QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) cons if (window->type() == Qt::Desktop) { QWindowsDesktopWindow *result = new QWindowsDesktopWindow(window); qCDebug(lcQpaWindows) << "Desktop window:" << window - << showbase << hex << result->winId() << noshowbase << dec << result->geometry(); + << Qt::showbase << Qt::hex << result->winId() << Qt::noshowbase << Qt::dec << result->geometry(); return result; } @@ -373,8 +373,8 @@ QPlatformWindow *QWindowsIntegration::createForeignWindow(QWindow *window, WId n screen = pScreen->screen(); if (screen && screen != window->screen()) window->setScreen(screen); - qCDebug(lcQpaWindows) << "Foreign window:" << window << showbase << hex - << result->winId() << noshowbase << dec << obtainedGeometry << screen; + qCDebug(lcQpaWindows) << "Foreign window:" << window << Qt::showbase << Qt::hex + << result->winId() << Qt::noshowbase << Qt::dec << obtainedGeometry << screen; return result; } diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp index c5af4d8042..44668cde78 100644 --- a/src/plugins/platforms/windows/qwindowskeymapper.cpp +++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp @@ -554,7 +554,7 @@ QDebug operator<<(QDebug d, const KeyboardLayoutItem &k) if (const quint32 qtKey = k.qtKey[i]) { d << '[' << i << ' '; QtDebugUtils::formatQFlags(d, ModsTbl[i]); - d << ' ' << hex << showbase << qtKey << dec << noshowbase << ' '; + d << ' ' << Qt::hex << Qt::showbase << qtKey << Qt::dec << Qt::noshowbase << ' '; QtDebugUtils::formatQEnum(d, Qt::Key(qtKey)); if (qtKey >= 32 && qtKey < 128) d << " '" << char(qtKey) << '\''; @@ -776,7 +776,7 @@ void QWindowsKeyMapper::updatePossibleKeyCodes(unsigned char *kbdBuffer, quint32 ::ToAscii(vk_key, scancode, kbdBuffer, reinterpret_cast(&buffer), 0); } qCDebug(lcQpaEvents) << __FUNCTION__ << "for virtual key=" - << hex << showbase << vk_key << dec << noshowbase << keyLayout[vk_key]; + << Qt::hex << Qt::showbase << vk_key << Qt::dec << Qt::noshowbase << keyLayout[vk_key]; } static inline QString messageKeyText(const MSG &msg) @@ -1384,7 +1384,7 @@ QList QWindowsKeyMapper::possibleKeys(const QKeyEvent *e) const } } qCDebug(lcQpaEvents) << __FUNCTION__ << e << "nativeVirtualKey=" - << showbase << hex << e->nativeVirtualKey() << dec << noshowbase + << Qt::showbase << Qt::hex << e->nativeVirtualKey() << Qt::dec << Qt::noshowbase << e->modifiers() << kbItem << "\n returns" << formatKeys(result); return result; } diff --git a/src/plugins/platforms/windows/qwindowsmenu.cpp b/src/plugins/platforms/windows/qwindowsmenu.cpp index 17a1b94101..e55e283fe1 100644 --- a/src/plugins/platforms/windows/qwindowsmenu.cpp +++ b/src/plugins/platforms/windows/qwindowsmenu.cpp @@ -896,8 +896,8 @@ void QWindowsMenuItem::formatDebug(QDebug &d) const d << ", parentMenu=" << static_cast(m_parentMenu); if (m_subMenu) d << ", subMenu=" << static_cast(m_subMenu); - d << ", tag=" << showbase << hex - << tag() << noshowbase << dec << ", id=" << m_id; + d << ", tag=" << Qt::showbase << Qt::hex + << tag() << Qt::noshowbase << Qt::dec << ", id=" << m_id; #if QT_CONFIG(shortcut) if (!m_shortcut.isEmpty()) d << ", shortcut=" << m_shortcut; @@ -933,7 +933,7 @@ void QWindowsMenu::formatDebug(QDebug &d) const if (m_parentMenu != nullptr) d << " [on menu]"; if (tag()) - d << ", tag=" << showbase << hex << tag() << noshowbase << dec; + d << ", tag=" << Qt::showbase << Qt::hex << tag() << Qt::noshowbase << Qt::dec; if (m_visible) d << " [visible]"; if (m_enabled) diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp index 737fd1d2a9..c4d53855a5 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp +++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp @@ -124,8 +124,8 @@ static inline QTouchDevice *createTouchDevice() return nullptr; const int tabletPc = GetSystemMetrics(SM_TABLETPC); const int maxTouchPoints = GetSystemMetrics(SM_MAXIMUMTOUCHES); - qCDebug(lcQpaEvents) << "Digitizers:" << hex << showbase << (digitizers & ~NID_READY) - << "Ready:" << (digitizers & NID_READY) << dec << noshowbase + qCDebug(lcQpaEvents) << "Digitizers:" << Qt::hex << Qt::showbase << (digitizers & ~NID_READY) + << "Ready:" << (digitizers & NID_READY) << Qt::dec << Qt::noshowbase << "Tablet PC:" << tabletPc << "Max touch points:" << maxTouchPoints; QTouchDevice *result = new QTouchDevice; result->setType(digitizers & NID_INTEGRATED_TOUCH diff --git a/src/plugins/platforms/windows/qwindowsole.cpp b/src/plugins/platforms/windows/qwindowsole.cpp index e9c3f2cbf6..fb6a74581a 100644 --- a/src/plugins/platforms/windows/qwindowsole.cpp +++ b/src/plugins/platforms/windows/qwindowsole.cpp @@ -110,7 +110,7 @@ QWindowsOleDataObject::GetData(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium) } if (QWindowsContext::verbose > 1 && lcQpaMime().isDebugEnabled()) - qCDebug(lcQpaMime) <<__FUNCTION__ << *pformatetc << "returns" << hex << showbase << quint64(hr); + qCDebug(lcQpaMime) <<__FUNCTION__ << *pformatetc << "returns" << Qt::hex << Qt::showbase << quint64(hr); return hr; } @@ -135,7 +135,7 @@ QWindowsOleDataObject::QueryGetData(LPFORMATETC pformatetc) ResultFromScode(S_OK) : ResultFromScode(S_FALSE); } if (QWindowsContext::verbose > 1) - qCDebug(lcQpaMime) << __FUNCTION__ << " returns 0x" << hex << int(hr); + qCDebug(lcQpaMime) << __FUNCTION__ << " returns 0x" << Qt::hex << int(hr); return hr; } @@ -163,7 +163,7 @@ QWindowsOleDataObject::SetData(LPFORMATETC pFormatetc, STGMEDIUM *pMedium, BOOL hr = ResultFromScode(S_OK); } if (QWindowsContext::verbose > 1) - qCDebug(lcQpaMime) << __FUNCTION__ << " returns 0x" << hex << int(hr); + qCDebug(lcQpaMime) << __FUNCTION__ << " returns 0x" << Qt::hex << int(hr); return hr; } diff --git a/src/plugins/platforms/windows/qwindowsopengltester.cpp b/src/plugins/platforms/windows/qwindowsopengltester.cpp index 840a3a11c4..35418a18e7 100644 --- a/src/plugins/platforms/windows/qwindowsopengltester.cpp +++ b/src/plugins/platforms/windows/qwindowsopengltester.cpp @@ -188,9 +188,9 @@ QDebug operator<<(QDebug d, const GpuDescription &gd) { QDebugStateSaver s(d); d.nospace(); - d << hex << showbase << "GpuDescription(vendorId=" << gd.vendorId + d << Qt::hex << Qt::showbase << "GpuDescription(vendorId=" << gd.vendorId << ", deviceId=" << gd.deviceId << ", subSysId=" << gd.subSysId - << dec << noshowbase << ", revision=" << gd.revision + << Qt::dec << Qt::noshowbase << ", revision=" << gd.revision << ", driver: " << gd.driverName << ", version=" << gd.driverVersion << ", " << gd.description << gd.gpuSuitableScreen << ')'; @@ -207,11 +207,11 @@ QString GpuDescription::toString() const << "\n Driver Name : " << driverName << "\n Driver Version : " << driverVersion.toString() << "\n Vendor ID : 0x" << qSetPadChar(QLatin1Char('0')) - << uppercasedigits << hex << qSetFieldWidth(4) << vendorId + << Qt::uppercasedigits << Qt::hex << qSetFieldWidth(4) << vendorId << "\n Device ID : 0x" << qSetFieldWidth(4) << deviceId << "\n SubSys ID : 0x" << qSetFieldWidth(8) << subSysId << "\n Revision ID : 0x" << qSetFieldWidth(4) << revision - << dec; + << Qt::dec; if (!gpuSuitableScreen.isEmpty()) str << "\nGL windows forced to screen: " << gpuSuitableScreen; return result; diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.cpp b/src/plugins/platforms/windows/qwindowspointerhandler.cpp index 9a8b5d5121..7da87a32d5 100644 --- a/src/plugins/platforms/windows/qwindowspointerhandler.cpp +++ b/src/plugins/platforms/windows/qwindowspointerhandler.cpp @@ -315,8 +315,8 @@ static QTouchDevice *createTouchDevice() return nullptr; const int tabletPc = GetSystemMetrics(SM_TABLETPC); const int maxTouchPoints = GetSystemMetrics(SM_MAXIMUMTOUCHES); - qCDebug(lcQpaEvents) << "Digitizers:" << hex << showbase << (digitizers & ~NID_READY) - << "Ready:" << (digitizers & NID_READY) << dec << noshowbase + qCDebug(lcQpaEvents) << "Digitizers:" << Qt::hex << Qt::showbase << (digitizers & ~NID_READY) + << "Ready:" << (digitizers & NID_READY) << Qt::dec << Qt::noshowbase << "Tablet PC:" << tabletPc << "Max touch points:" << maxTouchPoints; QTouchDevice *result = new QTouchDevice; result->setType(digitizers & NID_INTEGRATED_TOUCH @@ -469,19 +469,19 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd, QList touchPoints; if (QWindowsContext::verbose > 1) - qCDebug(lcQpaEvents).noquote().nospace() << showbase + qCDebug(lcQpaEvents).noquote().nospace() << Qt::showbase << __FUNCTION__ - << " message=" << hex << msg.message - << " count=" << dec << count; + << " message=" << Qt::hex << msg.message + << " count=" << Qt::dec << count; Qt::TouchPointStates allStates = 0; for (quint32 i = 0; i < count; ++i) { if (QWindowsContext::verbose > 1) - qCDebug(lcQpaEvents).noquote().nospace() << showbase + qCDebug(lcQpaEvents).noquote().nospace() << Qt::showbase << " TouchPoint id=" << touchInfo[i].pointerInfo.pointerId << " frame=" << touchInfo[i].pointerInfo.frameId - << " flags=" << hex << touchInfo[i].pointerInfo.pointerFlags; + << " flags=" << Qt::hex << touchInfo[i].pointerInfo.pointerFlags; QWindowSystemInterface::TouchPoint touchPoint; const quint32 pointerId = touchInfo[i].pointerInfo.pointerId; @@ -563,11 +563,11 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin const int z = 0; if (QWindowsContext::verbose > 1) - qCDebug(lcQpaEvents).noquote().nospace() << showbase + qCDebug(lcQpaEvents).noquote().nospace() << Qt::showbase << __FUNCTION__ << " sourceDevice=" << sourceDevice << " globalPos=" << globalPos << " localPos=" << localPos << " hiResGlobalPos=" << hiResGlobalPos - << " message=" << hex << msg.message - << " flags=" << hex << penInfo->pointerInfo.pointerFlags; + << " message=" << Qt::hex << msg.message + << " flags=" << Qt::hex << penInfo->pointerInfo.pointerFlags; const QTabletEvent::TabletDevice device = QTabletEvent::Stylus; QTabletEvent::PointerType type; diff --git a/src/plugins/platforms/windows/qwindowstabletsupport.cpp b/src/plugins/platforms/windows/qwindowstabletsupport.cpp index fa209f09c4..84c963af94 100644 --- a/src/plugins/platforms/windows/qwindowstabletsupport.cpp +++ b/src/plugins/platforms/windows/qwindowstabletsupport.cpp @@ -146,13 +146,13 @@ QDebug operator<<(QDebug d, const LOGCONTEXT &lc) QDebugStateSaver saver(d); d.nospace(); d << "LOGCONTEXT(\"" << QString::fromWCharArray(lc.lcName) << "\", options=0x" - << hex << lc.lcOptions << dec; + << Qt::hex << lc.lcOptions << Qt::dec; formatOptions(d, lc.lcOptions); - d << ", status=0x" << hex << lc.lcStatus << ", device=0x" << lc.lcDevice - << dec << ", PktRate=" << lc.lcPktRate + d << ", status=0x" << Qt::hex << lc.lcStatus << ", device=0x" << lc.lcDevice + << Qt::dec << ", PktRate=" << lc.lcPktRate << ", PktData=" << lc.lcPktData << ", PktMode=" << lc.lcPktMode - << ", MoveMask=0x" << hex << lc.lcMoveMask << ", BtnDnMask=0x" << lc.lcBtnDnMask - << ", BtnUpMask=0x" << lc.lcBtnUpMask << dec << ", SysMode=" << lc.lcSysMode + << ", MoveMask=0x" << Qt::hex << lc.lcMoveMask << ", BtnDnMask=0x" << lc.lcBtnDnMask + << ", BtnUpMask=0x" << lc.lcBtnUpMask << Qt::dec << ", SysMode=" << lc.lcSysMode << ", InOrg=(" << lc.lcInOrgX << ", " << lc.lcInOrgY << ", " << lc.lcInOrgZ << "), InExt=(" << lc.lcInExtX << ", " << lc.lcInExtY << ", " << lc.lcInExtZ << ") OutOrg=(" << lc.lcOutOrgX << ", " << lc.lcOutOrgY << ", " @@ -305,7 +305,7 @@ QString QWindowsTabletSupport::description() const << '.' << (specificationVersion & 0xFF) << " implementation: v" << (implementationVersion >> 8) << '.' << (implementationVersion & 0xFF) << ' ' << devices << " device(s), " << cursors << " cursor(s), " - << extensions << " extensions" << ", options: 0x" << hex << opts << dec; + << extensions << " extensions" << ", options: 0x" << Qt::hex << opts << Qt::dec; formatOptions(str, opts); if (m_tiltSupport) str << " tilt"; diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 338e594c7b..d55545af42 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -238,7 +238,7 @@ QDebug operator<<(QDebug d, const WINDOWPLACEMENT &wp) QDebugStateSaver saver(d); d.nospace(); d.noquote(); - d << "WINDOWPLACEMENT(flags=0x" << hex << wp.flags << dec << ", showCmd=" + d << "WINDOWPLACEMENT(flags=0x" << Qt::hex << wp.flags << Qt::dec << ", showCmd=" << wp.showCmd << ", ptMinPosition=" << wp.ptMinPosition << ", ptMaxPosition=" << wp.ptMaxPosition << ", rcNormalPosition=" << wp.rcNormalPosition; return d; @@ -248,7 +248,7 @@ QDebug operator<<(QDebug d, const GUID &guid) { QDebugStateSaver saver(d); d.nospace(); - d << '{' << hex << uppercasedigits << qSetPadChar(QLatin1Char('0')) + d << '{' << Qt::hex << Qt::uppercasedigits << qSetPadChar(QLatin1Char('0')) << qSetFieldWidth(8) << guid.Data1 << qSetFieldWidth(0) << '-' << qSetFieldWidth(4) << guid.Data2 << qSetFieldWidth(0) << '-' << qSetFieldWidth(4) @@ -883,7 +883,7 @@ QMargins QWindowsGeometryHint::frame(DWORD style, DWORD exStyle) const QMargins result(qAbs(rect.left), qAbs(rect.top), qAbs(rect.right), qAbs(rect.bottom)); qCDebug(lcQpaWindows).nospace() << __FUNCTION__ << " style=" - << showbase << hex << style << " exStyle=" << exStyle << dec << noshowbase + << Qt::showbase << Qt::hex << style << " exStyle=" << exStyle << Qt::dec << Qt::noshowbase << ' ' << rect << ' ' << result; return result; } diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp index 899081e752..81b889a80f 100644 --- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp +++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp @@ -636,13 +636,13 @@ static void dumpNativeWindowsRecursion(const QXcbConnection *connection, xcb_win const QChar oldPadChar =str.padChar(); str.setFieldWidth(8); str.setPadChar(QLatin1Char('0')); - str << hex << window; + str << Qt::hex << window; str.setFieldWidth(oldFieldWidth); str.setPadChar(oldPadChar); - str << dec << " \"" + str << Qt::dec << " \"" << QXcbWindow::windowTitle(connection, window) << "\" " - << geom.width() << 'x' << geom.height() << forcesign << geom.x() << geom.y() - << noforcesign << '\n'; + << geom.width() << 'x' << geom.height() << Qt::forcesign << geom.x() << geom.y() + << Qt::noforcesign << '\n'; auto reply = Q_XCB_REPLY(xcb_query_tree, conn, window); if (reply) { diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp index 0fa0e8cd7b..bfc105a040 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.cpp +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -915,7 +915,7 @@ QByteArray QXcbScreen::getEdid() const static inline void formatRect(QDebug &debug, const QRect r) { debug << r.width() << 'x' << r.height() - << forcesign << r.x() << r.y() << noforcesign; + << Qt::forcesign << r.x() << r.y() << Qt::noforcesign; } static inline void formatSizeF(QDebug &debug, const QSizeF s) @@ -929,7 +929,7 @@ QDebug operator<<(QDebug debug, const QXcbScreen *screen) debug.nospace(); debug << "QXcbScreen(" << (const void *)screen; if (screen) { - debug << fixed << qSetRealNumberPrecision(1); + debug << Qt::fixed << qSetRealNumberPrecision(1); debug << ", name=" << screen->name(); debug << ", geometry="; formatRect(debug, screen->geometry()); @@ -947,7 +947,7 @@ QDebug operator<<(QDebug debug, const QXcbScreen *screen) debug << "), orientation=" << screen->orientation(); debug << ", depth=" << screen->depth(); debug << ", refreshRate=" << screen->refreshRate(); - debug << ", root=" << hex << screen->root(); + debug << ", root=" << Qt::hex << screen->root(); debug << ", windowManagerName=" << screen->windowManagerName(); } debug << ')'; diff --git a/src/sql/doc/snippets/sqldatabase/sqldatabase.cpp b/src/sql/doc/snippets/sqldatabase/sqldatabase.cpp index a27feb1505..bba0487452 100644 --- a/src/sql/doc/snippets/sqldatabase/sqldatabase.cpp +++ b/src/sql/doc/snippets/sqldatabase/sqldatabase.cpp @@ -213,7 +213,7 @@ void QSqlQuery_snippets() while (i.hasNext()) { i.next(); cout << i.key().toUtf8().data() << ": " - << i.value().toString().toUtf8().data() << endl; + << i.value().toString().toUtf8().data() << Qt::endl; } //! [14] } @@ -223,7 +223,7 @@ void QSqlQuery_snippets() //! [15] QList list = query.boundValues().values(); for (int i = 0; i < list.size(); ++i) - cout << i << ": " << list.at(i).toString().toUtf8().data() << endl; + cout << i << ": " << list.at(i).toString().toUtf8().data() << Qt::endl; //! [15] } } diff --git a/src/sql/kernel/qsqlrecord.cpp b/src/sql/kernel/qsqlrecord.cpp index ecbe3eacdb..c4dc5d1adb 100644 --- a/src/sql/kernel/qsqlrecord.cpp +++ b/src/sql/kernel/qsqlrecord.cpp @@ -535,7 +535,7 @@ QDebug operator<<(QDebug dbg, const QSqlRecord &r) dbg << "QSqlRecord(" << count << ')'; for (int i = 0; i < count; ++i) { dbg.nospace(); - dbg << '\n' << qSetFieldWidth(2) << right << i << left << qSetFieldWidth(0) << ':'; + dbg << '\n' << qSetFieldWidth(2) << Qt::right << i << Qt::left << qSetFieldWidth(0) << ':'; dbg.space(); dbg << r.field(i) << r.value(i).toString(); } diff --git a/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp b/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp index ea410cd257..ce4232f3e8 100644 --- a/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp +++ b/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp @@ -161,22 +161,22 @@ static QString moc(const QString &name) static QTextStream &writeHeader(QTextStream &ts, bool changesWillBeLost) { - ts << "/*" << endl - << " * This file was generated by " PROGRAMNAME " version " PROGRAMVERSION << endl - << " * Command line was: " << commandLine << endl - << " *" << endl - << " * " PROGRAMNAME " is " PROGRAMCOPYRIGHT << endl - << " *" << endl - << " * This is an auto-generated file." << endl; + ts << "/*" << Qt::endl + << " * This file was generated by " PROGRAMNAME " version " PROGRAMVERSION << Qt::endl + << " * Command line was: " << commandLine << Qt::endl + << " *" << Qt::endl + << " * " PROGRAMNAME " is " PROGRAMCOPYRIGHT << Qt::endl + << " *" << Qt::endl + << " * This is an auto-generated file." << Qt::endl; if (changesWillBeLost) - ts << " * Do not edit! All changes made to it will be lost." << endl; + ts << " * Do not edit! All changes made to it will be lost." << Qt::endl; else - ts << " * This file may have been hand-edited. Look for HAND-EDIT comments" << endl - << " * before re-generating it." << endl; + ts << " * This file may have been hand-edited. Look for HAND-EDIT comments" << Qt::endl + << " * before re-generating it." << Qt::endl; - ts << " */" << endl - << endl; + ts << " */" << Qt::endl + << Qt::endl; return ts; } @@ -466,66 +466,66 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf } includeGuard = QString(QLatin1String("%1")) .arg(includeGuard); - hs << "#ifndef " << includeGuard << endl - << "#define " << includeGuard << endl - << endl; + hs << "#ifndef " << includeGuard << Qt::endl + << "#define " << includeGuard << Qt::endl + << Qt::endl; // include our stuff: - hs << "#include " << endl + hs << "#include " << Qt::endl << includeList - << "#include " << endl; + << "#include " << Qt::endl; for (const QString &include : qAsConst(includes)) { - hs << "#include \"" << include << "\"" << endl; + hs << "#include \"" << include << "\"" << Qt::endl; if (headerName.isEmpty()) - cs << "#include \"" << include << "\"" << endl; + cs << "#include \"" << include << "\"" << Qt::endl; } - hs << endl; + hs << Qt::endl; if (cppName != headerName) { if (!headerName.isEmpty() && headerName != QLatin1String("-")) - cs << "#include \"" << headerName << "\"" << endl << endl; + cs << "#include \"" << headerName << "\"" << Qt::endl << Qt::endl; } for (const QDBusIntrospection::Interface *interface : interfaces) { QString className = classNameForInterface(interface->name, Proxy); // comment: - hs << "/*" << endl - << " * Proxy class for interface " << interface->name << endl - << " */" << endl; - cs << "/*" << endl - << " * Implementation of interface class " << className << endl - << " */" << endl - << endl; + hs << "/*" << Qt::endl + << " * Proxy class for interface " << interface->name << Qt::endl + << " */" << Qt::endl; + cs << "/*" << Qt::endl + << " * Implementation of interface class " << className << Qt::endl + << " */" << Qt::endl + << Qt::endl; // class header: - hs << "class " << className << ": public QDBusAbstractInterface" << endl - << "{" << endl - << " Q_OBJECT" << endl; + hs << "class " << className << ": public QDBusAbstractInterface" << Qt::endl + << "{" << Qt::endl + << " Q_OBJECT" << Qt::endl; // the interface name - hs << "public:" << endl - << " static inline const char *staticInterfaceName()" << endl - << " { return \"" << interface->name << "\"; }" << endl - << endl; + hs << "public:" << Qt::endl + << " static inline const char *staticInterfaceName()" << Qt::endl + << " { return \"" << interface->name << "\"; }" << Qt::endl + << Qt::endl; // constructors/destructors: - hs << "public:" << endl - << " " << className << "(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr);" << endl - << endl - << " ~" << className << "();" << endl - << endl; - cs << className << "::" << className << "(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)" << endl - << " : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)" << endl - << "{" << endl - << "}" << endl - << endl - << className << "::~" << className << "()" << endl - << "{" << endl - << "}" << endl - << endl; + hs << "public:" << Qt::endl + << " " << className << "(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr);" << Qt::endl + << Qt::endl + << " ~" << className << "();" << Qt::endl + << Qt::endl; + cs << className << "::" << className << "(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)" << Qt::endl + << " : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)" << Qt::endl + << "{" << Qt::endl + << "}" << Qt::endl + << Qt::endl + << className << "::~" << className << "()" << Qt::endl + << "{" << Qt::endl + << "}" << Qt::endl + << Qt::endl; // properties: for (const QDBusIntrospection::Property &property : interface->properties) { @@ -545,27 +545,27 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf // it's writeable hs << " WRITE " << setter; - hs << ")" << endl; + hs << ")" << Qt::endl; // getter: if (property.access != QDBusIntrospection::Property::Write) { - hs << " inline " << type << " " << getter << "() const" << endl + hs << " inline " << type << " " << getter << "() const" << Qt::endl << " { return qvariant_cast< " << type << " >(property(\"" - << property.name << "\")); }" << endl; + << property.name << "\")); }" << Qt::endl; } // setter: if (property.access != QDBusIntrospection::Property::Read) { - hs << " inline void " << setter << "(" << constRefArg(type) << "value)" << endl + hs << " inline void " << setter << "(" << constRefArg(type) << "value)" << Qt::endl << " { setProperty(\"" << property.name - << "\", QVariant::fromValue(value)); }" << endl; + << "\", QVariant::fromValue(value)); }" << Qt::endl; } - hs << endl; + hs << Qt::endl; } // methods: - hs << "public Q_SLOTS: // METHODS" << endl; + hs << "public Q_SLOTS: // METHODS" << Qt::endl; for (const QDBusIntrospection::Method &method : interface->methods) { bool isDeprecated = method.annotations.value(QLatin1String("org.freedesktop.DBus.Deprecated")) == QLatin1String("true"); bool isNoReply = @@ -595,26 +595,26 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf QStringList argNames = makeArgNames(method.inputArgs); writeArgList(hs, argNames, method.annotations, method.inputArgs); - hs << ")" << endl - << " {" << endl - << " QList argumentList;" << endl; + hs << ")" << Qt::endl + << " {" << Qt::endl + << " QList argumentList;" << Qt::endl; if (!method.inputArgs.isEmpty()) { hs << " argumentList"; for (int argPos = 0; argPos < method.inputArgs.count(); ++argPos) hs << " << QVariant::fromValue(" << argNames.at(argPos) << ')'; - hs << ";" << endl; + hs << ";" << Qt::endl; } if (isNoReply) hs << " callWithArgumentList(QDBus::NoBlock, " - << "QStringLiteral(\"" << method.name << "\"), argumentList);" << endl; + << "QStringLiteral(\"" << method.name << "\"), argumentList);" << Qt::endl; else hs << " return asyncCallWithArgumentList(QStringLiteral(\"" - << method.name << "\"), argumentList);" << endl; + << method.name << "\"), argumentList);" << Qt::endl; // close the function: - hs << " }" << endl; + hs << " }" << Qt::endl; if (method.outputArgs.count() > 1) { // generate the old-form QDBusReply methods with multiple incoming parameters @@ -627,39 +627,39 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf QStringList argNames = makeArgNames(method.inputArgs, method.outputArgs); writeArgList(hs, argNames, method.annotations, method.inputArgs, method.outputArgs); - hs << ")" << endl - << " {" << endl - << " QList argumentList;" << endl; + hs << ")" << Qt::endl + << " {" << Qt::endl + << " QList argumentList;" << Qt::endl; int argPos = 0; if (!method.inputArgs.isEmpty()) { hs << " argumentList"; for (argPos = 0; argPos < method.inputArgs.count(); ++argPos) hs << " << QVariant::fromValue(" << argNames.at(argPos) << ')'; - hs << ";" << endl; + hs << ";" << Qt::endl; } hs << " QDBusMessage reply = callWithArgumentList(QDBus::Block, " - << "QStringLiteral(\"" << method.name << "\"), argumentList);" << endl; + << "QStringLiteral(\"" << method.name << "\"), argumentList);" << Qt::endl; argPos++; hs << " if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().count() == " - << method.outputArgs.count() << ") {" << endl; + << method.outputArgs.count() << ") {" << Qt::endl; // yes, starting from 1 for (int i = 1; i < method.outputArgs.count(); ++i) hs << " " << argNames.at(argPos++) << " = qdbus_cast<" << templateArg(qtTypeName(method.outputArgs.at(i).type, method.annotations, i, "Out")) - << ">(reply.arguments().at(" << i << "));" << endl; - hs << " }" << endl - << " return reply;" << endl - << " }" << endl; + << ">(reply.arguments().at(" << i << "));" << Qt::endl; + hs << " }" << Qt::endl + << " return reply;" << Qt::endl + << " }" << Qt::endl; } - hs << endl; + hs << Qt::endl; } - hs << "Q_SIGNALS: // SIGNALS" << endl; + hs << "Q_SIGNALS: // SIGNALS" << Qt::endl; for (const QDBusIntrospection::Signal &signal : interface->signals_) { hs << " "; if (signal.annotations.value(QLatin1String("org.freedesktop.DBus.Deprecated")) == @@ -671,12 +671,12 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf QStringList argNames = makeArgNames(signal.outputArgs); writeSignalArgList(hs, argNames, signal.annotations, signal.outputArgs); - hs << ");" << endl; // finished for header + hs << ");" << Qt::endl; // finished for header } // close the class: - hs << "};" << endl - << endl; + hs << "};" << Qt::endl + << Qt::endl; } if (!skipNamespaces) { @@ -698,17 +698,17 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf // i parts matched // close last.arguments().count() - i namespaces: for (int j = i; j < last.count(); ++j) - hs << QString((last.count() - j - 1 + i) * 2, QLatin1Char(' ')) << "}" << endl; + hs << QString((last.count() - j - 1 + i) * 2, QLatin1Char(' ')) << "}" << Qt::endl; // open current.arguments().count() - i namespaces for (int j = i; j < current.count(); ++j) - hs << QString(j * 2, QLatin1Char(' ')) << "namespace " << current.at(j) << " {" << endl; + hs << QString(j * 2, QLatin1Char(' ')) << "namespace " << current.at(j) << " {" << Qt::endl; // add this class: if (!name.isEmpty()) { hs << QString(current.count() * 2, QLatin1Char(' ')) << "typedef ::" << classNameForInterface(it->constData()->name, Proxy) - << " " << name << ";" << endl; + << " " << name << ";" << Qt::endl; } if (it == interfaces.constEnd()) @@ -719,12 +719,12 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf } // close the include guard - hs << "#endif" << endl; + hs << "#endif" << Qt::endl; QString mocName = moc(filename); if (includeMocs && !mocName.isEmpty()) - cs << endl - << "#include \"" << mocName << "\"" << endl; + cs << Qt::endl + << "#include \"" << mocName << "\"" << Qt::endl; cs.flush(); hs.flush(); @@ -772,36 +772,36 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte } includeGuard = QString(QLatin1String("%1")) .arg(includeGuard); - hs << "#ifndef " << includeGuard << endl - << "#define " << includeGuard << endl - << endl; + hs << "#ifndef " << includeGuard << Qt::endl + << "#define " << includeGuard << Qt::endl + << Qt::endl; // include our stuff: - hs << "#include " << endl; + hs << "#include " << Qt::endl; if (cppName == headerName) - hs << "#include " << endl - << "#include " << endl; - hs << "#include " << endl; + hs << "#include " << Qt::endl + << "#include " << Qt::endl; + hs << "#include " << Qt::endl; for (const QString &include : qAsConst(includes)) { - hs << "#include \"" << include << "\"" << endl; + hs << "#include \"" << include << "\"" << Qt::endl; if (headerName.isEmpty()) - cs << "#include \"" << include << "\"" << endl; + cs << "#include \"" << include << "\"" << Qt::endl; } if (cppName != headerName) { if (!headerName.isEmpty() && headerName != QLatin1String("-")) - cs << "#include \"" << headerName << "\"" << endl; + cs << "#include \"" << headerName << "\"" << Qt::endl; - cs << "#include " << endl + cs << "#include " << Qt::endl << includeList - << endl; + << Qt::endl; hs << forwardDeclarations; } else { hs << includeList; } - hs << endl; + hs << Qt::endl; QString parent = parentClassName; if (parentClassName.isEmpty()) @@ -811,47 +811,47 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte QString className = classNameForInterface(interface->name, Adaptor); // comment: - hs << "/*" << endl - << " * Adaptor class for interface " << interface->name << endl - << " */" << endl; - cs << "/*" << endl - << " * Implementation of adaptor class " << className << endl - << " */" << endl - << endl; + hs << "/*" << Qt::endl + << " * Adaptor class for interface " << interface->name << Qt::endl + << " */" << Qt::endl; + cs << "/*" << Qt::endl + << " * Implementation of adaptor class " << className << Qt::endl + << " */" << Qt::endl + << Qt::endl; // class header: - hs << "class " << className << ": public QDBusAbstractAdaptor" << endl - << "{" << endl - << " Q_OBJECT" << endl - << " Q_CLASSINFO(\"D-Bus Interface\", \"" << interface->name << "\")" << endl - << " Q_CLASSINFO(\"D-Bus Introspection\", \"\"" << endl + hs << "class " << className << ": public QDBusAbstractAdaptor" << Qt::endl + << "{" << Qt::endl + << " Q_OBJECT" << Qt::endl + << " Q_CLASSINFO(\"D-Bus Interface\", \"" << interface->name << "\")" << Qt::endl + << " Q_CLASSINFO(\"D-Bus Introspection\", \"\"" << Qt::endl << stringify(interface->introspection) - << " \"\")" << endl - << "public:" << endl - << " " << className << "(" << parent << " *parent);" << endl - << " virtual ~" << className << "();" << endl - << endl; + << " \"\")" << Qt::endl + << "public:" << Qt::endl + << " " << className << "(" << parent << " *parent);" << Qt::endl + << " virtual ~" << className << "();" << Qt::endl + << Qt::endl; if (!parentClassName.isEmpty()) - hs << " inline " << parent << " *parent() const" << endl - << " { return static_cast<" << parent << " *>(QObject::parent()); }" << endl - << endl; + hs << " inline " << parent << " *parent() const" << Qt::endl + << " { return static_cast<" << parent << " *>(QObject::parent()); }" << Qt::endl + << Qt::endl; // constructor/destructor - cs << className << "::" << className << "(" << parent << " *parent)" << endl - << " : QDBusAbstractAdaptor(parent)" << endl - << "{" << endl - << " // constructor" << endl - << " setAutoRelaySignals(true);" << endl - << "}" << endl - << endl - << className << "::~" << className << "()" << endl - << "{" << endl - << " // destructor" << endl - << "}" << endl - << endl; - - hs << "public: // PROPERTIES" << endl; + cs << className << "::" << className << "(" << parent << " *parent)" << Qt::endl + << " : QDBusAbstractAdaptor(parent)" << Qt::endl + << "{" << Qt::endl + << " // constructor" << Qt::endl + << " setAutoRelaySignals(true);" << Qt::endl + << "}" << Qt::endl + << Qt::endl + << className << "::~" << className << "()" << Qt::endl + << "{" << Qt::endl + << " // destructor" << Qt::endl + << "}" << Qt::endl + << Qt::endl; + + hs << "public: // PROPERTIES" << Qt::endl; for (const QDBusIntrospection::Property &property : interface->properties) { QByteArray type = qtTypeName(property.type, property.annotations); QString constRefType = constRefArg(type); @@ -863,38 +863,38 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte hs << " READ " << getter; if (property.access != QDBusIntrospection::Property::Read) hs << " WRITE " << setter; - hs << ")" << endl; + hs << ")" << Qt::endl; // getter: if (property.access != QDBusIntrospection::Property::Write) { - hs << " " << type << " " << getter << "() const;" << endl; + hs << " " << type << " " << getter << "() const;" << Qt::endl; cs << type << " " - << className << "::" << getter << "() const" << endl - << "{" << endl - << " // get the value of property " << property.name << endl - << " return qvariant_cast< " << type <<" >(parent()->property(\"" << property.name << "\"));" << endl - << "}" << endl - << endl; + << className << "::" << getter << "() const" << Qt::endl + << "{" << Qt::endl + << " // get the value of property " << property.name << Qt::endl + << " return qvariant_cast< " << type <<" >(parent()->property(\"" << property.name << "\"));" << Qt::endl + << "}" << Qt::endl + << Qt::endl; } // setter if (property.access != QDBusIntrospection::Property::Read) { - hs << " void " << setter << "(" << constRefType << "value);" << endl; - cs << "void " << className << "::" << setter << "(" << constRefType << "value)" << endl - << "{" << endl - << " // set the value of property " << property.name << endl + hs << " void " << setter << "(" << constRefType << "value);" << Qt::endl; + cs << "void " << className << "::" << setter << "(" << constRefType << "value)" << Qt::endl + << "{" << Qt::endl + << " // set the value of property " << property.name << Qt::endl << " parent()->setProperty(\"" << property.name << "\", QVariant::fromValue(value"; if (constRefType.contains(QLatin1String("QDBusVariant"))) cs << ".variant()"; - cs << "));" << endl - << "}" << endl - << endl; + cs << "));" << Qt::endl + << "}" << Qt::endl + << Qt::endl; } - hs << endl; + hs << Qt::endl; } - hs << "public Q_SLOTS: // METHODS" << endl; + hs << "public Q_SLOTS: // METHODS" << Qt::endl; for (const QDBusIntrospection::Method &method : interface->methods) { bool isNoReply = method.annotations.value(QLatin1String(ANNOTATION_NO_WAIT)) == QLatin1String("true"); @@ -930,10 +930,10 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte writeArgList(hs, argNames, method.annotations, method.inputArgs, method.outputArgs); writeArgList(cs, argNames, method.annotations, method.inputArgs, method.outputArgs); - hs << ");" << endl; // finished for header - cs << ")" << endl - << "{" << endl - << " // handle method call " << interface->name << "." << methodName(method) << endl; + hs << ");" << Qt::endl; // finished for header + cs << ")" << Qt::endl + << "{" << Qt::endl + << " // handle method call " << interface->name << "." << methodName(method) << Qt::endl; // make the call bool usingInvokeMethod = false; @@ -945,7 +945,7 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte // we are using QMetaObject::invokeMethod if (!returnType.isEmpty()) cs << " " << returnType << " " << argNames.at(method.inputArgs.count()) - << ";" << endl; + << ";" << Qt::endl; static const char invoke[] = " QMetaObject::invokeMethod(parent(), \""; cs << invoke << name << "\""; @@ -966,10 +966,10 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte << argNames.at(i) << ")"; - cs << ");" << endl; + cs << ");" << Qt::endl; if (!returnType.isEmpty()) - cs << " return " << argNames.at(method.inputArgs.count()) << ";" << endl; + cs << " return " << argNames.at(method.inputArgs.count()) << ";" << Qt::endl; } else { if (parentClassName.isEmpty()) cs << " //"; @@ -997,13 +997,13 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte first = false; } - cs << ");" << endl; + cs << ");" << Qt::endl; } - cs << "}" << endl - << endl; + cs << "}" << Qt::endl + << Qt::endl; } - hs << "Q_SIGNALS: // SIGNALS" << endl; + hs << "Q_SIGNALS: // SIGNALS" << Qt::endl; for (const QDBusIntrospection::Signal &signal : interface->signals_) { hs << " "; if (signal.annotations.value(QLatin1String("org.freedesktop.DBus.Deprecated")) == @@ -1015,21 +1015,21 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte QStringList argNames = makeArgNames(signal.outputArgs); writeSignalArgList(hs, argNames, signal.annotations, signal.outputArgs); - hs << ");" << endl; // finished for header + hs << ");" << Qt::endl; // finished for header } // close the class: - hs << "};" << endl - << endl; + hs << "};" << Qt::endl + << Qt::endl; } // close the include guard - hs << "#endif" << endl; + hs << "#endif" << Qt::endl; QString mocName = moc(filename); if (includeMocs && !mocName.isEmpty()) - cs << endl - << "#include \"" << mocName << "\"" << endl; + cs << Qt::endl + << "#include \"" << mocName << "\"" << Qt::endl; cs.flush(); hs.flush(); diff --git a/src/tools/qlalr/cppgenerator.cpp b/src/tools/qlalr/cppgenerator.cpp index 508db696b1..10b2d173ab 100644 --- a/src/tools/qlalr/cppgenerator.cpp +++ b/src/tools/qlalr/cppgenerator.cpp @@ -43,7 +43,7 @@ void generateSeparator(int i, QTextStream &out) if (!(i % 10)) { if (i) out << ","; - out << endl << " "; + out << Qt::endl << " "; } else { out << ", "; } @@ -187,14 +187,14 @@ void CppGenerator::operator () () { if (verbose) qout() << "*** Warning. Found a reduce/reduce conflict in state " << q << " on token ``" << s << "'' between rule " - << r << " and " << -u << endl; + << r << " and " << -u << Qt::endl; ++reduce_reduce_conflict_count; u = qMax (u, -r); if (verbose) - qout() << "\tresolved using rule " << -u << endl; + qout() << "\tresolved using rule " << -u << Qt::endl; } else if (u > 0) @@ -227,7 +227,7 @@ void CppGenerator::operator () () ++shift_reduce_conflict_count; if (verbose) - qout() << "*** Warning. Found a shift/reduce conflict in state " << q << " on token ``" << s << "'' with rule " << r << endl; + qout() << "*** Warning. Found a shift/reduce conflict in state " << q << " on token ``" << s << "'' with rule " << r << Qt::endl; } } } @@ -238,11 +238,11 @@ void CppGenerator::operator () () { if (shift_reduce_conflict_count != grammar.expected_shift_reduce || reduce_reduce_conflict_count != grammar.expected_reduce_reduce) - qerr() << "*** Conflicts: " << shift_reduce_conflict_count << " shift/reduce, " << reduce_reduce_conflict_count << " reduce/reduce" << endl; + qerr() << "*** Conflicts: " << shift_reduce_conflict_count << " shift/reduce, " << reduce_reduce_conflict_count << " reduce/reduce" << Qt::endl; if (verbose) - qout() << endl << "*** Conflicts: " << shift_reduce_conflict_count << " shift/reduce, " << reduce_reduce_conflict_count << " reduce/reduce" << endl - << endl; + qout() << Qt::endl << "*** Conflicts: " << shift_reduce_conflict_count << " shift/reduce, " << reduce_reduce_conflict_count << " reduce/reduce" << Qt::endl + << Qt::endl; } QBitArray used_rules (grammar.rules.count ()); @@ -266,7 +266,7 @@ void CppGenerator::operator () () RulePointer rule = grammar.rules.begin () + i; if (rule != grammar.goal) - qerr() << "*** Warning: Rule ``" << *rule << "'' is useless!" << endl; + qerr() << "*** Warning: Rule ``" << *rule << "'' is useless!" << Qt::endl; } } @@ -348,26 +348,26 @@ void CppGenerator::operator () () { out << copyrightHeader() << privateCopyrightHeader() - << endl; + << Qt::endl; } out << "// This file was generated by qlalr - DO NOT EDIT!\n"; - out << startIncludeGuard(grammar.merged_output) << endl; + out << startIncludeGuard(grammar.merged_output) << Qt::endl; if (copyright) { - out << "#if defined(ERROR)" << endl - << "# undef ERROR" << endl - << "#endif" << endl << endl; + out << "#if defined(ERROR)" << Qt::endl + << "# undef ERROR" << Qt::endl + << "#endif" << Qt::endl << Qt::endl; } generateDecl (out); generateImpl (out); out << p.decls(); out << p.impls(); - out << endl; + out << Qt::endl; - out << endIncludeGuard(grammar.merged_output) << endl; + out << endIncludeGuard(grammar.merged_output) << Qt::endl; return; } @@ -388,24 +388,24 @@ void CppGenerator::operator () () { out << copyrightHeader() << privateCopyrightHeader() - << endl; + << Qt::endl; } out << "// This file was generated by qlalr - DO NOT EDIT!\n"; - out << "#ifndef " << prot << endl - << "#define " << prot << endl - << endl; + out << "#ifndef " << prot << Qt::endl + << "#define " << prot << Qt::endl + << Qt::endl; if (copyright) { - out << "#include " << endl << endl; - out << "QT_BEGIN_NAMESPACE" << endl << endl; + out << "#include " << Qt::endl << Qt::endl; + out << "QT_BEGIN_NAMESPACE" << Qt::endl << Qt::endl; } generateDecl (out); if (copyright) - out << "QT_END_NAMESPACE" << endl; + out << "QT_END_NAMESPACE" << Qt::endl; - out << "#endif // " << prot << endl << endl; + out << "#endif // " << prot << Qt::endl << Qt::endl; } // end decls { // bits... @@ -419,12 +419,12 @@ void CppGenerator::operator () () out << "// This file was generated by qlalr - DO NOT EDIT!\n"; - out << "#include \"" << declFileName << "\"" << endl << endl; + out << "#include \"" << declFileName << "\"" << Qt::endl << Qt::endl; if (copyright) - out << "QT_BEGIN_NAMESPACE" << endl << endl; + out << "QT_BEGIN_NAMESPACE" << Qt::endl << Qt::endl; generateImpl(out); if (copyright) - out << "QT_END_NAMESPACE" << endl; + out << "QT_END_NAMESPACE" << Qt::endl; } // end bits @@ -455,10 +455,10 @@ QString CppGenerator::debugInfoProt() const void CppGenerator::generateDecl (QTextStream &out) { - out << "class " << grammar.table_name << endl - << "{" << endl - << "public:" << endl - << " enum VariousConstants {" << endl; + out << "class " << grammar.table_name << Qt::endl + << "{" << Qt::endl + << "public:" << Qt::endl + << " enum VariousConstants {" << Qt::endl; for (const Name &t : qAsConst(grammar.terminals)) { @@ -474,62 +474,62 @@ void CppGenerator::generateDecl (QTextStream &out) else name.prepend (grammar.token_prefix); - out << " " << name << " = " << value << "," << endl; + out << " " << name << " = " << value << "," << Qt::endl; } - out << endl - << " ACCEPT_STATE = " << accept_state << "," << endl - << " RULE_COUNT = " << grammar.rules.size () << "," << endl - << " STATE_COUNT = " << state_count << "," << endl - << " TERMINAL_COUNT = " << terminal_count << "," << endl - << " NON_TERMINAL_COUNT = " << non_terminal_count << "," << endl - << endl - << " GOTO_INDEX_OFFSET = " << compressed_action.index.size () << "," << endl - << " GOTO_INFO_OFFSET = " << compressed_action.info.size () << "," << endl - << " GOTO_CHECK_OFFSET = " << compressed_action.check.size () << endl - << " };" << endl - << endl - << " static const char *const spell[];" << endl - << " static const short lhs[];" << endl - << " static const short rhs[];" << endl; + out << Qt::endl + << " ACCEPT_STATE = " << accept_state << "," << Qt::endl + << " RULE_COUNT = " << grammar.rules.size () << "," << Qt::endl + << " STATE_COUNT = " << state_count << "," << Qt::endl + << " TERMINAL_COUNT = " << terminal_count << "," << Qt::endl + << " NON_TERMINAL_COUNT = " << non_terminal_count << "," << Qt::endl + << Qt::endl + << " GOTO_INDEX_OFFSET = " << compressed_action.index.size () << "," << Qt::endl + << " GOTO_INFO_OFFSET = " << compressed_action.info.size () << "," << Qt::endl + << " GOTO_CHECK_OFFSET = " << compressed_action.check.size () << Qt::endl + << " };" << Qt::endl + << Qt::endl + << " static const char *const spell[];" << Qt::endl + << " static const short lhs[];" << Qt::endl + << " static const short rhs[];" << Qt::endl; if (debug_info) { QString prot = debugInfoProt(); - out << endl << "#ifndef " << prot << endl - << " static const int rule_index[];" << endl - << " static const int rule_info[];" << endl - << "#endif // " << prot << endl << endl; + out << Qt::endl << "#ifndef " << prot << Qt::endl + << " static const int rule_index[];" << Qt::endl + << " static const int rule_info[];" << Qt::endl + << "#endif // " << prot << Qt::endl << Qt::endl; } - out << " static const short goto_default[];" << endl - << " static const short action_default[];" << endl - << " static const short action_index[];" << endl - << " static const short action_info[];" << endl - << " static const short action_check[];" << endl - << endl - << " static inline int nt_action (int state, int nt)" << endl - << " {" << endl - << " const int yyn = action_index [GOTO_INDEX_OFFSET + state] + nt;" << endl - << " if (yyn < 0 || action_check [GOTO_CHECK_OFFSET + yyn] != nt)" << endl - << " return goto_default [nt];" << endl - << endl - << " return action_info [GOTO_INFO_OFFSET + yyn];" << endl - << " }" << endl - << endl - << " static inline int t_action (int state, int token)" << endl - << " {" << endl - << " const int yyn = action_index [state] + token;" << endl - << endl - << " if (yyn < 0 || action_check [yyn] != token)" << endl - << " return - action_default [state];" << endl - << endl - << " return action_info [yyn];" << endl - << " }" << endl - << "};" << endl - << endl - << endl; + out << " static const short goto_default[];" << Qt::endl + << " static const short action_default[];" << Qt::endl + << " static const short action_index[];" << Qt::endl + << " static const short action_info[];" << Qt::endl + << " static const short action_check[];" << Qt::endl + << Qt::endl + << " static inline int nt_action (int state, int nt)" << Qt::endl + << " {" << Qt::endl + << " const int yyn = action_index [GOTO_INDEX_OFFSET + state] + nt;" << Qt::endl + << " if (yyn < 0 || action_check [GOTO_CHECK_OFFSET + yyn] != nt)" << Qt::endl + << " return goto_default [nt];" << Qt::endl + << Qt::endl + << " return action_info [GOTO_INFO_OFFSET + yyn];" << Qt::endl + << " }" << Qt::endl + << Qt::endl + << " static inline int t_action (int state, int token)" << Qt::endl + << " {" << Qt::endl + << " const int yyn = action_index [state] + token;" << Qt::endl + << Qt::endl + << " if (yyn < 0 || action_check [yyn] != token)" << Qt::endl + << " return - action_default [state];" << Qt::endl + << Qt::endl + << " return action_info [yyn];" << Qt::endl + << " }" << Qt::endl + << "};" << Qt::endl + << Qt::endl + << Qt::endl; } void CppGenerator::generateImpl (QTextStream &out) @@ -568,16 +568,16 @@ void CppGenerator::generateImpl (QTextStream &out) { first_nt = false; QString prot = debugInfoProt(); - out << endl << "#ifndef " << prot << endl; + out << Qt::endl << "#ifndef " << prot << Qt::endl; } out << "\"" << *t << "\""; } } if (debug_info) - out << endl << "#endif // " << debugInfoProt() << endl; + out << Qt::endl << "#endif // " << debugInfoProt() << Qt::endl; - out << endl << "};" << endl << endl; + out << Qt::endl << "};" << Qt::endl << Qt::endl; out << "const short " << grammar.table_name << "::lhs [] = {"; idx = 0; @@ -587,7 +587,7 @@ void CppGenerator::generateImpl (QTextStream &out) out << aut.id (rule->lhs); } - out << endl << "};" << endl << endl; + out << Qt::endl << "};" << Qt::endl << Qt::endl; out << "const short " << grammar.table_name << "::rhs [] = {"; idx = 0; @@ -597,13 +597,13 @@ void CppGenerator::generateImpl (QTextStream &out) out << rule->rhs.size (); } - out << endl << "};" << endl << endl; + out << Qt::endl << "};" << Qt::endl << Qt::endl; if (debug_info) { QString prot = debugInfoProt(); - out << endl << "#ifndef " << prot << endl; + out << Qt::endl << "#ifndef " << prot << Qt::endl; out << "const int " << grammar.table_name << "::rule_info [] = {"; idx = 0; for (auto rule = grammar.rules.cbegin (); rule != grammar.rules.cend (); ++rule, ++idx) @@ -615,7 +615,7 @@ void CppGenerator::generateImpl (QTextStream &out) for (const Name &n : rule->rhs) out << ", " << name_ids.value (n); } - out << endl << "};" << endl << endl; + out << Qt::endl << "};" << Qt::endl << Qt::endl; out << "const int " << grammar.table_name << "::rule_index [] = {"; idx = 0; @@ -627,8 +627,8 @@ void CppGenerator::generateImpl (QTextStream &out) out << offset; offset += rule->rhs.size () + 1; } - out << endl << "};" << endl - << "#endif // " << prot << endl << endl; + out << Qt::endl << "};" << Qt::endl + << "#endif // " << prot << Qt::endl << Qt::endl; } out << "const short " << grammar.table_name << "::action_default [] = {"; @@ -642,27 +642,27 @@ void CppGenerator::generateImpl (QTextStream &out) else out << "0"; } - out << endl << "};" << endl << endl; + out << Qt::endl << "};" << Qt::endl << Qt::endl; out << "const short " << grammar.table_name << "::goto_default [] = {"; generateList(defgoto, out); - out << endl << "};" << endl << endl; + out << Qt::endl << "};" << Qt::endl << Qt::endl; out << "const short " << grammar.table_name << "::action_index [] = {"; generateList(compressed_action.index, out); - out << "," << endl; + out << "," << Qt::endl; generateList(compressed_goto.index, out); - out << endl << "};" << endl << endl; + out << Qt::endl << "};" << Qt::endl << Qt::endl; out << "const short " << grammar.table_name << "::action_info [] = {"; generateList(compressed_action.info, out); - out << "," << endl; + out << "," << Qt::endl; generateList(compressed_goto.info, out); - out << endl << "};" << endl << endl; + out << Qt::endl << "};" << Qt::endl << Qt::endl; out << "const short " << grammar.table_name << "::action_check [] = {"; generateList(compressed_action.check, out); - out << "," << endl; + out << "," << Qt::endl; generateList(compressed_goto.check, out); - out << endl << "};" << endl << endl; + out << Qt::endl << "};" << Qt::endl << Qt::endl; } diff --git a/src/tools/qlalr/dotgraph.cpp b/src/tools/qlalr/dotgraph.cpp index 1fa0a1ac77..1d479af2b2 100644 --- a/src/tools/qlalr/dotgraph.cpp +++ b/src/tools/qlalr/dotgraph.cpp @@ -41,9 +41,9 @@ void DotGraph::operator () (Automaton *aut) { Grammar *g = aut->_M_grammar; - out << "digraph {" << endl << endl; + out << "digraph {" << Qt::endl << Qt::endl; - out << "subgraph Includes {" << endl; + out << "subgraph Includes {" << Qt::endl; for (Automaton::IncludesGraph::iterator incl = Automaton::IncludesGraph::begin_nodes (); incl != Automaton::IncludesGraph::end_nodes (); ++incl) { @@ -53,14 +53,14 @@ void DotGraph::operator () (Automaton *aut) out << "\t->\t"; out << "\"(" << aut->id ((*edge)->data.state) << ", " << (*edge)->data.nt << ")\"\t"; out << "[label=\"" << incl->data.state->follows [incl->data.nt] << "\"]"; - out << endl; + out << Qt::endl; } } - out << "}" << endl << endl; + out << "}" << Qt::endl << Qt::endl; - out << "subgraph LRA {" << endl; - //out << "node [shape=record];" << endl << endl; + out << "subgraph LRA {" << Qt::endl; + //out << "node [shape=record];" << Qt::endl << Qt::endl; for (StatePointer q = aut->states.begin (); q != aut->states.end (); ++q) { @@ -74,16 +74,16 @@ void DotGraph::operator () (Automaton *aut) for (ItemPointer item = q->kernel.begin (); item != q->kernel.end (); ++item) out << "| <" << index++ << "> " << *item; - out << "}\"]" << endl; + out << "}\"]" << Qt::endl; for (Bundle::iterator a = q->bundle.begin (); a != q->bundle.end (); ++a) { const char *clr = g->isTerminal (a.key ()) ? "blue" : "red"; - out << "\t" << state << "\t->\t" << aut->id (*a) << "\t[color=\"" << clr << "\",label=\"" << a.key () << "\"]" << endl; + out << "\t" << state << "\t->\t" << aut->id (*a) << "\t[color=\"" << clr << "\",label=\"" << a.key () << "\"]" << Qt::endl; } - out << endl; + out << Qt::endl; } - out << "}" << endl; - out << endl << endl << "}" << endl; + out << "}" << Qt::endl; + out << Qt::endl << Qt::endl << "}" << Qt::endl; } diff --git a/src/tools/qlalr/lalr.cpp b/src/tools/qlalr/lalr.cpp index ec960925aa..2a82eb154e 100644 --- a/src/tools/qlalr/lalr.cpp +++ b/src/tools/qlalr/lalr.cpp @@ -313,7 +313,7 @@ void Automaton::buildNullables () } #ifndef QLALR_NO_DEBUG_NULLABLES - qerr() << "nullables = {" << nullables << endl; + qerr() << "nullables = {" << nullables << Qt::endl; #endif } @@ -456,7 +456,7 @@ void Automaton::buildLookbackSets () lookbacks.insert (item, Lookback (p, A)); #ifndef QLALR_NO_DEBUG_LOOKBACKS - qerr() << "*** (" << id (q) << ", " << *rule << ") lookback (" << id (p) << ", " << *A << ")" << endl; + qerr() << "*** (" << id (q) << ", " << *rule << ") lookback (" << id (p) << ", " << *A << ")" << Qt::endl; #endif } } @@ -487,7 +487,7 @@ void Automaton::buildDirectReads () #ifndef QLALR_NO_DEBUG_DIRECT_READS for (QMap::iterator dr = q->reads.begin (); dr != q->reads.end (); ++dr) - qerr() << "*** DR(" << id (q) << ", " << dr.key () << ") = " << dr.value () << endl; + qerr() << "*** DR(" << id (q) << ", " << dr.key () << ") = " << dr.value () << Qt::endl; #endif } } @@ -520,7 +520,7 @@ void Automaton::buildReadsDigraph () dump (qerr(), source); qerr() << " reads "; dump (qerr(), target); - qerr() << endl; + qerr() << Qt::endl; #endif } } @@ -555,7 +555,7 @@ void Automaton::visitReadNode (ReadNode node) _M_reads_stack.push (node); #ifndef QLALR_NO_DEBUG_INCLUDES - // qerr() << "*** Debug. visit node (" << id (node->data.state) << ", " << node->data.nt << ") N = " << N << endl; + // qerr() << "*** Debug. visit node (" << id (node->data.state) << ", " << node->data.nt << ") N = " << N << Qt::endl; #endif for (ReadsGraph::edge_iterator edge = node->begin (); edge != node->end (); ++edge) @@ -635,7 +635,7 @@ void Automaton::buildIncludesDigraph () source->insertEdge (target); #ifndef QLALR_NO_DEBUG_INCLUDES - qerr() << "*** (" << id (p) << ", " << *A << ") includes (" << id (pp) << ", " << *name << ")" << endl; + qerr() << "*** (" << id (p) << ", " << *A << ") includes (" << id (pp) << ", " << *name << ")" << Qt::endl; #endif // QLALR_NO_DEBUG_INCLUDES continue; @@ -657,7 +657,7 @@ void Automaton::buildIncludesDigraph () source->insertEdge (target); #ifndef QLALR_NO_DEBUG_INCLUDES - qerr() << "*** (" << id (p) << ", " << *A << ") includes (" << id (pp) << ", " << *name << ")" << endl; + qerr() << "*** (" << id (p) << ", " << *A << ") includes (" << id (pp) << ", " << *name << ")" << Qt::endl; #endif // QLALR_NO_DEBUG_INCLUDES } } @@ -674,7 +674,7 @@ void Automaton::visitIncludeNode (IncludeNode node) _M_includes_stack.push (node); #ifndef QLALR_NO_DEBUG_INCLUDES - // qerr() << "*** Debug. visit node (" << id (node->data.state) << ", " << node->data.nt << ") N = " << N << endl; + // qerr() << "*** Debug. visit node (" << id (node->data.state) << ", " << node->data.nt << ") N = " << N << Qt::endl; #endif for (IncludesGraph::edge_iterator edge = node->begin (); edge != node->end (); ++edge) @@ -690,7 +690,7 @@ void Automaton::visitIncludeNode (IncludeNode node) dump (qerr(), node); qerr() << " += follows"; dump (qerr(), r); - qerr() << endl; + qerr() << Qt::endl; #endif NameSet &dst = node->data.state->follows [node->data.nt]; @@ -726,7 +726,7 @@ void Automaton::buildLookaheads () #ifndef QLALR_NO_DEBUG_LOOKAHEADS qerr() << "(" << id (p) << ", " << *item->rule << ") lookbacks "; dump (qerr(), lookback); - qerr() << " with follows (" << id (q) << ", " << lookback.nt << ") = " << q->follows [lookback.nt] << endl; + qerr() << " with follows (" << id (q) << ", " << lookback.nt << ") = " << q->follows [lookback.nt] << Qt::endl; #endif lookaheads [item].insert (q->follows [lookback.nt].begin (), q->follows [lookback.nt].end ()); diff --git a/src/tools/qlalr/lalr.g b/src/tools/qlalr/lalr.g index 05d30c21fd..a849800dd5 100644 --- a/src/tools/qlalr/lalr.g +++ b/src/tools/qlalr/lalr.g @@ -261,7 +261,7 @@ int Recognizer::nextToken() if (ch == QLatin1Char ('"')) inp (); else - qerr() << _M_input_file << ":" << _M_line << ": Warning. Expected `\"'" << endl; + qerr() << _M_input_file << ":" << _M_line << ": Warning. Expected `\"'" << Qt::endl; _M_current_value = text; return (token = STRING_LITERAL); @@ -314,7 +314,7 @@ int Recognizer::nextToken() return (token = PREC); else { - qerr() << _M_input_file << ":" << _M_line << ": Unknown keyword `" << text << "'" << endl; + qerr() << _M_input_file << ":" << _M_line << ": Unknown keyword `" << text << "'" << Qt::endl; exit (EXIT_FAILURE); return (token = ERROR); } @@ -659,7 +659,7 @@ case $rule_number: { if (_M_grammar->terminals.find (_M_current_rule->lhs) != _M_grammar->terminals.end ()) { - qerr() << _M_input_file << ":" << _M_line << ": Invalid non terminal `" << *_M_current_rule->lhs << "'" << endl; + qerr() << _M_input_file << ":" << _M_line << ": Invalid non terminal `" << *_M_current_rule->lhs << "'" << Qt::endl; return false; } @@ -683,7 +683,7 @@ case $rule_number: { if (_M_grammar->terminals.find (_M_current_rule->lhs) != _M_grammar->terminals.end ()) { - qerr() << _M_input_file << ":" << _M_line << ": Invalid non terminal `" << *_M_current_rule->lhs << "'" << endl; + qerr() << _M_input_file << ":" << _M_line << ": Invalid non terminal `" << *_M_current_rule->lhs << "'" << Qt::endl; return false; } @@ -712,7 +712,7 @@ case $rule_number: { Name tok = _M_grammar->intern (sym(2)); if (! _M_grammar->isTerminal (tok)) { - qerr() << _M_input_file << ":" << _M_line << ": `" << *tok << " is not a terminal symbol" << endl; + qerr() << _M_input_file << ":" << _M_line << ": `" << *tok << " is not a terminal symbol" << Qt::endl; _M_current_rule->prec = _M_grammar->names.end (); } else @@ -758,7 +758,7 @@ case $rule_number: { } } - qerr() << _M_input_file << ":" << _M_line << ": Syntax error" << endl; + qerr() << _M_input_file << ":" << _M_line << ": Syntax error" << Qt::endl; return false; } diff --git a/src/tools/qlalr/main.cpp b/src/tools/qlalr/main.cpp index 5971eb201d..a920b13c85 100644 --- a/src/tools/qlalr/main.cpp +++ b/src/tools/qlalr/main.cpp @@ -44,15 +44,15 @@ static void help_me () { - qerr() << "Usage: qlalr [options] [input file name]" << endl - << endl - << " --help, -h\t\tdisplay this help and exit" << endl - << " --verbose, -v\t\tverbose output" << endl - << " --no-debug\t\tno debug information" << endl - << " --no-lines\t\tno #line directives" << endl - << " --dot\t\t\tgenerate a graph" << endl - << " --qt\t\tadd the Qt copyright header and Qt-specific types and macros" << endl - << endl; + qerr() << "Usage: qlalr [options] [input file name]" << Qt::endl + << Qt::endl + << " --help, -h\t\tdisplay this help and exit" << Qt::endl + << " --verbose, -v\t\tverbose output" << Qt::endl + << " --no-debug\t\tno debug information" << Qt::endl + << " --no-lines\t\tno #line directives" << Qt::endl + << " --dot\t\t\tgenerate a graph" << Qt::endl + << " --qt\t\tadd the Qt copyright header and Qt-specific types and macros" << Qt::endl + << Qt::endl; exit (0); } @@ -91,7 +91,7 @@ int main (int argc, char *argv[]) file_name = arg; else - qerr() << "*** Warning. Ignore argument `" << arg << "'" << endl; + qerr() << "*** Warning. Ignore argument `" << arg << "'" << Qt::endl; } if (file_name.isEmpty ()) @@ -108,13 +108,13 @@ int main (int argc, char *argv[]) if (grammar.rules.isEmpty ()) { - qerr() << "*** Fatal. No rules!" << endl; + qerr() << "*** Fatal. No rules!" << Qt::endl; exit (EXIT_FAILURE); } else if (grammar.start == grammar.names.end ()) { - qerr() << "*** Fatal. No start symbol!" << endl; + qerr() << "*** Fatal. No start symbol!" << Qt::endl; exit (EXIT_FAILURE); } diff --git a/src/tools/qlalr/parsetable.cpp b/src/tools/qlalr/parsetable.cpp index c88ac1291e..9e71acebb4 100644 --- a/src/tools/qlalr/parsetable.cpp +++ b/src/tools/qlalr/parsetable.cpp @@ -43,13 +43,13 @@ void ParseTable::operator () (Automaton *aut) int rindex = 1; for (RulePointer rule = g->rules.begin (); rule != g->rules.end (); ++rule) - out << rindex++ << ")\t" << *rule << endl; - out << endl << endl; + out << rindex++ << ")\t" << *rule << Qt::endl; + out << Qt::endl << Qt::endl; int index = 0; for (StatePointer state = aut->states.begin (); state != aut->states.end (); ++state) { - out << "state " << index++ << endl << endl; + out << "state " << index++ << Qt::endl << Qt::endl; for (ItemPointer item = state->kernel.begin (); item != state->kernel.end (); ++item) { @@ -58,7 +58,7 @@ void ParseTable::operator () (Automaton *aut) if (item->dot == item->end_rhs ()) out << " " << aut->lookaheads [item]; - out << endl; + out << Qt::endl; } bool first = true; @@ -68,11 +68,11 @@ void ParseTable::operator () (Automaton *aut) continue; if (first) - out << endl; + out << Qt::endl; first = false; - out << " " << *arrow.key () << " shift, and go to state " << std::distance (aut->states.begin (), *arrow) << endl; + out << " " << *arrow.key () << " shift, and go to state " << std::distance (aut->states.begin (), *arrow) << Qt::endl; } first = true; @@ -82,13 +82,13 @@ void ParseTable::operator () (Automaton *aut) continue; if (first) - out << endl; + out << Qt::endl; first = false; const auto lookaheads = aut->lookaheads.value(item); for (const Name &la : lookaheads) - out << " " << *la << " reduce using rule " << aut->id (item->rule) << " (" << *item->rule->lhs << ")" << endl; + out << " " << *la << " reduce using rule " << aut->id (item->rule) << " (" << *item->rule->lhs << ")" << Qt::endl; } first = true; @@ -98,19 +98,19 @@ void ParseTable::operator () (Automaton *aut) continue; if (first) - out << endl; + out << Qt::endl; first = false; - out << " " << *arrow.key () << " go to state " << std::distance (aut->states.begin (), *arrow) << endl; + out << " " << *arrow.key () << " go to state " << std::distance (aut->states.begin (), *arrow) << Qt::endl; } if (state->defaultReduce != g->rules.end ()) { - out << endl - << " $default reduce using rule " << aut->id (state->defaultReduce) << " (" << *state->defaultReduce->lhs << ")" << endl; + out << Qt::endl + << " $default reduce using rule " << aut->id (state->defaultReduce) << " (" << *state->defaultReduce->lhs << ")" << Qt::endl; } - out << endl; + out << Qt::endl; } } diff --git a/src/tools/qlalr/recognizer.cpp b/src/tools/qlalr/recognizer.cpp index ab797c85d0..3da54c0c6a 100644 --- a/src/tools/qlalr/recognizer.cpp +++ b/src/tools/qlalr/recognizer.cpp @@ -97,7 +97,7 @@ int Recognizer::nextToken() if (ch == QLatin1Char ('"')) inp (); else - qerr() << _M_input_file << ":" << _M_line << ": Warning. Expected `\"'" << endl; + qerr() << _M_input_file << ":" << _M_line << ": Warning. Expected `\"'" << Qt::endl; _M_current_value = text; return (token = STRING_LITERAL); @@ -150,7 +150,7 @@ int Recognizer::nextToken() return (token = PREC); else { - qerr() << _M_input_file << ":" << _M_line << ": Unknown keyword `" << text << "'" << endl; + qerr() << _M_input_file << ":" << _M_line << ": Unknown keyword `" << text << "'" << Qt::endl; exit (EXIT_FAILURE); return (token = ERROR); } @@ -405,7 +405,7 @@ case 34: { if (_M_grammar->terminals.find (_M_current_rule->lhs) != _M_grammar->terminals.end ()) { - qerr() << _M_input_file << ":" << _M_line << ": Invalid non terminal `" << *_M_current_rule->lhs << "'" << endl; + qerr() << _M_input_file << ":" << _M_line << ": Invalid non terminal `" << *_M_current_rule->lhs << "'" << Qt::endl; return false; } @@ -420,7 +420,7 @@ case 38: { if (_M_grammar->terminals.find (_M_current_rule->lhs) != _M_grammar->terminals.end ()) { - qerr() << _M_input_file << ":" << _M_line << ": Invalid non terminal `" << *_M_current_rule->lhs << "'" << endl; + qerr() << _M_input_file << ":" << _M_line << ": Invalid non terminal `" << *_M_current_rule->lhs << "'" << Qt::endl; return false; } @@ -443,7 +443,7 @@ case 40: { Name tok = _M_grammar->intern (sym(2)); if (! _M_grammar->isTerminal (tok)) { - qerr() << _M_input_file << ":" << _M_line << ": `" << *tok << " is not a terminal symbol" << endl; + qerr() << _M_input_file << ":" << _M_line << ": `" << *tok << " is not a terminal symbol" << Qt::endl; _M_current_rule->prec = _M_grammar->names.end (); } else @@ -474,7 +474,7 @@ case 43: { } } - qerr() << _M_input_file << ":" << _M_line << ": Syntax error" << endl; + qerr() << _M_input_file << ":" << _M_line << ": Syntax error" << Qt::endl; return false; } diff --git a/src/tools/uic/cpp/cppwriteinitialization.cpp b/src/tools/uic/cpp/cppwriteinitialization.cpp index b8ff91f354..a1ff26ba04 100644 --- a/src/tools/uic/cpp/cppwriteinitialization.cpp +++ b/src/tools/uic/cpp/cppwriteinitialization.cpp @@ -1626,7 +1626,7 @@ QString WriteInitialization::writeFontProperties(const DomFont *f) } if (f->hasElementWeight() && f->elementWeight() > 0) { m_output << m_indent << fontName << ".setWeight(" - << f->elementWeight() << ");" << endl; + << f->elementWeight() << ");" << Qt::endl; } if (f->hasElementStrikeOut()) { m_output << m_indent << fontName << ".setStrikeOut(" @@ -2614,7 +2614,7 @@ static void generateMultiDirectiveBegin(QTextStream &outputStream, const QSet &directives) @@ -2622,7 +2622,7 @@ static void generateMultiDirectiveEnd(QTextStream &outputStream, const QSetisWindow()) debug << ", window"; debug << ", " << geometry.width() << 'x' << geometry.height() - << forcesign << geometry.x() << geometry.y() << noforcesign; + << Qt::forcesign << geometry.x() << geometry.y() << Qt::noforcesign; if (frameGeometry != geometry) { const QMargins margins(geometry.x() - frameGeometry.x(), geometry.y() - frameGeometry.y(), @@ -13190,7 +13190,7 @@ QDebug operator<<(QDebug debug, const QWidget *widget) } debug << ", devicePixelRatio=" << widget->devicePixelRatioF(); if (const WId wid = widget->internalWinId()) - debug << ", winId=0x" << hex << wid << dec; + debug << ", winId=0x" << Qt::hex << wid << Qt::dec; } debug << ')'; } else { diff --git a/src/widgets/widgets/qsplitter.cpp b/src/widgets/widgets/qsplitter.cpp index de838a8f93..4e251de501 100644 --- a/src/widgets/widgets/qsplitter.cpp +++ b/src/widgets/widgets/qsplitter.cpp @@ -1793,7 +1793,7 @@ void QSplitter::setStretchFactor(int index, int stretch) QTextStream& operator<<(QTextStream& ts, const QSplitter& splitter) { - ts << splitter.saveState() << endl; + ts << splitter.saveState() << Qt::endl; return ts; } diff --git a/src/xml/doc/snippets/code/src_xml_dom_qdom.cpp b/src/xml/doc/snippets/code/src_xml_dom_qdom.cpp index 2d18e0e537..f7d81f676f 100644 --- a/src/xml/doc/snippets/code/src_xml_dom_qdom.cpp +++ b/src/xml/doc/snippets/code/src_xml_dom_qdom.cpp @@ -74,7 +74,7 @@ QDomNode n = d.firstChild(); while (!n.isNull()) { if (n.isElement()) { QDomElement e = n.toElement(); - cout << "Element name: " << e.tagName() << endl; + cout << "Element name: " << e.tagName() << Qt::endl; break; } n = n.nextSibling(); @@ -126,10 +126,10 @@ QDomElement element4 = document.createElement("MyElement"); QDomElement e = //... //... QDomAttr a = e.attributeNode("href"); -cout << a.value() << endl; // prints "http://qt-project.org" +cout << a.value() << Qt::endl; // prints "http://qt-project.org" a.setValue("http://qt-project.org/doc"); // change the node's attribute QDomAttr a2 = e.attributeNode("href"); -cout << a2.value() << endl; // prints "http://qt-project.org/doc" +cout << a2.value() << Qt::endl; // prints "http://qt-project.org/doc" //! [8] @@ -201,7 +201,7 @@ QDomNode n = docElem.firstChild(); while(!n.isNull()) { QDomElement e = n.toElement(); // try to convert the node to an element. if(!e.isNull()) { - cout << qPrintable(e.tagName()) << endl; // the node really is an element. + cout << qPrintable(e.tagName()) << Qt::endl; // the node really is an element. } n = n.nextSibling(); } diff --git a/src/xml/dom/qdom.cpp b/src/xml/dom/qdom.cpp index cffc1974af..fedd53f3a9 100644 --- a/src/xml/dom/qdom.cpp +++ b/src/xml/dom/qdom.cpp @@ -3598,7 +3598,7 @@ void QDomDocumentTypePrivate::save(QTextStream& s, int, int indent) const } if (entities->length()>0 || notations->length()>0) { - s << " [" << endl; + s << " [" << Qt::endl; QHash::const_iterator it2 = notations->map.constBegin(); for (; it2 != notations->map.constEnd(); ++it2) @@ -3611,7 +3611,7 @@ void QDomDocumentTypePrivate::save(QTextStream& s, int, int indent) const s << ']'; } - s << '>' << endl; + s << '>' << Qt::endl; } /************************************************************** @@ -4627,7 +4627,7 @@ void QDomElementPrivate::save(QTextStream& s, int depth, int indent) const /* -1 disables new lines. */ if (indent != -1) - s << endl; + s << Qt::endl; } QDomNodePrivate::save(s, depth + 1, indent); if (!last->isText()) s << QString(indent < 1 ? 0 : depth * indent, QLatin1Char(' ')); @@ -4639,7 +4639,7 @@ void QDomElementPrivate::save(QTextStream& s, int depth, int indent) const if (!(next && next->isText())) { /* -1 disables new lines. */ if (indent != -1) - s << endl; + s << Qt::endl; } } @@ -5329,7 +5329,7 @@ void QDomCommentPrivate::save(QTextStream& s, int depth, int indent) const s << "-->"; if (!(next && next->isText())) - s << endl; + s << Qt::endl; } /************************************************************** @@ -5552,7 +5552,7 @@ void QDomNotationPrivate::save(QTextStream& s, int, int) const } else { s << "SYSTEM " << quotedValue(m_sys); } - s << '>' << endl; + s << '>' << Qt::endl; } /************************************************************** @@ -5733,7 +5733,7 @@ void QDomEntityPrivate::save(QTextStream& s, int, int) const _name = QLatin1String("% ") + _name.mid(1); if (m_sys.isNull() && m_pub.isNull()) { - s << "" << endl; + s << "" << Qt::endl; } else { s << "' << endl; + s << '>' << Qt::endl; } } @@ -6014,7 +6014,7 @@ QDomNodePrivate* QDomProcessingInstructionPrivate::cloneNode(bool deep) void QDomProcessingInstructionPrivate::save(QTextStream& s, int, int) const { - s << "" << endl; + s << "" << Qt::endl; } /************************************************************** -- cgit v1.2.3 From 415c435d605827cf4f4d9d0f723ed27c9b6baba5 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 30 Apr 2019 12:53:42 +0200 Subject: Compile when bumping the Qt version to 6.0 Change-Id: Idae1a2df144598df3921ef9a12e0e0b740fd723d Reviewed-by: Allan Sandfeld Jensen --- src/corelib/serialization/qxmlstream.cpp | 12 +++++++++++- src/corelib/serialization/qxmlstream.h | 4 ++-- 2 files changed, 13 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/corelib/serialization/qxmlstream.cpp b/src/corelib/serialization/qxmlstream.cpp index 0170be7602..d43d9c4e14 100644 --- a/src/corelib/serialization/qxmlstream.cpp +++ b/src/corelib/serialization/qxmlstream.cpp @@ -2285,12 +2285,14 @@ QXmlStreamAttribute::QXmlStreamAttribute() m_isDefault = false; } +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) /*! Destructs an attribute. */ QXmlStreamAttribute::~QXmlStreamAttribute() { } +#endif /*! Constructs an attribute in the namespace described with \a namespaceUri with \a name and value \a value. @@ -2366,6 +2368,7 @@ QXmlStreamAttribute::QXmlStreamAttribute(const QString &qualifiedName, const QSt */ +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) /*! Creates a copy of \a other. */ @@ -2386,7 +2389,7 @@ QXmlStreamAttribute& QXmlStreamAttribute::operator=(const QXmlStreamAttribute &o m_isDefault = other.m_isDefault; return *this; } - +#endif /*! \class QXmlStreamAttributes @@ -2442,6 +2445,8 @@ QXmlStreamAttribute& QXmlStreamAttribute::operator=(const QXmlStreamAttribute &o QXmlStreamNotationDeclaration::QXmlStreamNotationDeclaration() { } + +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) /*! Creates a copy of \a other. */ @@ -2467,6 +2472,7 @@ Destructs this notation declaration. QXmlStreamNotationDeclaration::~QXmlStreamNotationDeclaration() { } +#endif /*! \fn QStringRef QXmlStreamNotationDeclaration::name() const @@ -2539,6 +2545,7 @@ QXmlStreamNamespaceDeclaration::QXmlStreamNamespaceDeclaration(const QString &pr m_namespaceUri = namespaceUri; } +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) /*! Creates a copy of \a other. */ @@ -2562,6 +2569,7 @@ Destructs this namespace declaration. QXmlStreamNamespaceDeclaration::~QXmlStreamNamespaceDeclaration() { } +#endif /*! \fn QStringRef QXmlStreamNamespaceDeclaration::prefix() const @@ -2609,6 +2617,7 @@ QXmlStreamEntityDeclaration::QXmlStreamEntityDeclaration() { } +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) /*! Creates a copy of \a other. */ @@ -2636,6 +2645,7 @@ QXmlStreamEntityDeclaration& QXmlStreamEntityDeclaration::operator=(const QXmlSt QXmlStreamEntityDeclaration::~QXmlStreamEntityDeclaration() { } +#endif /*! \fn QXmlStreamStringRef::swap(QXmlStreamStringRef &other) \since 5.6 diff --git a/src/corelib/serialization/qxmlstream.h b/src/corelib/serialization/qxmlstream.h index 55dcc4e4e8..7d0aa64570 100644 --- a/src/corelib/serialization/qxmlstream.h +++ b/src/corelib/serialization/qxmlstream.h @@ -104,8 +104,8 @@ class Q_CORE_EXPORT QXmlStreamAttribute { public: QXmlStreamAttribute(); QXmlStreamAttribute(const QString &qualifiedName, const QString &value); -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) QXmlStreamAttribute(const QString &namespaceUri, const QString &name, const QString &value); +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) QXmlStreamAttribute(const QXmlStreamAttribute &); QXmlStreamAttribute(QXmlStreamAttribute &&other) noexcept // = default; : m_name(std::move(other.m_name)), @@ -191,6 +191,7 @@ class Q_CORE_EXPORT QXmlStreamNamespaceDeclaration { friend class QXmlStreamReaderPrivate; public: QXmlStreamNamespaceDeclaration(); + QXmlStreamNamespaceDeclaration(const QString &prefix, const QString &namespaceUri); #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) QXmlStreamNamespaceDeclaration(const QXmlStreamNamespaceDeclaration &); QXmlStreamNamespaceDeclaration(QXmlStreamNamespaceDeclaration &&other) noexcept // = default @@ -207,7 +208,6 @@ public: qSwap(reserved, other.reserved); return *this; } - QXmlStreamNamespaceDeclaration(const QString &prefix, const QString &namespaceUri); ~QXmlStreamNamespaceDeclaration(); QXmlStreamNamespaceDeclaration& operator=(const QXmlStreamNamespaceDeclaration &); #endif // < Qt 6 -- cgit v1.2.3 From a08c0ca94974142af77ec30eee715a5eb9a2faf5 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 30 Apr 2019 13:25:33 +0200 Subject: Prepare QDataStream for Qt 6.0 Add the required datastream versions for 6.0. Of course the number for 5.15 and 6.0 is still something we can bump. Change-Id: I676385817befc06ea8d0ff1e9eba9c94cb4698b0 Reviewed-by: Allan Sandfeld Jensen --- src/corelib/serialization/qdatastream.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/corelib/serialization/qdatastream.h b/src/corelib/serialization/qdatastream.h index 2acf7d8c4b..60d429d707 100644 --- a/src/corelib/serialization/qdatastream.h +++ b/src/corelib/serialization/qdatastream.h @@ -102,9 +102,17 @@ public: Qt_5_13 = 19, Qt_5_14 = Qt_5_13, #if QT_VERSION >= 0x050f00 + Qt_5_15 = Qt_5_14, + Qt_DefaultCompiledVersion = Qt_5_15 +#elif QT_VERSION >= 0x060000 + Qt_6_0 = Qt_5_15, + Qt_DefaultCompiledVersion = Qt_6_0 +#else + Qt_DefaultCompiledVersion = Qt_5_14 +#endif +#if QT_VERSION >= 0x060100 #error Add the datastream version for this Qt version and update Qt_DefaultCompiledVersion #endif - Qt_DefaultCompiledVersion = Qt_5_14 }; enum ByteOrder { -- cgit v1.2.3 From 93d3248ed0c81cbe162781a3fac1243c774a7574 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 30 Apr 2019 14:13:06 +0200 Subject: Compile for Qt 6 Change-Id: I3069081d1c706980a8133b06d46588c4310cb304 Reviewed-by: Allan Sandfeld Jensen --- src/corelib/kernel/qobject.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 73b655cb36..eaf35adb90 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -4031,6 +4031,7 @@ static void dumpRecursive(int level, const QObject *object) } } +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) /*! \overload \obsolete @@ -4044,6 +4045,7 @@ void QObject::dumpObjectTree() { const_cast(this)->dumpObjectTree(); } +#endif /*! Dumps a tree of children to the debug output. @@ -4058,6 +4060,7 @@ void QObject::dumpObjectTree() const dumpRecursive(0, this); } +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) /*! \overload \obsolete @@ -4072,6 +4075,7 @@ void QObject::dumpObjectInfo() { const_cast(this)->dumpObjectInfo(); } +#endif /*! Dumps information about signal connections, etc. for this object -- cgit v1.2.3 From 857a83259d8f1cfe7d3673c15f5a3436be89b432 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 30 Apr 2019 14:42:55 +0200 Subject: Compile with Qt 6 Change-Id: Ie45f4dc6d44723c8992872e6c4c2e30d7257ca0c Reviewed-by: Allan Sandfeld Jensen --- src/gui/image/qimagereader.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp index 61f20e0c65..ae433ff651 100644 --- a/src/gui/image/qimagereader.cpp +++ b/src/gui/image/qimagereader.cpp @@ -1115,8 +1115,10 @@ bool QImageReader::autoTransform() const case QImageReaderPrivate::DoNotApplyTransform: return false; case QImageReaderPrivate::UsePluginDefault: +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) if (d->initHandler()) return d->handler->supportsOption(QImageIOHandler::TransformedByDefault); +#endif Q_FALLTHROUGH(); default: break; -- cgit v1.2.3 From c7a5cdb98ca4694fa8364c79b5cf53adf7bf19b9 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 30 Apr 2019 14:43:05 +0200 Subject: Compile with Qt 6 Change-Id: I2cd5f93d01b2a7645bf6bccede484fc301209007 Reviewed-by: Allan Sandfeld Jensen --- src/gui/painting/qtransform.cpp | 8 ++++++++ src/gui/painting/qtransform.h | 4 ++++ 2 files changed, 12 insertions(+) (limited to 'src') diff --git a/src/gui/painting/qtransform.cpp b/src/gui/painting/qtransform.cpp index 6110a548fd..7696da7d45 100644 --- a/src/gui/painting/qtransform.cpp +++ b/src/gui/painting/qtransform.cpp @@ -265,7 +265,9 @@ QTransform::QTransform() , m_13(0), m_23(0), m_33(1) , m_type(TxNone) , m_dirty(TxNone) +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) , d(nullptr) +#endif { } @@ -284,7 +286,9 @@ QTransform::QTransform(qreal h11, qreal h12, qreal h13, , m_13(h13), m_23(h23), m_33(h33) , m_type(TxNone) , m_dirty(TxProject) +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) , d(nullptr) +#endif { } @@ -301,7 +305,9 @@ QTransform::QTransform(qreal h11, qreal h12, qreal h21, , m_13(0), m_23(0), m_33(1) , m_type(TxNone) , m_dirty(TxShear) +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) , d(nullptr) +#endif { } @@ -317,7 +323,9 @@ QTransform::QTransform(const QMatrix &mtx) m_13(0), m_23(0), m_33(1) , m_type(TxNone) , m_dirty(TxShear) +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) , d(nullptr) +#endif { } diff --git a/src/gui/painting/qtransform.h b/src/gui/painting/qtransform.h index 18c53f4a6f..b220770144 100644 --- a/src/gui/painting/qtransform.h +++ b/src/gui/painting/qtransform.h @@ -176,7 +176,9 @@ private: , m_13(h13), m_23(h23), m_33(h33) , m_type(TxNone) , m_dirty(TxProject) +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) , d(nullptr) +#endif { } inline QTransform(bool) @@ -184,7 +186,9 @@ private: , m_13(0), m_23(0), m_33(1) , m_type(TxNone) , m_dirty(TxNone) +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) , d(nullptr) +#endif { } inline TransformationType inline_type() const; -- cgit v1.2.3 From 1e4042d03f798aa088fea5d340342d56363d07ca Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 30 Apr 2019 14:43:13 +0200 Subject: Compile with Qt 6 Change-Id: I6d8d562a871a2f49db5db8630a08f53a14c0f7d3 Reviewed-by: Allan Sandfeld Jensen --- src/sql/models/qsqltablemodel.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/sql/models/qsqltablemodel.cpp b/src/sql/models/qsqltablemodel.cpp index 98d6ddf882..11d30ab2e8 100644 --- a/src/sql/models/qsqltablemodel.cpp +++ b/src/sql/models/qsqltablemodel.cpp @@ -50,6 +50,7 @@ #include "qsqltablemodel_p.h" #include +#include QT_BEGIN_NAMESPACE @@ -611,7 +612,7 @@ bool QSqlTableModel::setData(const QModelIndex &index, const QVariant &value, in /*! \reimp */ -bool QStringListModel::clearItemData(const QModelIndex &index) +bool QSqlTableModel::clearItemData(const QModelIndex &index) { return setData(index, QVariant(), Qt::EditRole); } -- cgit v1.2.3 From 9c04e7c61ebc87904c0fc40d5e421e862b406a58 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 30 Apr 2019 14:57:31 +0200 Subject: Fix API for Qt 6 Change-Id: Ic07b5cf09ed410a27ca95f106747f98de4d86d68 Reviewed-by: Allan Sandfeld Jensen --- src/widgets/kernel/qwidget.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/widgets/kernel/qwidget.h b/src/widgets/kernel/qwidget.h index aec3eee639..e47deb5d0d 100644 --- a/src/widgets/kernel/qwidget.h +++ b/src/widgets/kernel/qwidget.h @@ -555,7 +555,7 @@ public: void addAction(QAction *action); #if QT_VERSION >= QT_VERSION_CHECK(6,0,0) void addActions(const QList &actions); - void insertActions(const QAction *before, const QList &actions); + void insertActions(QAction *before, const QList &actions); #else void addActions(QList actions); void insertActions(QAction *before, QList actions); -- cgit v1.2.3 From 91b3099d713b25367aafaf0aa8b719b7bd316155 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 30 Apr 2019 15:19:19 +0200 Subject: Compile with Qt 6 Change-Id: I6efa420acab070e625f99b49eee08076d4a6a9ff Reviewed-by: Allan Sandfeld Jensen --- src/plugins/platforms/xcb/nativepainting/qpixmap_x11.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/platforms/xcb/nativepainting/qpixmap_x11.cpp b/src/plugins/platforms/xcb/nativepainting/qpixmap_x11.cpp index b1ce39f363..f86bedbdcd 100644 --- a/src/plugins/platforms/xcb/nativepainting/qpixmap_x11.cpp +++ b/src/plugins/platforms/xcb/nativepainting/qpixmap_x11.cpp @@ -2017,7 +2017,7 @@ QImage QX11PlatformPixmap::toImage(const QXImageWrapper &xiWrapper, const QRect } } else if (xi->bits_per_pixel == d) { // compatible depth char *xidata = xi->data; // copy each scanline - int bpl = qMin(image.bytesPerLine(),xi->bytes_per_line); + int bpl = qMin(int(image.bytesPerLine()),xi->bytes_per_line); for (int y=0; yheight; y++) { memcpy(image.scanLine(y), xidata, bpl); xidata += xi->bytes_per_line; -- cgit v1.2.3 From 936632c9c1e92de899bb17596a66167e8d515bc4 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Thu, 2 May 2019 11:46:32 +0200 Subject: QList: fix regression in swapItemsAt Commit e0d2b50249839d10ecf87abc296b8020046d1d75 makes swapItemsAt use ADL to find swap(). Problem is, QList has a swap() function (that swaps the elements at the specificed _indices_); that function will be found before ADL kicks in. So do the second best thing: use qSwap instead. Change-Id: Icf2b4e3ce09117e4056acbad3e2d8a625861d807 Reviewed-by: Lars Knoll --- src/corelib/tools/qlist.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index 59578b1e61..b916dcfd24 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -707,8 +707,7 @@ inline void QList::swapItemsAt(int i, int j) Q_ASSERT_X(i >= 0 && i < p.size() && j >= 0 && j < p.size(), "QList::swap", "index out of range"); detach(); - using std::swap; - swap(d->array[d->begin + i], d->array[d->begin + j]); + qSwap(d->array[d->begin + i], d->array[d->begin + j]); } template -- cgit v1.2.3 From 0d39cf6865301c96b69cfdc0df587f5962252e8e Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 2 May 2019 11:55:36 +0200 Subject: QTextMarkdownImporter: Fix deprecation warning Use QTextCharFormat::setAnchorNames(), fixing: text/qtextmarkdownimporter.cpp:322:36: warning: 'void QTextCharFormat::setAnchorName(const QString&)' is deprecated: Use setAnchorNames() instead [-Wdeprecated-declarations] Amends 65314b6ce88cdbb28a22be0cab9856ec9bc9604b. Task-number: QTBUG-72349 Change-Id: I7f909d1fcc5c4045c738b5a5c491b2ac1de6eac5 Reviewed-by: Shawn Rutledge --- src/gui/text/qtextmarkdownimporter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/gui/text/qtextmarkdownimporter.cpp b/src/gui/text/qtextmarkdownimporter.cpp index 2477e0bc74..bcb0b777d4 100644 --- a/src/gui/text/qtextmarkdownimporter.cpp +++ b/src/gui/text/qtextmarkdownimporter.cpp @@ -319,7 +319,7 @@ int QTextMarkdownImporter::cbEnterSpan(MD_SPANTYPE type, void *det) QString url = QString::fromLatin1(detail->href.text, detail->href.size); QString title = QString::fromLatin1(detail->title.text, detail->title.size); charFmt.setAnchorHref(url); - charFmt.setAnchorName(title); + charFmt.setAnchorNames(QStringList(title)); charFmt.setForeground(m_palette.link()); qCDebug(lcMD) << "anchor" << url << title; } break; -- cgit v1.2.3 From 1b16f79bf2a4efa5c8f60ae48adbf563fa819611 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Thu, 2 May 2019 18:14:20 +0200 Subject: QSharedData: delete the copy assignment operator Do not merely declare it as private, use C++11's = delete. This has the nice side effect that subclasses are no longer implicitly copy assignable either (they shouldn't be). Change-Id: Icd03f71006c31baf7d079365fa3bea1a2a9d559b Reviewed-by: Thiago Macieira --- src/corelib/tools/qshareddata.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/corelib/tools/qshareddata.h b/src/corelib/tools/qshareddata.h index 04051472d6..c29a509209 100644 --- a/src/corelib/tools/qshareddata.h +++ b/src/corelib/tools/qshareddata.h @@ -60,9 +60,8 @@ public: inline QSharedData() : ref(0) { } inline QSharedData(const QSharedData &) : ref(0) { } -private: // using the assignment operator would lead to corruption in the ref-counting - QSharedData &operator=(const QSharedData &); + QSharedData &operator=(const QSharedData &) = delete; }; template class QSharedDataPointer -- cgit v1.2.3 From fe57936d8c6e1bdafea5ba3260cc05c137a88ead Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Sat, 27 Apr 2019 22:10:17 +0200 Subject: qIsNull: redo implementation The reason for using type-punning through an integer was to avoid compiler warnings about float comparisons. We have now a better mechanism to suppress such warnings, so there is no need to be "clever" and trigger UB because of the union usage. Drive-by change: add constexpr+noexcept because now there's no longer UB. Change-Id: I29f7514e39055658d4ef6c431daf5abfc660df16 Reviewed-by: Edward Welbourne Reviewed-by: Thiago Macieira --- src/corelib/global/qglobal.h | 36 ++++++++++-------------------------- 1 file changed, 10 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 4817acb48f..a1f191516a 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -902,38 +902,22 @@ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR static inline Q_DECL_UNUSED bool qFuzzyIsNul return qAbs(f) <= 0.00001f; } -/* - This function tests a double for a null value. It doesn't - check whether the actual value is 0 or close to 0, but whether - it is binary 0, disregarding sign. -*/ -Q_REQUIRED_RESULT static inline Q_DECL_UNUSED bool qIsNull(double d) +QT_WARNING_PUSH +QT_WARNING_DISABLE_CLANG("-Wfloat-equal") +QT_WARNING_DISABLE_GCC("-Wfloat-equal") + +Q_REQUIRED_RESULT Q_DECL_CONSTEXPR static inline Q_DECL_UNUSED bool qIsNull(double d) noexcept { - union U { - double d; - quint64 u; - }; - U val; - val.d = d; - return (val.u & Q_UINT64_C(0x7fffffffffffffff)) == 0; + return d == 0.0; } -/* - This function tests a float for a null value. It doesn't - check whether the actual value is 0 or close to 0, but whether - it is binary 0, disregarding sign. -*/ -Q_REQUIRED_RESULT static inline Q_DECL_UNUSED bool qIsNull(float f) +Q_REQUIRED_RESULT Q_DECL_CONSTEXPR static inline Q_DECL_UNUSED bool qIsNull(float f) noexcept { - union U { - float f; - quint32 u; - }; - U val; - val.f = f; - return (val.u & 0x7fffffff) == 0; + return f == 0.0f; } +QT_WARNING_POP + /* Compilers which follow outdated template instantiation rules require a class to have a comparison operator to exist when -- cgit v1.2.3 From 78a7e54f8f5c4ca6ce1ee6b0ac82c42b21738ac5 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Mon, 3 Dec 2018 16:03:17 +0100 Subject: Custom color-space based on chromaticities Change-Id: I7fa6efa8993aa2b79ea60b6a21bf57c4f67a120f Reviewed-by: Eirik Aavitsland --- src/gui/painting/qcolormatrix_p.h | 45 +++++++++-- src/gui/painting/qcolorspace.cpp | 155 ++++++++++++++++++++++++++++++++------ src/gui/painting/qcolorspace.h | 3 + src/gui/painting/qcolorspace_p.h | 26 +++++++ 4 files changed, 201 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/gui/painting/qcolormatrix_p.h b/src/gui/painting/qcolormatrix_p.h index 3d1dca6222..66db95df7e 100644 --- a/src/gui/painting/qcolormatrix_p.h +++ b/src/gui/painting/qcolormatrix_p.h @@ -52,6 +52,7 @@ // #include +#include #include QT_BEGIN_NAMESPACE @@ -61,7 +62,13 @@ class QColorVector { public: QColorVector() = default; - constexpr QColorVector(float x, float y, float z) : x(x), y(y), z(z), _unused(0.0f) { } + Q_DECL_CONSTEXPR QColorVector(float x, float y, float z) : x(x), y(y), z(z), _unused(0.0f) { } + explicit Q_DECL_CONSTEXPR QColorVector(const QPointF &chr) // from XY chromaticity + : x(chr.x() / chr.y()) + , y(1.0f) + , z((1.0 - chr.x() - chr.y()) / chr.y()) + , _unused(0.0f) + { } float x; // X, x or red float y; // Y, y or green float z; // Z, Y or blue @@ -69,11 +76,28 @@ public: friend inline bool operator==(const QColorVector &v1, const QColorVector &v2); friend inline bool operator!=(const QColorVector &v1, const QColorVector &v2); + bool isNull() const + { + return !x && !y && !z; + } + + static Q_DECL_CONSTEXPR QColorVector null() { return QColorVector(0.0f, 0.0f, 0.0f); } + static bool isValidChromaticity(const QPointF &chr) + { + if (chr.x() < qreal(0.0) || chr.x() > qreal(1.0)) + return false; + if (chr.y() <= qreal(0.0) || chr.y() > qreal(1.0)) + return false; + if (chr.x() + chr.y() > qreal(1.0)) + return false; + return true; + } - static constexpr QColorVector null() { return QColorVector(0.0f, 0.0f, 0.0f); } - // Common whitepoints on normalized XYZ form: - static constexpr QColorVector D50() { return QColorVector(0.96421f, 1.0f, 0.82519f); } - static constexpr QColorVector D65() { return QColorVector(0.95043f, 1.0f, 1.08890f); } + // Common whitepoints: + static Q_DECL_CONSTEXPR QPointF D50Chromaticity() { return QPointF(0.34567, 0.35850); } + static Q_DECL_CONSTEXPR QPointF D65Chromaticity() { return QPointF(0.31271, 0.32902); } + static Q_DECL_CONSTEXPR QColorVector D50() { return QColorVector(D50Chromaticity()); } + static Q_DECL_CONSTEXPR QColorVector D65() { return QColorVector(D65Chromaticity()); } }; inline bool operator==(const QColorVector &v1, const QColorVector &v2) @@ -102,6 +126,10 @@ public: friend inline bool operator==(const QColorMatrix &m1, const QColorMatrix &m2); friend inline bool operator!=(const QColorMatrix &m1, const QColorMatrix &m2); + bool isNull() const + { + return r.isNull() && g.isNull() && b.isNull(); + } bool isValid() const { // A color matrix must be invertible @@ -167,6 +195,13 @@ public: { return { { 1.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f, 1.0f } }; } + static QColorMatrix fromScale(QColorVector v) + { + return QColorMatrix { { v.x, 0.0f, 0.0f }, + { 0.0f, v.y, 0.0f }, + { 0.0f, 0.0f, v.z } }; + } + // These are used to recognize matrices from ICC profiles: static QColorMatrix toXyzFromSRgb() { return QColorMatrix { { 0.4360217452f, 0.2224751115f, 0.0139281144f }, diff --git a/src/gui/painting/qcolorspace.cpp b/src/gui/painting/qcolorspace.cpp index 24785f7b61..c98c31fe05 100644 --- a/src/gui/painting/qcolorspace.cpp +++ b/src/gui/painting/qcolorspace.cpp @@ -53,6 +53,102 @@ QT_BEGIN_NAMESPACE +QColorSpacePrimaries::QColorSpacePrimaries(QColorSpace::Gamut gamut) +{ + switch (gamut) { + case QColorSpace::Gamut::SRgb: + redPoint = QPointF(0.640, 0.330); + greenPoint = QPointF(0.300, 0.600); + bluePoint = QPointF(0.150, 0.060); + whitePoint = QColorVector::D65Chromaticity(); + break; + case QColorSpace::Gamut::DciP3D65: + redPoint = QPointF(0.680, 0.320); + greenPoint = QPointF(0.265, 0.690); + bluePoint = QPointF(0.150, 0.060); + whitePoint = QColorVector::D65Chromaticity(); + break; + case QColorSpace::Gamut::Bt2020: + redPoint = QPointF(0.708, 0.292); + greenPoint = QPointF(0.190, 0.797); + bluePoint = QPointF(0.131, 0.046); + whitePoint = QColorVector::D65Chromaticity(); + break; + case QColorSpace::Gamut::AdobeRgb: + redPoint = QPointF(0.640, 0.330); + greenPoint = QPointF(0.210, 0.710); + bluePoint = QPointF(0.150, 0.060); + whitePoint = QColorVector::D65Chromaticity(); + break; + case QColorSpace::Gamut::ProPhotoRgb: + redPoint = QPointF(0.7347, 0.2653); + greenPoint = QPointF(0.1596, 0.8404); + bluePoint = QPointF(0.0366, 0.0001); + whitePoint = QColorVector::D50Chromaticity(); + break; + default: + Q_UNREACHABLE(); + } +} + +bool QColorSpacePrimaries::areValid() const +{ + if (!QColorVector::isValidChromaticity(redPoint)) + return false; + if (!QColorVector::isValidChromaticity(greenPoint)) + return false; + if (!QColorVector::isValidChromaticity(bluePoint)) + return false; + if (!QColorVector::isValidChromaticity(whitePoint)) + return false; + return true; +} + +QColorMatrix QColorSpacePrimaries::toXyzMatrix() const +{ + // This converts to XYZ in some undefined scale. + QColorMatrix toXyz = { QColorVector(redPoint), + QColorVector(greenPoint), + QColorVector(bluePoint) }; + + // Since the white point should be (1.0, 1.0, 1.0) in the + // input, we can figure out the scale by using the + // inverse conversion on the white point. + QColorVector wXyz(whitePoint); + QColorVector whiteScale = toXyz.inverted().map(wXyz); + + // Now we have scaled conversion to XYZ relative to the given whitepoint + toXyz = toXyz * QColorMatrix::fromScale(whiteScale); + + // But we want a conversion to XYZ relative to D50 + QColorVector wXyzD50 = QColorVector::D50(); + + if (wXyz != wXyzD50) { + // Do chromatic adaptation to map our white point to XYZ D50. + + // The Bradford method chromatic adaptation matrix: + QColorMatrix abrad = { { 0.8951f, -0.7502f, 0.0389f }, + { 0.2664f, 1.7135f, -0.0685f }, + { -0.1614f, 0.0367f, 1.0296f } }; + QColorMatrix abradinv = { { 0.9869929f, 0.4323053f, -0.0085287f }, + { -0.1470543f, 0.5183603f, 0.0400428f }, + { 0.1599627f, 0.0492912f, 0.9684867f } }; + + QColorVector srcCone = abrad.map(wXyz); + QColorVector dstCone = abrad.map(wXyzD50); + + QColorMatrix wToD50 = { { dstCone.x / srcCone.x, 0, 0 }, + { 0, dstCone.y / srcCone.y, 0 }, + { 0, 0, dstCone.z / srcCone.z } }; + + + QColorMatrix chromaticAdaptation = abradinv * (wToD50 * abrad); + toXyz = chromaticAdaptation * toXyz; + } + + return toXyz; +} + QColorSpacePrivate::QColorSpacePrivate() : id(QColorSpace::Unknown) , gamut(QColorSpace::Gamut::Custom) @@ -128,6 +224,21 @@ QColorSpacePrivate::QColorSpacePrivate(QColorSpace::Gamut gamut, QColorSpace::Tr initialize(); } +QColorSpacePrivate::QColorSpacePrivate(const QColorSpacePrimaries &primaries, + QColorSpace::TransferFunction fun, + float gamma) + : gamut(QColorSpace::Gamut::Custom) + , transferFunction(fun) + , gamma(gamma) +{ + Q_ASSERT(primaries.areValid()); + toXyz = primaries.toXyzMatrix(); + whitePoint = QColorVector(primaries.whitePoint); + if (!identifyColorSpace()) + id = QColorSpace::Unknown; + setTransferFunction(); +} + bool QColorSpacePrivate::identifyColorSpace() { switch (gamut) { @@ -195,33 +306,14 @@ void QColorSpacePrivate::initialize() void QColorSpacePrivate::setToXyzMatrix() { - switch (gamut) { - case QColorSpace::Gamut::SRgb: - toXyz = QColorMatrix::toXyzFromSRgb(); - whitePoint = QColorVector::D65(); - return; - case QColorSpace::Gamut::AdobeRgb: - toXyz = QColorMatrix::toXyzFromAdobeRgb(); - whitePoint = QColorVector::D65(); - return; - case QColorSpace::Gamut::DciP3D65: - toXyz = QColorMatrix::toXyzFromDciP3D65(); - whitePoint = QColorVector::D65(); - return; - case QColorSpace::Gamut::ProPhotoRgb: - toXyz = QColorMatrix::toXyzFromProPhotoRgb(); - whitePoint = QColorVector::D50(); - return; - case QColorSpace::Gamut::Bt2020: - toXyz = QColorMatrix::toXyzFromBt2020(); - whitePoint = QColorVector::D65(); - return; - case QColorSpace::Gamut::Custom: + if (gamut == QColorSpace::Gamut::Custom) { toXyz = QColorMatrix::null(); whitePoint = QColorVector::D50(); return; } - Q_UNREACHABLE(); + QColorSpacePrimaries primaries(gamut); + toXyz = primaries.toXyzMatrix(); + whitePoint = QColorVector(primaries.whitePoint); } void QColorSpacePrivate::setTransferFunction() @@ -386,6 +478,23 @@ QColorSpace::QColorSpace(QColorSpace::Gamut gamut, float gamma) { } +/*! + Creates a custom colorspace with a gamut based on the chromaticities of the primary colors \a whitePoint, + \a redPoint, \a greenPoint and \a bluePoint, and using the transfer function \a fun and optionally \a gamma. + */ +QColorSpace::QColorSpace(const QPointF &whitePoint, const QPointF &redPoint, + const QPointF &greenPoint, const QPointF &bluePoint, + QColorSpace::TransferFunction fun, float gamma) +{ + QColorSpacePrimaries primaries(whitePoint, redPoint, greenPoint, bluePoint); + if (!primaries.areValid()) { + qWarning() << "QColorSpace attempted constructed from invalid primaries:" << whitePoint << redPoint << greenPoint << bluePoint; + d_ptr = QColorSpace(QColorSpace::Undefined).d_ptr; + return; + } + d_ptr = new QColorSpacePrivate(primaries, fun, gamma); +} + QColorSpace::~QColorSpace() { } diff --git a/src/gui/painting/qcolorspace.h b/src/gui/painting/qcolorspace.h index 923546ec6f..56676826a9 100644 --- a/src/gui/painting/qcolorspace.h +++ b/src/gui/painting/qcolorspace.h @@ -85,6 +85,9 @@ public: QColorSpace(ColorSpaceId colorSpaceId = Undefined); QColorSpace(Gamut gamut, TransferFunction fun, float gamma = 0.0f); QColorSpace(Gamut gamut, float gamma); + QColorSpace(const QPointF &whitePoint, const QPointF &redPoint, + const QPointF &greenPoint, const QPointF &bluePoint, + TransferFunction fun, float gamma = 0.0f); ~QColorSpace(); QColorSpace(QColorSpace &&colorSpace); diff --git a/src/gui/painting/qcolorspace_p.h b/src/gui/painting/qcolorspace_p.h index 91107a9a89..21260a281d 100644 --- a/src/gui/painting/qcolorspace_p.h +++ b/src/gui/painting/qcolorspace_p.h @@ -57,15 +57,41 @@ #include "qcolortrclut_p.h" #include +#include QT_BEGIN_NAMESPACE +class Q_GUI_EXPORT QColorSpacePrimaries +{ +public: + QColorSpacePrimaries() = default; + QColorSpacePrimaries(QColorSpace::Gamut gamut); + QColorSpacePrimaries(QPointF whitePoint, + QPointF redPoint, + QPointF greenPoint, + QPointF bluePoint) + : whitePoint(whitePoint) + , redPoint(redPoint) + , greenPoint(greenPoint) + , bluePoint(bluePoint) + { } + + QColorMatrix toXyzMatrix() const; + bool areValid() const; + + QPointF whitePoint; + QPointF redPoint; + QPointF greenPoint; + QPointF bluePoint; +}; + class QColorSpacePrivate : public QSharedData { public: QColorSpacePrivate(); QColorSpacePrivate(QColorSpace::ColorSpaceId colorSpaceId); QColorSpacePrivate(QColorSpace::Gamut gamut, QColorSpace::TransferFunction fun, float gamma); + QColorSpacePrivate(const QColorSpacePrimaries &primaries, QColorSpace::TransferFunction fun, float gamma); QColorSpacePrivate(const QColorSpacePrivate &other) = default; QColorSpacePrivate &operator=(const QColorSpacePrivate &other) = default; -- cgit v1.2.3 From d775b1fcb3fc7bd41af37f5d0a4d999320b62364 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Thu, 4 Apr 2019 18:13:32 +0200 Subject: Remove handling of missing Q_COMPILER_INITIALIZER_LISTS Change-Id: Id65b39c787235a051262544932e6717d076f1ea0 Reviewed-by: Edward Welbourne Reviewed-by: Thiago Macieira --- src/corelib/global/qflags.h | 6 ------ src/corelib/global/qoperatingsystemversion.cpp | 2 -- src/corelib/global/qoperatingsystemversion.h | 2 -- src/corelib/serialization/qjsonarray.h | 4 ---- src/corelib/serialization/qjsonobject.h | 4 ---- src/corelib/tools/qhash.h | 9 +-------- src/corelib/tools/qlinkedlist.h | 10 ++-------- src/corelib/tools/qlist.h | 9 ++------- src/corelib/tools/qmap.h | 11 ++--------- src/corelib/tools/qset.h | 5 ----- src/corelib/tools/qstringlist.h | 2 -- src/corelib/tools/qvarlengtharray.h | 12 +++--------- src/corelib/tools/qvector.h | 16 +++++----------- src/corelib/tools/qversionnumber.h | 4 ---- 14 files changed, 15 insertions(+), 81 deletions(-) (limited to 'src') diff --git a/src/corelib/global/qflags.h b/src/corelib/global/qflags.h index 65f4892472..bd3c219968 100644 --- a/src/corelib/global/qflags.h +++ b/src/corelib/global/qflags.h @@ -42,9 +42,7 @@ #ifndef QFLAGS_H #define QFLAGS_H -#ifdef Q_COMPILER_INITIALIZER_LISTS #include -#endif QT_BEGIN_NAMESPACE @@ -121,10 +119,8 @@ public: Q_DECL_CONSTEXPR inline QFlags(Zero = nullptr) noexcept : i(0) {} Q_DECL_CONSTEXPR inline QFlags(QFlag flag) noexcept : i(flag) {} -#ifdef Q_COMPILER_INITIALIZER_LISTS Q_DECL_CONSTEXPR inline QFlags(std::initializer_list flags) noexcept : i(initializer_list_helper(flags.begin(), flags.end())) {} -#endif Q_DECL_RELAXED_CONSTEXPR inline QFlags &operator&=(int mask) noexcept { i &= mask; return *this; } Q_DECL_RELAXED_CONSTEXPR inline QFlags &operator&=(uint mask) noexcept { i &= mask; return *this; } @@ -154,14 +150,12 @@ public: } private: -#ifdef Q_COMPILER_INITIALIZER_LISTS Q_DECL_CONSTEXPR static inline Int initializer_list_helper(typename std::initializer_list::const_iterator it, typename std::initializer_list::const_iterator end) noexcept { return (it == end ? Int(0) : (Int(*it) | initializer_list_helper(it + 1, end))); } -#endif Int i; }; diff --git a/src/corelib/global/qoperatingsystemversion.cpp b/src/corelib/global/qoperatingsystemversion.cpp index 94dc261b41..42a1275621 100644 --- a/src/corelib/global/qoperatingsystemversion.cpp +++ b/src/corelib/global/qoperatingsystemversion.cpp @@ -340,7 +340,6 @@ QString QOperatingSystemVersion::name() const } } -#ifdef Q_COMPILER_INITIALIZER_LISTS /*! \fn bool QOperatingSystemVersion::isAnyOfType(std::initializer_list types) const @@ -355,7 +354,6 @@ bool QOperatingSystemVersion::isAnyOfType(std::initializer_list types) c } return false; } -#endif /*! \variable QOperatingSystemVersion::Windows7 diff --git a/src/corelib/global/qoperatingsystemversion.h b/src/corelib/global/qoperatingsystemversion.h index df01e5438a..e99e4f8997 100644 --- a/src/corelib/global/qoperatingsystemversion.h +++ b/src/corelib/global/qoperatingsystemversion.h @@ -119,9 +119,7 @@ public: Q_DECL_CONSTEXPR int segmentCount() const { return m_micro >= 0 ? 3 : m_minor >= 0 ? 2 : m_major >= 0 ? 1 : 0; } -#ifdef Q_COMPILER_INITIALIZER_LISTS bool isAnyOfType(std::initializer_list types) const; -#endif Q_DECL_CONSTEXPR OSType type() const { return m_os; } QString name() const; diff --git a/src/corelib/serialization/qjsonarray.h b/src/corelib/serialization/qjsonarray.h index 86b7bf9d76..983a6753b5 100644 --- a/src/corelib/serialization/qjsonarray.h +++ b/src/corelib/serialization/qjsonarray.h @@ -42,9 +42,7 @@ #include #include -#if defined(Q_COMPILER_INITIALIZER_LISTS) #include -#endif QT_BEGIN_NAMESPACE @@ -58,14 +56,12 @@ class Q_CORE_EXPORT QJsonArray public: QJsonArray(); -#if defined(Q_COMPILER_INITIALIZER_LISTS) || defined(Q_QDOC) QJsonArray(std::initializer_list args) { initialize(); for (std::initializer_list::const_iterator i = args.begin(); i != args.end(); ++i) append(*i); } -#endif ~QJsonArray(); diff --git a/src/corelib/serialization/qjsonobject.h b/src/corelib/serialization/qjsonobject.h index 92d45cc838..d8e2ab9ca7 100644 --- a/src/corelib/serialization/qjsonobject.h +++ b/src/corelib/serialization/qjsonobject.h @@ -42,10 +42,8 @@ #include #include -#ifdef Q_COMPILER_INITIALIZER_LISTS #include #include -#endif QT_BEGIN_NAMESPACE @@ -60,14 +58,12 @@ class Q_CORE_EXPORT QJsonObject public: QJsonObject(); -#if defined(Q_COMPILER_INITIALIZER_LISTS) || defined(Q_QDOC) QJsonObject(std::initializer_list > args) { initialize(); for (std::initializer_list >::const_iterator i = args.begin(); i != args.end(); ++i) insert(i->first, i->second); } -#endif ~QJsonObject(); diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h index 0078bbbee9..4b4cb2d5f0 100644 --- a/src/corelib/tools/qhash.h +++ b/src/corelib/tools/qhash.h @@ -48,11 +48,8 @@ #include #include -#ifdef Q_COMPILER_INITIALIZER_LISTS -#include -#endif - #include +#include #if defined(Q_CC_MSVC) #pragma warning( push ) @@ -242,7 +239,6 @@ class QHash public: inline QHash() noexcept : d(const_cast(&QHashData::shared_null)) { } -#ifdef Q_COMPILER_INITIALIZER_LISTS inline QHash(std::initializer_list > list) : d(const_cast(&QHashData::shared_null)) { @@ -250,7 +246,6 @@ public: for (typename std::initializer_list >::const_iterator it = list.begin(); it != list.end(); ++it) insert(it->first, it->second); } -#endif QHash(const QHash &other) : d(other.d) { d->ref.ref(); if (!d->sharable) detach(); } ~QHash() { if (!d->ref.deref()) freeData(d); } @@ -1042,14 +1037,12 @@ class QMultiHash : public QHash { public: QMultiHash() noexcept {} -#ifdef Q_COMPILER_INITIALIZER_LISTS inline QMultiHash(std::initializer_list > list) { this->reserve(int(list.size())); for (typename std::initializer_list >::const_iterator it = list.begin(); it != list.end(); ++it) insert(it->first, it->second); } -#endif #ifdef Q_QDOC template QMultiHash(InputIterator f, InputIterator l); diff --git a/src/corelib/tools/qlinkedlist.h b/src/corelib/tools/qlinkedlist.h index 0c8a99e258..8994449fbf 100644 --- a/src/corelib/tools/qlinkedlist.h +++ b/src/corelib/tools/qlinkedlist.h @@ -44,15 +44,11 @@ #include #include +#include +#include #include #include -#include - -#if defined(Q_COMPILER_INITIALIZER_LISTS) -# include -#endif - QT_BEGIN_NAMESPACE @@ -83,10 +79,8 @@ class QLinkedList public: inline QLinkedList() noexcept : d(const_cast(&QLinkedListData::shared_null)) { } inline QLinkedList(const QLinkedList &l) : d(l.d) { d->ref.ref(); if (!d->sharable) detach(); } -#if defined(Q_COMPILER_INITIALIZER_LISTS) inline QLinkedList(std::initializer_list list) : QLinkedList(list.begin(), list.end()) {} -#endif template = true> inline QLinkedList(InputIterator first, InputIterator last) : QLinkedList() diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index b916dcfd24..27868f7313 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -48,12 +48,10 @@ #include #include -#include -#include #include -#ifdef Q_COMPILER_INITIALIZER_LISTS #include -#endif +#include +#include #include #include @@ -166,13 +164,10 @@ public: inline QList &operator=(QList &&other) noexcept { QList moved(std::move(other)); swap(moved); return *this; } inline void swap(QList &other) noexcept { qSwap(d, other.d); } -#ifdef Q_COMPILER_INITIALIZER_LISTS inline QList(std::initializer_list args) : QList(args.begin(), args.end()) {} -#endif template = true> QList(InputIterator first, InputIterator last); - bool operator==(const QList &l) const; inline bool operator!=(const QList &l) const { return !(*this == l); } diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h index 2d01a75a42..18c681581f 100644 --- a/src/corelib/tools/qmap.h +++ b/src/corelib/tools/qmap.h @@ -49,13 +49,10 @@ #include #endif -#include -#include #include - -#ifdef Q_COMPILER_INITIALIZER_LISTS #include -#endif +#include +#include QT_BEGIN_NAMESPACE @@ -326,14 +323,12 @@ class QMap public: inline QMap() noexcept : d(static_cast *>(const_cast(&QMapDataBase::shared_null))) { } -#ifdef Q_COMPILER_INITIALIZER_LISTS inline QMap(std::initializer_list > list) : d(static_cast *>(const_cast(&QMapDataBase::shared_null))) { for (typename std::initializer_list >::const_iterator it = list.begin(); it != list.end(); ++it) insert(it->first, it->second); } -#endif QMap(const QMap &other); inline ~QMap() { if (!d->ref.deref()) d->destroy(); } @@ -1186,13 +1181,11 @@ class QMultiMap : public QMap { public: QMultiMap() noexcept {} -#ifdef Q_COMPILER_INITIALIZER_LISTS inline QMultiMap(std::initializer_list > list) { for (typename std::initializer_list >::const_iterator it = list.begin(); it != list.end(); ++it) insert(it->first, it->second); } -#endif QMultiMap(const QMap &other) : QMap(other) {} QMultiMap(QMap &&other) noexcept : QMap(std::move(other)) {} void swap(QMultiMap &other) noexcept { QMap::swap(other); } diff --git a/src/corelib/tools/qset.h b/src/corelib/tools/qset.h index 7ae715d247..8b31de71a9 100644 --- a/src/corelib/tools/qset.h +++ b/src/corelib/tools/qset.h @@ -43,10 +43,7 @@ #include #include -#ifdef Q_COMPILER_INITIALIZER_LISTS #include -#endif - #include QT_BEGIN_NAMESPACE @@ -59,10 +56,8 @@ class QSet public: inline QSet() noexcept {} -#ifdef Q_COMPILER_INITIALIZER_LISTS inline QSet(std::initializer_list list) : QSet(list.begin(), list.end()) {} -#endif template = true> inline QSet(InputIterator first, InputIterator last) { diff --git a/src/corelib/tools/qstringlist.h b/src/corelib/tools/qstringlist.h index 73ac737643..cf136a64c6 100644 --- a/src/corelib/tools/qstringlist.h +++ b/src/corelib/tools/qstringlist.h @@ -105,9 +105,7 @@ public: inline explicit QStringList(const QString &i) { append(i); } inline QStringList(const QList &l) : QList(l) { } inline QStringList(QList &&l) noexcept : QList(std::move(l)) { } -#ifdef Q_COMPILER_INITIALIZER_LISTS inline QStringList(std::initializer_list args) : QList(args) { } -#endif template = true> inline QStringList(InputIterator first, InputIterator last) : QList(first, last) { } diff --git a/src/corelib/tools/qvarlengtharray.h b/src/corelib/tools/qvarlengtharray.h index c81af68593..01fc63b677 100644 --- a/src/corelib/tools/qvarlengtharray.h +++ b/src/corelib/tools/qvarlengtharray.h @@ -45,14 +45,12 @@ #include #include -#include -#include -#include #include -#ifdef Q_COMPILER_INITIALIZER_LISTS #include -#endif #include +#include +#include +#include QT_BEGIN_NAMESPACE @@ -70,12 +68,10 @@ public: append(other.constData(), other.size()); } -#ifdef Q_COMPILER_INITIALIZER_LISTS QVarLengthArray(std::initializer_list args) : QVarLengthArray(args.begin(), args.end()) { } -#endif template = true> inline QVarLengthArray(InputIterator first, InputIterator last) @@ -103,7 +99,6 @@ public: return *this; } -#ifdef Q_COMPILER_INITIALIZER_LISTS QVarLengthArray &operator=(std::initializer_list list) { resize(list.size()); @@ -111,7 +106,6 @@ public: QT_MAKE_CHECKED_ARRAY_ITERATOR(this->begin(), this->size())); return *this; } -#endif inline void removeLast() { Q_ASSERT(s > 0); diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h index 7e14a0c9b2..d6baa76a30 100644 --- a/src/corelib/tools/qvector.h +++ b/src/corelib/tools/qvector.h @@ -48,12 +48,10 @@ #include #include +#include #include #include #include -#ifdef Q_COMPILER_INITIALIZER_LISTS -#include -#endif #include @@ -76,10 +74,8 @@ public: QVector &operator=(QVector &&other) noexcept { QVector moved(std::move(other)); swap(moved); return *this; } void swap(QVector &other) noexcept { qSwap(d, other.d); } -#ifdef Q_COMPILER_INITIALIZER_LISTS inline QVector(std::initializer_list args); QVector &operator=(std::initializer_list args); -#endif template = true> inline QVector(InputIterator first, InputIterator last); @@ -521,11 +517,10 @@ QVector::QVector(int asize, const T &t) } } -#ifdef Q_COMPILER_INITIALIZER_LISTS -# if defined(Q_CC_MSVC) +#if defined(Q_CC_MSVC) QT_WARNING_PUSH QT_WARNING_DISABLE_MSVC(4127) // conditional expression is constant -# endif // Q_CC_MSVC +#endif // Q_CC_MSVC template QVector::QVector(std::initializer_list args) @@ -550,10 +545,9 @@ QVector &QVector::operator=(std::initializer_list args) return *this; } -# if defined(Q_CC_MSVC) +#if defined(Q_CC_MSVC) QT_WARNING_POP -# endif // Q_CC_MSVC -#endif // Q_COMPILER_INITIALIZER_LISTS +#endif // Q_CC_MSVC template template > diff --git a/src/corelib/tools/qversionnumber.h b/src/corelib/tools/qversionnumber.h index 1488014d38..d43b86ba51 100644 --- a/src/corelib/tools/qversionnumber.h +++ b/src/corelib/tools/qversionnumber.h @@ -138,7 +138,6 @@ class QVersionNumber else pointer_segments = new QVector(std::move(seg)); } -#ifdef Q_COMPILER_INITIALIZER_LISTS SegmentStorage(std::initializer_list args) { if (dataFitsInline(args.begin(), int(args.size()))) { @@ -147,7 +146,6 @@ class QVersionNumber pointer_segments = new QVector(args); } } -#endif ~SegmentStorage() { if (isUsingPointer()) delete pointer_segments; } @@ -229,11 +227,9 @@ public: : m_segments(std::move(seg)) {} -#ifdef Q_COMPILER_INITIALIZER_LISTS inline QVersionNumber(std::initializer_list args) : m_segments(args) {} -#endif inline explicit QVersionNumber(int maj) { m_segments.setSegments(1, maj); } -- cgit v1.2.3 From 1f1e04f29f93401c8d0aa0941f92cc1e4a6c7688 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 2 May 2019 14:31:34 +0200 Subject: Deprecate providing a function as a property flag Property flags such as SCRIPTABLE should not get controlled by a function. I can't see this feature being used anywhere and it leads to additional overhead that I'd like to get rid of for Qt 6. Change-Id: Iaa10b2b3bfb7eec11401f7b6bb887c9467b67183 Reviewed-by: Thiago Macieira Reviewed-by: Simon Hausmann --- src/tools/moc/moc.cpp | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp index 7f43917f7e..2f0ea633fa 100644 --- a/src/tools/moc/moc.cpp +++ b/src/tools/moc/moc.cpp @@ -1194,6 +1194,15 @@ void Moc::createPropertyDef(PropertyDef &propDef) propDef.type = type; + auto checkIsFunction = [&](const QByteArray &def, const char *name) { + if (def.endsWith(')')) { + QByteArray msg = "Providing a function for "; + msg += name; + msg += " in a property declaration is deprecated and will not be supported in Qt 6 anymore."; + warning(msg.constData()); + } + }; + next(); propDef.name = lexem(); while (test(IDENTIFIER)) { @@ -1243,11 +1252,13 @@ void Moc::createPropertyDef(PropertyDef &propDef) error(2); break; case 'S': - if (l == "SCRIPTABLE") + if (l == "SCRIPTABLE") { propDef.scriptable = v + v2; - else if (l == "STORED") + checkIsFunction(propDef.scriptable, "SCRIPTABLE"); + } else if (l == "STORED") { propDef.stored = v + v2; - else + checkIsFunction(propDef.stored, "STORED"); + } else error(2); break; case 'W': if (l != "WRITE") error(2); @@ -1255,15 +1266,18 @@ void Moc::createPropertyDef(PropertyDef &propDef) break; case 'D': if (l != "DESIGNABLE") error(2); propDef.designable = v + v2; + checkIsFunction(propDef.designable, "DESIGNABLE"); break; case 'E': if (l != "EDITABLE") error(2); propDef.editable = v + v2; + checkIsFunction(propDef.editable, "EDITABLE"); break; case 'N': if (l != "NOTIFY") error(2); propDef.notify = v; break; case 'U': if (l != "USER") error(2); propDef.user = v + v2; + checkIsFunction(propDef.user, "USER"); break; default: error(2); -- cgit v1.2.3 From e929808c83e4a473135590c69413a98f36a3500a Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Fri, 3 May 2019 11:43:03 +0200 Subject: Prefix QTextStream operators with Qt:: Change-Id: I128769cb78abb8168f0bf29cef8c693073793ced Reviewed-by: Allan Sandfeld Jensen --- src/gui/text/qtextmarkdownwriter.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/gui/text/qtextmarkdownwriter.cpp b/src/gui/text/qtextmarkdownwriter.cpp index fed4a7b766..313d62bb8a 100644 --- a/src/gui/text/qtextmarkdownwriter.cpp +++ b/src/gui/text/qtextmarkdownwriter.cpp @@ -80,10 +80,10 @@ void QTextMarkdownWriter::writeTable(const QAbstractTableModel &table) QString s = table.headerData(col, Qt::Horizontal).toString(); m_stream << "|" << s << QString(tableColumnWidths[col] - s.length(), Space); } - m_stream << "|" << endl; + m_stream << "|" << Qt::endl; for (int col = 0; col < tableColumnWidths.length(); ++col) m_stream << '|' << QString(tableColumnWidths[col], QLatin1Char('-')); - m_stream << '|'<< endl; + m_stream << '|'<< Qt::endl; // write the body for (int row = 0; row < table.rowCount(); ++row) { @@ -91,7 +91,7 @@ void QTextMarkdownWriter::writeTable(const QAbstractTableModel &table) QString s = table.data(table.index(row, col)).toString(); m_stream << "|" << s << QString(tableColumnWidths[col] - s.length(), Space); } - m_stream << '|'<< endl; + m_stream << '|'<< Qt::endl; } } -- cgit v1.2.3 From b5547e49cd1760ba5d100dcc720e6366cbd23f06 Mon Sep 17 00:00:00 2001 From: Kevin Funk Date: Thu, 25 Apr 2019 16:33:20 +0200 Subject: Fix minor compiler warning from Clang Fixes: .../qcolorspace_p.h:70:25: warning: explicitly defaulted copy assignment operator is implicitly deleted [-Wdefaulted-function-deleted] QColorSpacePrivate &operator=(const QColorSpacePrivate &other) = default; ^ .../qcolorspace_p.h:63:28: note: copy assignment operator of 'QColorSpacePrivate' is implicitly deleted because base class 'QSharedData' has an inaccessible copy assignment operator class QColorSpacePrivate : public QSharedData ^ Change-Id: I20d453279ec2cb8b9b9d1364762c6e560d6f843d Reviewed-by: Simon Hausmann --- src/gui/painting/qcolorspace_p.h | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/gui/painting/qcolorspace_p.h b/src/gui/painting/qcolorspace_p.h index 21260a281d..a6ab2ab5cd 100644 --- a/src/gui/painting/qcolorspace_p.h +++ b/src/gui/painting/qcolorspace_p.h @@ -93,7 +93,6 @@ public: QColorSpacePrivate(QColorSpace::Gamut gamut, QColorSpace::TransferFunction fun, float gamma); QColorSpacePrivate(const QColorSpacePrimaries &primaries, QColorSpace::TransferFunction fun, float gamma); QColorSpacePrivate(const QColorSpacePrivate &other) = default; - QColorSpacePrivate &operator=(const QColorSpacePrivate &other) = default; void initialize(); void setToXyzMatrix(); -- cgit v1.2.3 From 82ddecfb17158c35de1d0740dd7ecd5562d41726 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Fri, 3 May 2019 11:53:18 +0200 Subject: Deprecate {to,from}Std{List,Vector} ask our users to use the range constructors instead. This will allow us to remove the include dependency towards and in Qt 6. Change-Id: Id90f2058432e19941de1fa847100a7920432ad71 Reviewed-by: Thiago Macieira --- src/corelib/tools/qlist.h | 6 ++++++ src/corelib/tools/qvector.h | 6 ++++++ 2 files changed, 12 insertions(+) (limited to 'src') diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index 27868f7313..513d7eafe1 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -51,7 +51,9 @@ #include #include #include +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) #include +#endif #include #include @@ -403,10 +405,14 @@ public: static QList fromVector(const QVector &vector); static QList fromSet(const QSet &set); +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) + Q_DECL_DEPRECATED_X("Use QList(list.begin(), list.end()) instead.") static inline QList fromStdList(const std::list &list) { QList tmp; std::copy(list.begin(), list.end(), std::back_inserter(tmp)); return tmp; } + Q_DECL_DEPRECATED_X("Use std::list(list.begin(), list.end()) instead.") inline std::list toStdList() const { std::list tmp; std::copy(constBegin(), constEnd(), std::back_inserter(tmp)); return tmp; } +#endif private: Node *detach_helper_grow(int i, int n); diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h index d6baa76a30..4e148c9c55 100644 --- a/src/corelib/tools/qvector.h +++ b/src/corelib/tools/qvector.h @@ -49,7 +49,9 @@ #include #include +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) #include +#endif #include #include @@ -292,10 +294,14 @@ public: static QVector fromList(const QList &list); +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) + Q_DECL_DEPRECATED_X("Use QVector(vector.begin(), vector.end()) instead.") static inline QVector fromStdVector(const std::vector &vector) { QVector tmp; tmp.reserve(int(vector.size())); std::copy(vector.begin(), vector.end(), std::back_inserter(tmp)); return tmp; } + Q_DECL_DEPRECATED_X("Use std::vector(vector.begin(), vector.end()) instead.") inline std::vector toStdVector() const { return std::vector(d->begin(), d->end()); } +#endif private: // ### Qt6: remove methods, they are unused void reallocData(const int size, const int alloc, QArrayData::AllocationOptions options = QArrayData::Default); -- cgit v1.2.3 From 08101b2b27f7f2177993ddb62c15187c169ccd19 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 30 Apr 2019 14:13:22 +0200 Subject: Fix qplugin.h for Qt 6 Change-Id: I3ae6594a2982f990a5b3851a063b0b2f02d16bd9 Reviewed-by: Thiago Macieira --- src/corelib/plugin/qplugin.h | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/corelib/plugin/qplugin.h b/src/corelib/plugin/qplugin.h index 676b5047d6..c176155c28 100644 --- a/src/corelib/plugin/qplugin.h +++ b/src/corelib/plugin/qplugin.h @@ -75,7 +75,12 @@ typedef QObject *(*QtPluginInstanceFunction)(); #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) typedef const char *(*QtPluginMetaDataFunction)(); #else -typedef QPair (*QtPluginMetaDataFunction)(); +struct QPluginMetaData +{ + const uchar *data; + size_t size; +}; +typedef QPluginMetaData (*QtPluginMetaDataFunction)(); #endif @@ -84,12 +89,14 @@ struct Q_CORE_EXPORT QStaticPlugin #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) public: constexpr QStaticPlugin(QtPluginInstanceFunction i, QtPluginMetaDataFunction m) - : instance(i), rawMetaData(m().first), rawMetaDataSize(m().second) + : instance(i), rawMetaData(m().data), rawMetaDataSize(m().size) + {} QtPluginInstanceFunction instance; private: // ### Qt 6: revise, as this is not standard-layout const void *rawMetaData; - qsizetype rawMetaDataSize + qsizetype rawMetaDataSize; +public: #elif !defined(Q_QDOC) // Note: This struct is initialized using an initializer list. // As such, it cannot have any new constructors or variables. @@ -154,6 +161,16 @@ void Q_CORE_EXPORT qRegisterStaticPluginFunction(QStaticPlugin staticPlugin); #if defined(QT_STATICPLUGIN) +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +# define QT_MOC_EXPORT_PLUGIN(PLUGINCLASS, PLUGINCLASSNAME) \ + static QT_PREPEND_NAMESPACE(QObject) *qt_plugin_instance_##PLUGINCLASSNAME() \ + Q_PLUGIN_INSTANCE(PLUGINCLASS) \ + static QPluginMetaData qt_plugin_query_metadata_##PLUGINCLASSNAME() \ + { return { qt_pluginMetaData, sizeof qt_pluginMetaData }; } \ + const QT_PREPEND_NAMESPACE(QStaticPlugin) qt_static_plugin_##PLUGINCLASSNAME() { \ + return { qt_plugin_instance_##PLUGINCLASSNAME, qt_plugin_query_metadata_##PLUGINCLASSNAME}; \ + } +#else # define QT_MOC_EXPORT_PLUGIN(PLUGINCLASS, PLUGINCLASSNAME) \ static QT_PREPEND_NAMESPACE(QObject) *qt_plugin_instance_##PLUGINCLASSNAME() \ Q_PLUGIN_INSTANCE(PLUGINCLASS) \ @@ -162,13 +179,15 @@ void Q_CORE_EXPORT qRegisterStaticPluginFunction(QStaticPlugin staticPlugin); QT_PREPEND_NAMESPACE(QStaticPlugin) plugin = { qt_plugin_instance_##PLUGINCLASSNAME, qt_plugin_query_metadata_##PLUGINCLASSNAME}; \ return plugin; \ } +#endif -#elif QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +#else +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) # define QT_MOC_EXPORT_PLUGIN(PLUGINCLASS, PLUGINCLASSNAME) \ Q_EXTERN_C Q_DECL_EXPORT \ - auto qt_plugin_query_metadata() \ - { return qMakePair(qt_pluginMetaData, sizeof qt_pluginMetaData); } \ + QPluginMetaData qt_plugin_query_metadata() \ + { return { qt_pluginMetaData, sizeof qt_pluginMetaData }; } \ Q_EXTERN_C Q_DECL_EXPORT QT_PREPEND_NAMESPACE(QObject) *qt_plugin_instance() \ Q_PLUGIN_INSTANCE(PLUGINCLASS) @@ -183,6 +202,7 @@ void Q_CORE_EXPORT qRegisterStaticPluginFunction(QStaticPlugin staticPlugin); #endif +#endif #define Q_EXPORT_PLUGIN(PLUGIN) \ Q_EXPORT_PLUGIN2(PLUGIN, PLUGIN) -- cgit v1.2.3 From 298ab596a1e1fb147fde6d3c0d6c859d1e045781 Mon Sep 17 00:00:00 2001 From: Christian Ehrlicher Date: Sun, 5 May 2019 10:57:38 +0200 Subject: QtSql: mark QSqlite2 plugin as obsolete Mark QSqlite2 plugin as obsolete so it can be removed with Qt6. The last sqlite2 release was 2005 so it's time to remove this plugin in Qt6. [ChangeLog][QtSql][SQlite2] Marked QSQLITE2 plugin as obsolete - it will be removed with Qt6 together with the QTDS plugin Change-Id: I9861331d4eb2b13f38b9e0e09ad9472b70e9b6e2 Reviewed-by: Lars Knoll --- src/plugins/sqldrivers/sqlite2/smain.cpp | 1 + src/plugins/sqldrivers/tds/main.cpp | 1 + src/sql/doc/src/sql-driver.qdoc | 4 ++-- 3 files changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/plugins/sqldrivers/sqlite2/smain.cpp b/src/plugins/sqldrivers/sqlite2/smain.cpp index 3a5734f8c9..7d971d6e5a 100644 --- a/src/plugins/sqldrivers/sqlite2/smain.cpp +++ b/src/plugins/sqldrivers/sqlite2/smain.cpp @@ -43,6 +43,7 @@ QT_BEGIN_NAMESPACE +// ### Qt6: remove, obsolete since 5.14 class QSQLite2DriverPlugin : public QSqlDriverPlugin { Q_OBJECT diff --git a/src/plugins/sqldrivers/tds/main.cpp b/src/plugins/sqldrivers/tds/main.cpp index 4aa1444608..18efb22ea4 100644 --- a/src/plugins/sqldrivers/tds/main.cpp +++ b/src/plugins/sqldrivers/tds/main.cpp @@ -50,6 +50,7 @@ QT_BEGIN_NAMESPACE +// ### Qt6: remove, obsolete since 4.7 class QTDSDriverPlugin : public QSqlDriverPlugin { Q_OBJECT diff --git a/src/sql/doc/src/sql-driver.qdoc b/src/sql/doc/src/sql-driver.qdoc index cccce48bb3..c6ac4d17ff 100644 --- a/src/sql/doc/src/sql-driver.qdoc +++ b/src/sql/doc/src/sql-driver.qdoc @@ -54,9 +54,9 @@ \li Open Database Connectivity (ODBC) - Microsoft SQL Server and other ODBC-compliant databases \row \li \l{#QPSQL}{QPSQL} \li PostgreSQL (versions 7.3 and above) - \row \li \l{#QSQLITE2}{QSQLITE2} \li SQLite version 2 + \row \li \l{#QSQLITE2}{QSQLITE2} \li SQLite version 2 \note obsolete since Qt 5.14 \row \li \l{#QSQLITE}{QSQLITE} \li SQLite version 3 - \row \li \l{#QTDS}{QTDS} \li Sybase Adaptive Server \note obsolete from Qt 4.7 + \row \li \l{#QTDS}{QTDS} \li Sybase Adaptive Server \note obsolete since Qt 4.7 \endtable SQLite is the in-process database system with the best test coverage -- cgit v1.2.3 From 5146582b8d0bb0cde518d57c379e5b97047c6c27 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Fri, 3 May 2019 15:57:15 +0200 Subject: Compile-fix: add private/ prefix to qnetconmonitor_p.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Build was failing without it. Change-Id: I23a6e8a359e6208f78fa9ef571b8b27f8ecb3628 Reviewed-by: Mårten Nordheim --- src/network/access/qnetworkaccessmanager_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/network/access/qnetworkaccessmanager_p.h b/src/network/access/qnetworkaccessmanager_p.h index d3a3936533..dfd747a767 100644 --- a/src/network/access/qnetworkaccessmanager_p.h +++ b/src/network/access/qnetworkaccessmanager_p.h @@ -55,7 +55,7 @@ #include "qnetworkaccessmanager.h" #include "qnetworkaccesscache_p.h" #include "qnetworkaccessbackend_p.h" -#include "qnetconmonitor_p.h" +#include "private/qnetconmonitor_p.h" #include "qnetworkrequest.h" #include "qhsts_p.h" #include "private/qobject_p.h" -- cgit v1.2.3 From aea6ff4f57135b0f2f076e86e22cb87c0a7014fe Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Tue, 7 May 2019 01:35:04 +0200 Subject: Fix the generation of docs for qobject_pointer_cast QSharedPointer uses a dummy header for qdoc; the functions were implemented and documented as qdoc comments, but not added to the dummy header. Change-Id: Iec78e3566a528631557067fbeb5606916ea74f2d Reviewed-by: Martin Smith --- src/corelib/tools/qsharedpointer.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/corelib/tools/qsharedpointer.h b/src/corelib/tools/qsharedpointer.h index 98b38b97d3..80d0618402 100644 --- a/src/corelib/tools/qsharedpointer.h +++ b/src/corelib/tools/qsharedpointer.h @@ -48,6 +48,8 @@ # include #else +#include // for std::shared_ptr + QT_BEGIN_NAMESPACE @@ -167,6 +169,10 @@ template QSharedPointer qSharedPointerConstCast(const QSha template QSharedPointer qSharedPointerConstCast(const QWeakPointer &src); template QSharedPointer qSharedPointerObjectCast(const QSharedPointer &src); template QSharedPointer qSharedPointerObjectCast(const QWeakPointer &src); +template std::shared_ptr qobject_pointer_cast(const std::shared_ptr &src); +template std::shared_ptr qobject_pointer_cast(std::shared_ptr &&src); +template std::shared_ptr qSharedPointerObjectCast(const std::shared_ptr &src); +template std::shared_ptr qSharedPointerObjectCast(std::shared_ptr &&src); template QWeakPointer qWeakPointerCast(const QWeakPointer &src); -- cgit v1.2.3 From 587bdd144b7e574e57f17167808774fa9783ee78 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 13 Nov 2018 10:26:50 +0100 Subject: Add QUrl to bootstrap set The QML language server needs to use QUrl as that is what the language server protocol uses to specify files. As we cannot implicitly cast char to QChar in the bootstrap library, we need to apply a build fix in qipaddress.cpp. Change-Id: Ifaf8421457b1f734402b5aad965ecdec764a73e8 Reviewed-by: Oswald Buddenhagen --- src/corelib/io/qipaddress.cpp | 2 +- src/tools/bootstrap/bootstrap.pro | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/corelib/io/qipaddress.cpp b/src/corelib/io/qipaddress.cpp index 039e291b43..d9f7916dd4 100644 --- a/src/corelib/io/qipaddress.cpp +++ b/src/corelib/io/qipaddress.cpp @@ -253,7 +253,7 @@ const QChar *parseIp6(IPv6Address &address, const QChar *begin, const QChar *end static inline QChar toHex(uchar c) { - return QtMiscUtils::toHexLower(c); + return QChar::fromLatin1(QtMiscUtils::toHexLower(c)); } void toString(QString &appendTo, IPv6Address address) diff --git a/src/tools/bootstrap/bootstrap.pro b/src/tools/bootstrap/bootstrap.pro index 1662e99674..708211279c 100644 --- a/src/tools/bootstrap/bootstrap.pro +++ b/src/tools/bootstrap/bootstrap.pro @@ -42,6 +42,7 @@ SOURCES += \ ../../corelib/io/qfsfileengine.cpp \ ../../corelib/io/qfsfileengine_iterator.cpp \ ../../corelib/io/qiodevice.cpp \ + ../../corelib/io/qipaddress.cpp \ ../../corelib/io/qfiledevice.cpp \ ../../corelib/io/qresource.cpp \ ../../corelib/io/qtemporarydir.cpp \ @@ -50,6 +51,9 @@ SOURCES += \ ../../corelib/io/qstandardpaths.cpp \ ../../corelib/io/qloggingcategory.cpp \ ../../corelib/io/qloggingregistry.cpp \ + ../../corelib/io/qurl.cpp \ + ../../corelib/io/qurlidna.cpp \ + ../../corelib/io/qurlrecode.cpp \ ../../corelib/kernel/qcoreapplication.cpp \ ../../corelib/kernel/qcoreglobaldata.cpp \ ../../corelib/kernel/qmetatype.cpp \ -- cgit v1.2.3 From d510e1e7f919e01a3b875ff5a575b818e5ee03e8 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Wed, 10 Oct 2018 08:51:04 +0200 Subject: Add swapItemsAt() to QVector This closes one compatibility gap with QList, to make it easier to replace QList with QVector in Qt6. Change-Id: I5655bc4cd2150a6f09a1ed68c0742f3b42ca47e4 Reviewed-by: Simon Hausmann --- src/corelib/tools/qvector.h | 7 +++++++ src/corelib/tools/qvector.qdoc | 10 ++++++++++ 2 files changed, 17 insertions(+) (limited to 'src') diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h index 4e148c9c55..b763d6e7e2 100644 --- a/src/corelib/tools/qvector.h +++ b/src/corelib/tools/qvector.h @@ -251,6 +251,13 @@ public: T value(int i) const; T value(int i, const T &defaultValue) const; + void swapItemsAt(int i, int j) { + Q_ASSERT_X(i >= 0 && i < size() && j >= 0 && j < size(), + "QVector::swap", "index out of range"); + detach(); + qSwap(d->begin()[i], d->begin()[j]); + } + // STL compatibility typedef T value_type; typedef value_type* pointer; diff --git a/src/corelib/tools/qvector.qdoc b/src/corelib/tools/qvector.qdoc index cb47d36356..c1b5054f93 100644 --- a/src/corelib/tools/qvector.qdoc +++ b/src/corelib/tools/qvector.qdoc @@ -288,6 +288,16 @@ never fails. */ +/*! \fn template void QVector::swapItemsAt(int i, int j) + \since 5.14 + + Exchange the item at index position \a i with the item at index + position \a j. This function assumes that both \a i and \a j are + at least 0 but less than size(). To avoid failure, test that both + \a i and \a j are at least 0 and less than size(). +*/ + + /*! \fn template bool QVector::operator==(const QVector &other) const Returns \c true if \a other is equal to this vector; otherwise -- cgit v1.2.3 From 92f984273262531f909ede17a324f546fe502b5c Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Mon, 6 May 2019 14:00:53 +0200 Subject: Deprecate conversion functions between QList and QSet Users should use range constructors instead to do the conversion. Keep conversion methods between QList and QVector as these will turn into a no-op in Qt 6, whereas forcing people to use range constructors would lead to deep copies of the data. Change-Id: Id9fc9e4d007044e019826da523e8418857c91283 Reviewed-by: Simon Hausmann --- src/corelib/statemachine/qstatemachine.cpp | 13 +++++++------ src/corelib/tools/qlist.h | 8 +++++--- src/corelib/tools/qset.h | 13 +++++++++---- src/corelib/tools/qvector.h | 3 +-- src/gui/opengl/qopengl.cpp | 2 +- src/gui/text/qtextodfwriter.cpp | 2 +- src/network/ssl/qsslsocket_openssl_symbols.cpp | 2 +- src/tools/uic/cpp/cppwriteinitialization.cpp | 2 +- src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp | 2 +- src/widgets/graphicsview/qgraphicsscene.cpp | 10 +++++----- src/widgets/graphicsview/qsimplex_p.cpp | 2 +- src/widgets/itemviews/qtableview.cpp | 4 ++-- src/widgets/kernel/qapplication.cpp | 2 +- src/widgets/kernel/qgesturemanager.cpp | 2 +- 14 files changed, 37 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index ee3f7be279..be48dbc92f 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -370,10 +370,11 @@ static QList getEffectiveTargetStates(QAbstractTransition *tra QList historyConfiguration = QHistoryStatePrivate::get(historyState)->configuration; if (!historyConfiguration.isEmpty()) { // There is a saved history, so apply that. - targets.unite(historyConfiguration.toSet()); + targets.unite(QSet(historyConfiguration.constBegin(), historyConfiguration.constEnd())); } else if (QAbstractTransition *defaultTransition = historyState->defaultTransition()) { // No saved history, take all default transition targets. - targets.unite(defaultTransition->targetStates().toSet()); + const auto &targetStates = defaultTransition->targetStates(); + targets.unite(QSet(targetStates.constBegin(), targetStates.constEnd())); } else { // Woops, we found a history state without a default state. That's not valid! QStateMachinePrivate *m = QStateMachinePrivate::get(historyState->machine()); @@ -384,7 +385,7 @@ static QList getEffectiveTargetStates(QAbstractTransition *tra } } - targetsList = targets.toList(); + targetsList = targets.values(); cache->insert(transition, targetsList); return targetsList; } @@ -740,7 +741,7 @@ QList QStateMachinePrivate::computeExitSet(const QList statesToExit_sorted = computeExitSet_Unordered(enabledTransitions, cache).toList(); + QList statesToExit_sorted = computeExitSet_Unordered(enabledTransitions, cache).values(); std::sort(statesToExit_sorted.begin(), statesToExit_sorted.end(), stateExitLessThan); return statesToExit_sorted; } @@ -777,7 +778,7 @@ QSet QStateMachinePrivate::computeExitSet_Unordered(QAbstractTr // makes the state machine invalid. if (error == QStateMachine::NoError) setError(QStateMachine::NoCommonAncestorForTransitionError, t->sourceState()); - QList lst = pendingErrorStates.toList(); + QList lst = pendingErrorStates.values(); lst.prepend(t->sourceState()); domain = findLCCA(lst); @@ -879,7 +880,7 @@ QList QStateMachinePrivate::computeEntrySet(const QList statesToEnter_sorted = statesToEnter.toList(); + QList statesToEnter_sorted = statesToEnter.values(); std::sort(statesToEnter_sorted.begin(), statesToEnter_sorted.end(), stateEntryLessThan); return statesToEnter_sorted; } diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index 25380d45ec..04c1f12f5f 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -403,13 +403,15 @@ public: inline QList &operator<<(const QList &l) { *this += l; return *this; } + static QList fromVector(const QVector &vector); QVector toVector() const; - QSet toSet() const; - static QList fromVector(const QVector &vector); +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) + Q_DECL_DEPRECATED_X("Use QList(set.begin(), set.end()) instead.") static QList fromSet(const QSet &set); + Q_DECL_DEPRECATED_X("Use QSet(list.begin(), list.end()) instead.") + QSet toSet() const; -#if QT_VERSION < QT_VERSION_CHECK(6,0,0) Q_DECL_DEPRECATED_X("Use QList(list.begin(), list.end()) instead.") static inline QList fromStdList(const std::list &list) { QList tmp; std::copy(list.begin(), list.end(), std::back_inserter(tmp)); return tmp; } diff --git a/src/corelib/tools/qset.h b/src/corelib/tools/qset.h index 8b31de71a9..83e574bf1c 100644 --- a/src/corelib/tools/qset.h +++ b/src/corelib/tools/qset.h @@ -245,10 +245,13 @@ public: inline QSet operator-(const QSet &other) const { QSet result = *this; result -= other; return result; } - QList toList() const; - inline QList values() const { return toList(); } - + QList values() const; +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) + Q_DECL_DEPRECATED_X("Use values() instead.") + QList toList() const { return values(); } + Q_DECL_DEPRECATED_X("Use QSet(list.begin(), list.end()) instead.") static QSet fromList(const QList &list); +#endif private: Hash q_hash; @@ -368,7 +371,7 @@ Q_INLINE_TEMPLATE bool QSet::contains(const QSet &other) const } template -Q_OUTOFLINE_TEMPLATE QList QSet::toList() const +Q_OUTOFLINE_TEMPLATE QList QSet::values() const { QList result; result.reserve(size()); @@ -380,6 +383,7 @@ Q_OUTOFLINE_TEMPLATE QList QSet::toList() const return result; } +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) template Q_OUTOFLINE_TEMPLATE QSet QList::toSet() const { @@ -401,6 +405,7 @@ QList QList::fromSet(const QSet &set) { return set.toList(); } +#endif Q_DECLARE_SEQUENTIAL_ITERATOR(Set) diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h index b763d6e7e2..492afeac75 100644 --- a/src/corelib/tools/qvector.h +++ b/src/corelib/tools/qvector.h @@ -297,9 +297,8 @@ public: inline QVector &operator<<(T &&t) { append(std::move(t)); return *this; } - QList toList() const; - static QVector fromList(const QList &list); + QList toList() const; #if QT_VERSION < QT_VERSION_CHECK(6,0,0) Q_DECL_DEPRECATED_X("Use QVector(vector.begin(), vector.end()) instead.") diff --git a/src/gui/opengl/qopengl.cpp b/src/gui/opengl/qopengl.cpp index 6b701fe52b..667d16317f 100644 --- a/src/gui/opengl/qopengl.cpp +++ b/src/gui/opengl/qopengl.cpp @@ -80,7 +80,7 @@ QOpenGLExtensionMatcher::QOpenGLExtensionMatcher() if (extensionStr) { QByteArray ba(extensionStr); QList extensions = ba.split(' '); - m_extensions = extensions.toSet(); + m_extensions = QSet(extensions.constBegin(), extensions.constEnd()); } else { #ifdef QT_OPENGL_3 // clear error state diff --git a/src/gui/text/qtextodfwriter.cpp b/src/gui/text/qtextodfwriter.cpp index a62e7e425a..8eaad403d0 100644 --- a/src/gui/text/qtextodfwriter.cpp +++ b/src/gui/text/qtextodfwriter.cpp @@ -1007,7 +1007,7 @@ bool QTextOdfWriter::writeAll() // add objects for lists, frames and tables const QVector allFormats = m_document->allFormats(); - const QList copy = formats.toList(); + const QList copy = formats.values(); for (auto index : copy) { QTextObject *object = m_document->objectForFormat(allFormats[index]); if (object) { diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp index e04d45c10c..6f935a02e4 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols.cpp +++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp @@ -693,7 +693,7 @@ static QStringList libraryPathList() // discover paths of already loaded libraries QSet loadedPaths; dl_iterate_phdr(dlIterateCallback, &loadedPaths); - paths.append(loadedPaths.toList()); + paths.append(loadedPaths.values()); #endif return paths; diff --git a/src/tools/uic/cpp/cppwriteinitialization.cpp b/src/tools/uic/cpp/cppwriteinitialization.cpp index a1ff26ba04..2510fd0edc 100644 --- a/src/tools/uic/cpp/cppwriteinitialization.cpp +++ b/src/tools/uic/cpp/cppwriteinitialization.cpp @@ -2607,7 +2607,7 @@ static void generateMultiDirectiveBegin(QTextStream &outputStream, const QSet getVariables(const QList &constraints) for (auto it = c->variables.cbegin(), end = c->variables.cend(); it != end; ++it) variableSet.insert(static_cast(it.key())); } - return variableSet.toList(); + return variableSet.values(); } /*! diff --git a/src/widgets/graphicsview/qgraphicsscene.cpp b/src/widgets/graphicsview/qgraphicsscene.cpp index 3897823e98..e5bd65d61e 100644 --- a/src/widgets/graphicsview/qgraphicsscene.cpp +++ b/src/widgets/graphicsview/qgraphicsscene.cpp @@ -6352,7 +6352,7 @@ void QGraphicsScenePrivate::gestureEventHandler(QGestureEvent *event) << "delivering override to" << item.data() << gestures; // send gesture override - QGestureEvent ev(gestures.toList()); + QGestureEvent ev(gestures.values()); ev.t = QEvent::GestureOverride; ev.setWidget(event->widget()); // mark event and individual gestures as ignored @@ -6442,7 +6442,7 @@ void QGraphicsScenePrivate::gestureEventHandler(QGestureEvent *event) DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:" << "delivering to" << receiver.data() << gestures; - QGestureEvent ev(gestures.toList()); + QGestureEvent ev(gestures.values()); ev.setWidget(event->widget()); sendEvent(receiver.data(), &ev); QSet ignoredGestures; @@ -6473,7 +6473,7 @@ void QGraphicsScenePrivate::gestureEventHandler(QGestureEvent *event) // look for new potential targets for gestures that were ignored // and should be propagated. - QSet targetsSet = cachedTargetItems.toSet(); + QSet targetsSet(cachedTargetItems.constBegin(), cachedTargetItems.constEnd()); if (receiver) { // first if the gesture should be propagated to parents only @@ -6505,7 +6505,7 @@ void QGraphicsScenePrivate::gestureEventHandler(QGestureEvent *event) gestureTargetsAtHotSpots(ignoredGestures, Qt::ReceivePartialGestures, &cachedItemGestures, &targetsSet, 0, 0); - cachedTargetItems = targetsSet.toList(); + cachedTargetItems = targetsSet.values(); std::sort(cachedTargetItems.begin(), cachedTargetItems.end(), qt_closestItemFirst); DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:" << "new targets:" << cachedTargetItems; @@ -6583,7 +6583,7 @@ void QGraphicsScenePrivate::cancelGesturesForChildren(QGesture *original) } Q_ASSERT(target); - const QList list = gestures.toList(); + const QList list = gestures.values(); QGestureEvent ev(list); sendEvent(target, &ev); diff --git a/src/widgets/graphicsview/qsimplex_p.cpp b/src/widgets/graphicsview/qsimplex_p.cpp index e6ffa856f1..e18f1fa4c4 100644 --- a/src/widgets/graphicsview/qsimplex_p.cpp +++ b/src/widgets/graphicsview/qsimplex_p.cpp @@ -164,7 +164,7 @@ bool QSimplex::setConstraints(const QList &newConstraints) for (auto it = v.cbegin(), end = v.cend(); it != end; ++it) variablesSet.insert(it.key()); } - variables = variablesSet.toList(); + variables = variablesSet.values(); // Set Variables reverse mapping // We also need to be able to find the index for a given variable, to do that diff --git a/src/widgets/itemviews/qtableview.cpp b/src/widgets/itemviews/qtableview.cpp index 9e9aa63b53..0e03ff2a97 100644 --- a/src/widgets/itemviews/qtableview.cpp +++ b/src/widgets/itemviews/qtableview.cpp @@ -191,7 +191,7 @@ QList QSpanCollection::spansInRect(int x, int y, int w, break; --it_y; } - return list.toList(); + return list.values(); } #undef DEBUG_SPAN_UPDATE @@ -875,7 +875,7 @@ void QTableViewPrivate::drawAndClipSpans(const QRegion &area, QPainter *painter, for(int y = firstVisualRow; y <= lastVisualRow; y++) set.insert(spans.spanAt(x,y)); set.remove(0); - visibleSpans = set.toList(); + visibleSpans = set.values(); } for (QSpanCollection::Span *span : qAsConst(visibleSpans)) { diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index c1c4014c6b..ca48a9e145 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -1721,7 +1721,7 @@ QWidgetList QApplication::topLevelWidgets() QWidgetList QApplication::allWidgets() { if (QWidgetPrivate::allWidgets) - return QWidgetPrivate::allWidgets->toList(); + return QWidgetPrivate::allWidgets->values(); return QWidgetList(); } diff --git a/src/widgets/kernel/qgesturemanager.cpp b/src/widgets/kernel/qgesturemanager.cpp index cd27c9c5be..390602205c 100644 --- a/src/widgets/kernel/qgesturemanager.cpp +++ b/src/widgets/kernel/qgesturemanager.cpp @@ -171,7 +171,7 @@ void QGestureManager::cleanupCachedGestures(QObject *target, Qt::GestureType typ while (iter != m_objectGestures.end()) { ObjectGesture objectGesture = iter.key(); if (objectGesture.gesture == type && target == objectGesture.object) { - QSet gestures = iter.value().toSet(); + QSet gestures = QSet(iter.value().constBegin(), iter.value().constEnd()); for (QHash >::iterator it = m_obsoleteGestures.begin(), e = m_obsoleteGestures.end(); it != e; ++it) { it.value() -= gestures; -- cgit v1.2.3 From 06b8644953fc526707b5fe24c8ef08f4829ba1c6 Mon Sep 17 00:00:00 2001 From: Dmitry Kazakov Date: Thu, 6 Dec 2018 16:16:27 +0300 Subject: Fix notification of QDockWidget when it gets undocked Before the patch the notification was emitted only when the docker was attached to the panel or changed a position on it. It looks like the old behavior was documented in a unittest, so this patch might actually be a "behavior change". Change-Id: Id3ffbd2018a8e68844d174328dd1c4ceb7fa01d3 Reviewed-by: Richard Moe Gustavsen --- src/widgets/widgets/qdockwidget.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/widgets/widgets/qdockwidget.cpp b/src/widgets/widgets/qdockwidget.cpp index 4041c730b8..f98e0e44db 100644 --- a/src/widgets/widgets/qdockwidget.cpp +++ b/src/widgets/widgets/qdockwidget.cpp @@ -1182,6 +1182,8 @@ void QDockWidgetPrivate::setWindowState(bool floating, bool unplug, const QRect QMainWindowLayout *mwlayout = qt_mainwindow_layout_from_dock(q); if (mwlayout) emit q->dockLocationChanged(mwlayout->dockWidgetArea(q)); + } else { + emit q->dockLocationChanged(Qt::NoDockWidgetArea); } } -- cgit v1.2.3 From 2841d5bf64d6228cdb5e42cdd1d4e2e8035217fa Mon Sep 17 00:00:00 2001 From: Dmitry Kazakov Date: Tue, 4 Dec 2018 20:11:34 +0300 Subject: Return QScreen's HMONITOR handle via QPlatformNativeInterface It is needed to be able to fetch extra information about the display via DXGI interface. Change-Id: Id83982eb07ade157719e430d0abcc2613409a343 Reviewed-by: Friedemann Kleint --- .../platforms/windows/qwindowsnativeinterface.cpp | 16 ++++++++++++++++ src/plugins/platforms/windows/qwindowsnativeinterface.h | 1 + src/plugins/platforms/windows/qwindowsscreen.cpp | 5 +++++ src/plugins/platforms/windows/qwindowsscreen.h | 2 ++ 4 files changed, 24 insertions(+) (limited to 'src') diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp index b8ab7f8779..e581b30ced 100644 --- a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp +++ b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp @@ -40,6 +40,7 @@ #include "qwindowsnativeinterface.h" #include "qwindowsclipboard.h" #include "qwindowswindow.h" +#include "qwindowsscreen.h" #include "qwindowscontext.h" #include "qwindowscursor.h" #include "qwindowsopenglcontext.h" @@ -124,6 +125,21 @@ void *QWindowsNativeInterface::nativeResourceForWindow(const QByteArray &resourc return nullptr; } +void *QWindowsNativeInterface::nativeResourceForScreen(const QByteArray &resource, QScreen *screen) +{ + if (!screen || !screen->handle()) { + qWarning("%s: '%s' requested for null screen or screen without handle.", __FUNCTION__, resource.constData()); + return nullptr; + } + QWindowsScreen *bs = static_cast(screen->handle()); + int type = resourceType(resource); + if (type == HandleType) + return bs->handle(); + + qWarning("%s: Invalid key '%s' requested.", __FUNCTION__, resource.constData()); + return nullptr; +} + #ifndef QT_NO_CURSOR void *QWindowsNativeInterface::nativeResourceForCursor(const QByteArray &resource, const QCursor &cursor) { diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.h b/src/plugins/platforms/windows/qwindowsnativeinterface.h index e6f8aae8fb..ce395dc5a4 100644 --- a/src/plugins/platforms/windows/qwindowsnativeinterface.h +++ b/src/plugins/platforms/windows/qwindowsnativeinterface.h @@ -74,6 +74,7 @@ public: void *nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context) override; #endif void *nativeResourceForWindow(const QByteArray &resource, QWindow *window) override; + void *nativeResourceForScreen(const QByteArray &resource, QScreen *screen) override; #ifndef QT_NO_CURSOR void *nativeResourceForCursor(const QByteArray &resource, const QCursor &cursor) override; #endif diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp index 0520f88935..b70b0bbe31 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.cpp +++ b/src/plugins/platforms/windows/qwindowsscreen.cpp @@ -321,6 +321,11 @@ void QWindowsScreen::handleChanges(const QWindowsScreenData &newData) } } +HMONITOR QWindowsScreen::handle() const +{ + return m_data.hMonitor; +} + QRect QWindowsScreen::virtualGeometry(const QPlatformScreen *screen) // cf QScreen::virtualGeometry() { QRect result; diff --git a/src/plugins/platforms/windows/qwindowsscreen.h b/src/plugins/platforms/windows/qwindowsscreen.h index 824bcb1ad6..33c9effa2a 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.h +++ b/src/plugins/platforms/windows/qwindowsscreen.h @@ -104,6 +104,8 @@ public: inline void handleChanges(const QWindowsScreenData &newData); + HMONITOR handle() const; + #ifndef QT_NO_CURSOR QPlatformCursor *cursor() const override { return m_cursor.data(); } const CursorPtr &cursorPtr() const { return m_cursor; } -- cgit v1.2.3 From add4b56b21bae5cef222ee23e00707664ca50e7f Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Tue, 7 May 2019 14:57:56 +0200 Subject: Add warning suppression for icc when comparing floating-point values The new implementations of qIsNull use naked floating point comparisons to 0 and suppress the warnings for clang and gcc; so add suppression also for icc. Fixes: QTBUG-75644 Change-Id: I59aa1443666a542f38197f2b124503cc562708cb Reviewed-by: Qt CI Bot Reviewed-by: Giuseppe D'Angelo --- src/corelib/global/qglobal.h | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index a1f191516a..0a0c434a07 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -905,6 +905,7 @@ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR static inline Q_DECL_UNUSED bool qFuzzyIsNul QT_WARNING_PUSH QT_WARNING_DISABLE_CLANG("-Wfloat-equal") QT_WARNING_DISABLE_GCC("-Wfloat-equal") +QT_WARNING_DISABLE_INTEL(1572) Q_REQUIRED_RESULT Q_DECL_CONSTEXPR static inline Q_DECL_UNUSED bool qIsNull(double d) noexcept { -- cgit v1.2.3 From ce1830fd21751e90060d77ba529bcd8904555587 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Wed, 24 Apr 2019 11:26:58 +0200 Subject: Migrate Windows system libs to external dependencies Started-by: Oswald Buddenhagen Change-Id: I211ce3252b836894aeeac1c85eb316d9596bca57 Reviewed-by: Oliver Wolff --- src/corelib/configure.json | 64 ++++++++++++++++++++++ src/corelib/corelib.pro | 6 +- src/corelib/io/io.pri | 3 +- src/dbus/dbus.pro | 10 ++-- src/network/socket/socket.pri | 2 +- .../fontdatabases/windows/windows.pri | 4 +- src/platformsupport/fontdatabases/winrt/winrt.pri | 4 +- src/plugins/bearer/nla/nla.pro | 2 +- src/plugins/platforms/direct2d/direct2d.pro | 4 +- .../windows/uiautomation/uiautomation.pri | 3 +- src/plugins/platforms/windows/windows.pri | 16 ++++-- src/plugins/platforms/windows/windows.pro | 3 +- src/plugins/platforms/winrt/winrt.pro | 3 +- src/plugins/printsupport/windows/windows.pro | 3 +- src/plugins/styles/windowsvista/windowsvista.pro | 2 +- src/printsupport/kernel/kernel.pri | 5 +- src/widgets/kernel/win.pri | 5 +- src/winmain/winmain.pro | 2 +- 18 files changed, 107 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/corelib/configure.json b/src/corelib/configure.json index a6091d4825..d24867ffa0 100644 --- a/src/corelib/configure.json +++ b/src/corelib/configure.json @@ -235,6 +235,66 @@ "sources": [ "-lslog2" ] + }, + "advapi32": { + "label": "advapi32", + "sources": [ + "-ladvapi32" + ] + }, + "gdi32": { + "label": "gdi32", + "sources": [ + "-lgdi32" + ] + }, + "kernel32": { + "label": "kernel32", + "sources": [ + "-lkernel32" + ] + }, + "netapi32": { + "label": "netapi32", + "sources": [ + "-lnetapi32" + ] + }, + "ole32": { + "label": "ole32", + "sources": [ + "-lole32" + ] + }, + "shell32": { + "label": "shell32", + "sources": [ + "-lshell32" + ] + }, + "uuid": { + "label": "uuid", + "sources": [ + "-luuid" + ] + }, + "user32": { + "label": "user32", + "sources": [ + "-luser32" + ] + }, + "winmm": { + "label": "winmm", + "sources": [ + "-lwinmm" + ] + }, + "ws2_32": { + "label": "ws2_32", + "sources": [ + "-lws2_32" + ] } }, @@ -1017,6 +1077,10 @@ If enabled, a binary dump of the Public Suffix List (http://www.publicsuffix.org Mozilla License) is included. The data is then also used in QNetworkCookieJar::validateCookie.", "section": "Utilities", "output": [ "publicFeature" ] + }, + "win32_system_libs": { + "label": "Windows System Libraries", + "condition": "config.win32 && libs.advapi32 && libs.gdi32 && libs.kernel32 && libs.netapi32 && libs.ole32 && libs.shell32 && libs.uuid && libs.user32 && libs.winmm && libs.ws2_32" } }, diff --git a/src/corelib/corelib.pro b/src/corelib/corelib.pro index dc43e56836..6babbac8f5 100644 --- a/src/corelib/corelib.pro +++ b/src/corelib/corelib.pro @@ -47,10 +47,8 @@ include(mimetypes/mimetypes.pri) include(platform/platform.pri) win32 { - LIBS_PRIVATE += -lws2_32 - !winrt { - LIBS_PRIVATE += -lkernel32 -luser32 -lshell32 -luuid -lole32 -ladvapi32 -lwinmm - } + QMAKE_USE_PRIVATE += ws2_32 + !winrt: QMAKE_USE_PRIVATE += advapi32 kernel32 ole32 shell32 uuid user32 winmm } darwin { diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri index 9b6044752f..13b43ad8f7 100644 --- a/src/corelib/io/io.pri +++ b/src/corelib/io/io.pri @@ -158,7 +158,8 @@ win32 { io/qwindowspipereader.cpp \ io/qwindowspipewriter.cpp - LIBS += -lmpr -lnetapi32 -luserenv + LIBS += -lmpr -luserenv + QMAKE_USE_PRIVATE += netapi32 } else { SOURCES += \ io/qstandardpaths_winrt.cpp \ diff --git a/src/dbus/dbus.pro b/src/dbus/dbus.pro index 920a04315d..2cfd7e086c 100644 --- a/src/dbus/dbus.pro +++ b/src/dbus/dbus.pro @@ -9,11 +9,11 @@ qtConfig(dbus-linked) { } win32 { - LIBS_PRIVATE += \ - -lws2_32 \ - -ladvapi32 \ - -lnetapi32 \ - -luser32 + QMAKE_USE_PRIVATE += \ + advapi32 \ + netapi32 \ + user32 \ + ws2_32 } DEFINES += QT_NO_FOREACH diff --git a/src/network/socket/socket.pri b/src/network/socket/socket.pri index 44ff5b7b39..c3a98ea31a 100644 --- a/src/network/socket/socket.pri +++ b/src/network/socket/socket.pri @@ -58,7 +58,7 @@ unix { msvc: QMAKE_MOC_OPTIONS += -D_WINSOCK_DEPRECATED_NO_WARNINGS win32:!winrt:SOURCES += socket/qnativesocketengine_win.cpp -win32:!winrt:LIBS_PRIVATE += -ladvapi32 +win32:!winrt: QMAKE_USE_PRIVATE += advapi32 winrt { SOURCES += socket/qnativesocketengine_winrt.cpp diff --git a/src/platformsupport/fontdatabases/windows/windows.pri b/src/platformsupport/fontdatabases/windows/windows.pri index 9c529f55ea..7ddfb2c281 100644 --- a/src/platformsupport/fontdatabases/windows/windows.pri +++ b/src/platformsupport/fontdatabases/windows/windows.pri @@ -30,5 +30,5 @@ qtConfig(directwrite):qtConfig(direct2d) { DEFINES *= QT_NO_DIRECTWRITE } -LIBS += -lole32 -lgdi32 -luser32 -ladvapi32 -mingw: LIBS += -luuid +QMAKE_USE_PRIVATE += advapi32 ole32 user32 gdi32 +mingw: QMAKE_USE_PRIVATE += uuid diff --git a/src/platformsupport/fontdatabases/winrt/winrt.pri b/src/platformsupport/fontdatabases/winrt/winrt.pri index 7617df2e7a..1cd417c1fd 100644 --- a/src/platformsupport/fontdatabases/winrt/winrt.pri +++ b/src/platformsupport/fontdatabases/winrt/winrt.pri @@ -8,6 +8,4 @@ HEADERS += \ DEFINES += __WRL_NO_DEFAULT_LIB__ -LIBS += -lws2_32 - -QMAKE_USE_PRIVATE += dwrite_1 +QMAKE_USE_PRIVATE += dwrite_1 ws2_32 diff --git a/src/plugins/bearer/nla/nla.pro b/src/plugins/bearer/nla/nla.pro index 113d0667d2..76f3279d25 100644 --- a/src/plugins/bearer/nla/nla.pro +++ b/src/plugins/bearer/nla/nla.pro @@ -2,7 +2,7 @@ TARGET = qnlabearer QT = core core-private network network-private -LIBS += -lws2_32 +QMAKE_USE_PRIVATE += ws2_32 HEADERS += qnlaengine.h \ ../platformdefs_win.h \ diff --git a/src/plugins/platforms/direct2d/direct2d.pro b/src/plugins/platforms/direct2d/direct2d.pro index 9764272632..6e73bd14f9 100644 --- a/src/plugins/platforms/direct2d/direct2d.pro +++ b/src/plugins/platforms/direct2d/direct2d.pro @@ -8,8 +8,8 @@ QT += \ qtConfig(accessibility): QT += accessibility_support-private qtConfig(vulkan): QT += vulkan_support-private -LIBS += -ldwmapi -lversion -lgdi32 -QMAKE_USE_PRIVATE += dwrite_1 d2d1_1 d3d11_1 dxgi1_2 +LIBS += -ldwmapi -lversion +QMAKE_USE_PRIVATE += gdi32 dwrite_1 d2d1_1 d3d11_1 dxgi1_2 include(../windows/windows.pri) diff --git a/src/plugins/platforms/windows/uiautomation/uiautomation.pri b/src/plugins/platforms/windows/uiautomation/uiautomation.pri index e3071766d9..b79e42cdec 100644 --- a/src/plugins/platforms/windows/uiautomation/uiautomation.pri +++ b/src/plugins/platforms/windows/uiautomation/uiautomation.pri @@ -39,5 +39,4 @@ HEADERS += \ $$PWD/qwindowsuiagriditemprovider.h \ $$PWD/qwindowsuiautils.h -mingw: LIBS *= -luuid - +mingw: QMAKE_USE *= uuid diff --git a/src/plugins/platforms/windows/windows.pri b/src/plugins/platforms/windows/windows.pri index 7004d7e854..95ba961df1 100644 --- a/src/plugins/platforms/windows/windows.pri +++ b/src/plugins/platforms/windows/windows.pri @@ -1,15 +1,21 @@ # Note: OpenGL32 must precede Gdi32 as it overwrites some functions. -LIBS += -lole32 -luser32 -lwinspool -limm32 -lwinmm -loleaut32 +LIBS += -lwinspool -limm32 -loleaut32 QT_FOR_CONFIG += gui qtConfig(opengl):!qtConfig(opengles2):!qtConfig(dynamicgl): LIBS *= -lopengl32 -mingw: LIBS *= -luuid +mingw: QMAKE_USE *= uuid # For the dialog helpers: -LIBS += -lshlwapi -lshell32 -ladvapi32 -lwtsapi32 - -QMAKE_USE_PRIVATE += d3d9/nolink +LIBS += -lshlwapi -lwtsapi32 + +QMAKE_USE_PRIVATE += \ + advapi32 \ + d3d9/nolink \ + ole32 \ + shell32 \ + user32 \ + winmm DEFINES *= QT_NO_CAST_FROM_ASCII QT_NO_FOREACH diff --git a/src/plugins/platforms/windows/windows.pro b/src/plugins/platforms/windows/windows.pro index 174bc7b609..50a3bb41a9 100644 --- a/src/plugins/platforms/windows/windows.pro +++ b/src/plugins/platforms/windows/windows.pro @@ -8,7 +8,8 @@ QT += \ qtConfig(accessibility): QT += accessibility_support-private qtConfig(vulkan): QT += vulkan_support-private -LIBS += -lgdi32 -ldwmapi +LIBS += -ldwmapi +QMAKE_USE_PRIVATE += gdi32 include(windows.pri) diff --git a/src/plugins/platforms/winrt/winrt.pro b/src/plugins/platforms/winrt/winrt.pro index 43132a1a76..43dc8f074c 100644 --- a/src/plugins/platforms/winrt/winrt.pro +++ b/src/plugins/platforms/winrt/winrt.pro @@ -8,8 +8,7 @@ QT += \ DEFINES *= QT_NO_CAST_FROM_ASCII __WRL_NO_DEFAULT_LIB__ -LIBS += -lws2_32 -QMAKE_USE_PRIVATE += d3d11 +QMAKE_USE_PRIVATE += d3d11 ws2_32 SOURCES = \ main.cpp \ diff --git a/src/plugins/printsupport/windows/windows.pro b/src/plugins/printsupport/windows/windows.pro index 06694fb7fe..6ca601b2a4 100644 --- a/src/plugins/printsupport/windows/windows.pro +++ b/src/plugins/printsupport/windows/windows.pro @@ -18,7 +18,8 @@ HEADERS += \ OTHER_FILES += windows.json -LIBS += -lwinspool -lcomdlg32 -lgdi32 -luser32 +LIBS += -lwinspool -lcomdlg32 +QMAKE_USE_PRIVATE += user32 gdi32 PLUGIN_TYPE = printsupport PLUGIN_CLASS_NAME = QWindowsPrinterSupportPlugin diff --git a/src/plugins/styles/windowsvista/windowsvista.pro b/src/plugins/styles/windowsvista/windowsvista.pro index f82bcfc91b..c08db7f533 100644 --- a/src/plugins/styles/windowsvista/windowsvista.pro +++ b/src/plugins/styles/windowsvista/windowsvista.pro @@ -10,7 +10,7 @@ SOURCES += qwindowsvistastyle.cpp HEADERS += qwindowsxpstyle_p.h qwindowsxpstyle_p_p.h SOURCES += qwindowsxpstyle.cpp -LIBS_PRIVATE += -lgdi32 -luser32 +QMAKE_USE_PRIVATE += user32 gdi32 # DEFINES/LIBS needed for qwizard_win.cpp and the styles include(../../../widgets/kernel/win.pri) diff --git a/src/printsupport/kernel/kernel.pri b/src/printsupport/kernel/kernel.pri index ea7b4b9780..2ceaf152eb 100644 --- a/src/printsupport/kernel/kernel.pri +++ b/src/printsupport/kernel/kernel.pri @@ -33,7 +33,10 @@ win32 { $$PWD/qprintengine_win_p.h SOURCES += \ $$PWD/qprintengine_win.cpp - !winrt: LIBS_PRIVATE += -lwinspool -lcomdlg32 -lgdi32 -luser32 + !winrt { + LIBS_PRIVATE += -lwinspool -lcomdlg32 + QMAKE_USE_PRIVATE += user32 gdi32 + } } unix:!darwin:qtConfig(cups) { diff --git a/src/widgets/kernel/win.pri b/src/widgets/kernel/win.pri index f6877b02db..3b3170beb1 100644 --- a/src/widgets/kernel/win.pri +++ b/src/widgets/kernel/win.pri @@ -2,4 +2,7 @@ # -------------------------------------------------------------------- INCLUDEPATH += ../3rdparty/wintab -!winrt: LIBS_PRIVATE *= -lshell32 -luxtheme -ldwmapi +!winrt { + LIBS_PRIVATE *= -luxtheme -ldwmapi + QMAKE_USE_PRIVATE += shell32 +} diff --git a/src/winmain/winmain.pro b/src/winmain/winmain.pro index 9cb6ab0c59..1f54c846ec 100644 --- a/src/winmain/winmain.pro +++ b/src/winmain/winmain.pro @@ -23,7 +23,7 @@ winrt { } else { CONFIG -= qt SOURCES = qtmain_win.cpp - LIBS += -lshell32 + QMAKE_USE_PRIVATE += shell32 } load(qt_installs) -- cgit v1.2.3 From c1721cc859cc58cf04b73ba3e8db51f628684b26 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 8 May 2019 08:52:56 +0200 Subject: uic/Python: Generate empty strings as "" instead of QString() Task-number: PYSIDE-797 Change-Id: I4ce12ba01318e5ed7e88178dfd2450d9fe78c708 Reviewed-by: Cristian Maureira-Fredes --- src/tools/uic/cpp/cppwriteinitialization.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/tools/uic/cpp/cppwriteinitialization.cpp b/src/tools/uic/cpp/cppwriteinitialization.cpp index 2510fd0edc..55541db98a 100644 --- a/src/tools/uic/cpp/cppwriteinitialization.cpp +++ b/src/tools/uic/cpp/cppwriteinitialization.cpp @@ -2465,8 +2465,10 @@ void WriteInitialization::initializeTableWidget(DomWidget *w) QString WriteInitialization::trCall(const QString &str, const QString &commentHint, const QString &id) const { - if (str.isEmpty()) - return QLatin1String("QString()"); + if (str.isEmpty()) { + return language::language() == Language::Cpp + ? QLatin1String("QString()") : QLatin1String("\"\""); + } QString result; QTextStream ts(&result); -- cgit v1.2.3 From 6a58a68ae3feb27dca48ebb3274b748f784b3d12 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Tue, 7 May 2019 17:25:59 +0200 Subject: Remove 3rdparty include from QTextMarkdownImporter header file It's a private header; but to be able to use it in a test, it has to be as clean as a public header. Change-Id: I868372406e62acc24051a6523fee89bb911a61f9 Reviewed-by: Gatis Paeglis --- src/gui/text/qtextmarkdownimporter.cpp | 49 +++++++++++++++++----------------- src/gui/text/qtextmarkdownimporter_p.h | 45 +++++++++++++++---------------- 2 files changed, 47 insertions(+), 47 deletions(-) (limited to 'src') diff --git a/src/gui/text/qtextmarkdownimporter.cpp b/src/gui/text/qtextmarkdownimporter.cpp index bcb0b777d4..2c520a71c9 100644 --- a/src/gui/text/qtextmarkdownimporter.cpp +++ b/src/gui/text/qtextmarkdownimporter.cpp @@ -46,6 +46,7 @@ #include #include #include +#include "../../3rdparty/md4c/md4c.h" QT_BEGIN_NAMESPACE @@ -57,31 +58,31 @@ Q_LOGGING_CATEGORY(lcMD, "qt.text.markdown") static int CbEnterBlock(MD_BLOCKTYPE type, void *detail, void *userdata) { QTextMarkdownImporter *mdi = static_cast(userdata); - return mdi->cbEnterBlock(type, detail); + return mdi->cbEnterBlock(int(type), detail); } static int CbLeaveBlock(MD_BLOCKTYPE type, void *detail, void *userdata) { QTextMarkdownImporter *mdi = static_cast(userdata); - return mdi->cbLeaveBlock(type, detail); + return mdi->cbLeaveBlock(int(type), detail); } static int CbEnterSpan(MD_SPANTYPE type, void *detail, void *userdata) { QTextMarkdownImporter *mdi = static_cast(userdata); - return mdi->cbEnterSpan(type, detail); + return mdi->cbEnterSpan(int(type), detail); } static int CbLeaveSpan(MD_SPANTYPE type, void *detail, void *userdata) { QTextMarkdownImporter *mdi = static_cast(userdata); - return mdi->cbLeaveSpan(type, detail); + return mdi->cbLeaveSpan(int(type), detail); } static int CbText(MD_TEXTTYPE type, const MD_CHAR *text, MD_SIZE size, void *userdata) { QTextMarkdownImporter *mdi = static_cast(userdata); - return mdi->cbText(type, text, size); + return mdi->cbText(int(type), text, size); } static void CbDebugLog(const char *msg, void *userdata) @@ -131,15 +132,15 @@ void QTextMarkdownImporter::import(QTextDocument *doc, const QString &markdown) doc->clear(); qCDebug(lcMD) << "default font" << doc->defaultFont() << "mono font" << m_monoFont; QByteArray md = markdown.toUtf8(); - md_parse(md.constData(), md.size(), &callbacks, this); + md_parse(md.constData(), MD_SIZE(md.size()), &callbacks, this); delete m_cursor; m_cursor = nullptr; } -int QTextMarkdownImporter::cbEnterBlock(MD_BLOCKTYPE type, void *det) +int QTextMarkdownImporter::cbEnterBlock(int blockType, void *det) { - m_blockType = type; - switch (type) { + m_blockType = blockType; + switch (blockType) { case MD_BLOCK_P: { QTextBlockFormat blockFmt; int margin = m_doc->defaultFont().pointSize() / 2; @@ -157,10 +158,10 @@ int QTextMarkdownImporter::cbEnterBlock(MD_BLOCKTYPE type, void *det) MD_BLOCK_H_DETAIL *detail = static_cast(det); QTextBlockFormat blockFmt; QTextCharFormat charFmt; - int sizeAdjustment = 4 - detail->level; // H1 to H6: +3 to -2 + int sizeAdjustment = 4 - int(detail->level); // H1 to H6: +3 to -2 charFmt.setProperty(QTextFormat::FontSizeAdjustment, sizeAdjustment); charFmt.setFontWeight(QFont::Bold); - blockFmt.setHeadingLevel(detail->level); + blockFmt.setHeadingLevel(int(detail->level)); m_cursor->insertBlock(blockFmt, charFmt); } break; case MD_BLOCK_LI: { @@ -258,10 +259,10 @@ int QTextMarkdownImporter::cbEnterBlock(MD_BLOCKTYPE type, void *det) return 0; // no error } -int QTextMarkdownImporter::cbLeaveBlock(MD_BLOCKTYPE type, void *detail) +int QTextMarkdownImporter::cbLeaveBlock(int blockType, void *detail) { Q_UNUSED(detail) - switch (type) { + switch (blockType) { case MD_BLOCK_UL: case MD_BLOCK_OL: m_listStack.pop(); @@ -304,10 +305,10 @@ int QTextMarkdownImporter::cbLeaveBlock(MD_BLOCKTYPE type, void *detail) return 0; // no error } -int QTextMarkdownImporter::cbEnterSpan(MD_SPANTYPE type, void *det) +int QTextMarkdownImporter::cbEnterSpan(int spanType, void *det) { QTextCharFormat charFmt; - switch (type) { + switch (spanType) { case MD_SPAN_EM: charFmt.setFontItalic(true); break; @@ -316,8 +317,8 @@ int QTextMarkdownImporter::cbEnterSpan(MD_SPANTYPE type, void *det) break; case MD_SPAN_A: { MD_SPAN_A_DETAIL *detail = static_cast(det); - QString url = QString::fromLatin1(detail->href.text, detail->href.size); - QString title = QString::fromLatin1(detail->title.text, detail->title.size); + QString url = QString::fromLatin1(detail->href.text, int(detail->href.size)); + QString title = QString::fromLatin1(detail->title.text, int(detail->title.size)); charFmt.setAnchorHref(url); charFmt.setAnchorNames(QStringList(title)); charFmt.setForeground(m_palette.link()); @@ -326,8 +327,8 @@ int QTextMarkdownImporter::cbEnterSpan(MD_SPANTYPE type, void *det) case MD_SPAN_IMG: { m_imageSpan = true; MD_SPAN_IMG_DETAIL *detail = static_cast(det); - QString src = QString::fromUtf8(detail->src.text, detail->src.size); - QString title = QString::fromUtf8(detail->title.text, detail->title.size); + QString src = QString::fromUtf8(detail->src.text, int(detail->src.size)); + QString title = QString::fromUtf8(detail->title.text, int(detail->title.size)); QTextImageFormat img; img.setName(src); qCDebug(lcMD) << "image" << src << "title" << title << "relative to" << m_doc->baseUrl(); @@ -346,7 +347,7 @@ int QTextMarkdownImporter::cbEnterSpan(MD_SPANTYPE type, void *det) return 0; // no error } -int QTextMarkdownImporter::cbLeaveSpan(MD_SPANTYPE type, void *detail) +int QTextMarkdownImporter::cbLeaveSpan(int spanType, void *detail) { Q_UNUSED(detail) QTextCharFormat charFmt; @@ -356,20 +357,20 @@ int QTextMarkdownImporter::cbLeaveSpan(MD_SPANTYPE type, void *detail) charFmt = m_spanFormatStack.top(); } m_cursor->setCharFormat(charFmt); - if (type == MD_SPAN_IMG) + if (spanType == int(MD_SPAN_IMG)) m_imageSpan = false; return 0; // no error } -int QTextMarkdownImporter::cbText(MD_TEXTTYPE type, const MD_CHAR *text, MD_SIZE size) +int QTextMarkdownImporter::cbText(int textType, const char *text, unsigned size) { if (m_imageSpan) return 0; // it's the alt-text static const QRegularExpression openingBracket(QStringLiteral("<[a-zA-Z]")); static const QRegularExpression closingBracket(QStringLiteral("(/>| #include -#include "../../3rdparty/md4c/md4c.h" - QT_BEGIN_NAMESPACE class QTextCursor; @@ -69,22 +67,23 @@ class Q_GUI_EXPORT QTextMarkdownImporter { public: enum Feature { - FeatureCollapseWhitespace = MD_FLAG_COLLAPSEWHITESPACE, - FeaturePermissiveATXHeaders = MD_FLAG_PERMISSIVEATXHEADERS, - FeaturePermissiveURLAutoLinks = MD_FLAG_PERMISSIVEURLAUTOLINKS, - FeaturePermissiveMailAutoLinks = MD_FLAG_PERMISSIVEEMAILAUTOLINKS, - FeatureNoIndentedCodeBlocks = MD_FLAG_NOINDENTEDCODEBLOCKS, - FeatureNoHTMLBlocks = MD_FLAG_NOHTMLBLOCKS, - FeatureNoHTMLSpans = MD_FLAG_NOHTMLSPANS, - FeatureTables = MD_FLAG_TABLES, - FeatureStrikeThrough = MD_FLAG_STRIKETHROUGH, - FeaturePermissiveWWWAutoLinks = MD_FLAG_PERMISSIVEWWWAUTOLINKS, - FeatureTasklists = MD_FLAG_TASKLISTS, + // Must be kept in sync with MD_FLAG_* in md4c.h + FeatureCollapseWhitespace = 0x0001, // MD_FLAG_COLLAPSEWHITESPACE + FeaturePermissiveATXHeaders = 0x0002, // MD_FLAG_PERMISSIVEATXHEADERS + FeaturePermissiveURLAutoLinks = 0x0004, // MD_FLAG_PERMISSIVEURLAUTOLINKS + FeaturePermissiveMailAutoLinks = 0x0008, // MD_FLAG_PERMISSIVEEMAILAUTOLINKS + FeatureNoIndentedCodeBlocks = 0x0010, // MD_FLAG_NOINDENTEDCODEBLOCKS + FeatureNoHTMLBlocks = 0x0020, // MD_FLAG_NOHTMLBLOCKS + FeatureNoHTMLSpans = 0x0040, // MD_FLAG_NOHTMLSPANS + FeatureTables = 0x0100, // MD_FLAG_TABLES + FeatureStrikeThrough = 0x0200, // MD_FLAG_STRIKETHROUGH + FeaturePermissiveWWWAutoLinks = 0x0400, // MD_FLAG_PERMISSIVEWWWAUTOLINKS + FeatureTasklists = 0x0800, // MD_FLAG_TASKLISTS // composite flags - FeaturePermissiveAutoLinks = MD_FLAG_PERMISSIVEAUTOLINKS, - FeatureNoHTML = MD_FLAG_NOHTML, - DialectCommonMark = MD_DIALECT_COMMONMARK, - DialectGitHub = MD_DIALECT_GITHUB + FeaturePermissiveAutoLinks = FeaturePermissiveMailAutoLinks | FeaturePermissiveURLAutoLinks | FeaturePermissiveWWWAutoLinks, // MD_FLAG_PERMISSIVEAUTOLINKS + FeatureNoHTML = FeatureNoHTMLBlocks | FeatureNoHTMLSpans, // MD_FLAG_NOHTML + DialectCommonMark = 0, // MD_DIALECT_COMMONMARK + DialectGitHub = FeaturePermissiveAutoLinks | FeatureTables | FeatureStrikeThrough | FeatureTasklists // MD_DIALECT_GITHUB }; Q_DECLARE_FLAGS(Features, Feature) @@ -94,11 +93,11 @@ public: public: // MD4C callbacks - int cbEnterBlock(MD_BLOCKTYPE type, void* detail); - int cbLeaveBlock(MD_BLOCKTYPE type, void* detail); - int cbEnterSpan(MD_SPANTYPE type, void* detail); - int cbLeaveSpan(MD_SPANTYPE type, void* detail); - int cbText(MD_TEXTTYPE type, const MD_CHAR* text, MD_SIZE size); + int cbEnterBlock(int blockType, void* detail); + int cbLeaveBlock(int blockType, void* detail); + int cbEnterSpan(int spanType, void* detail); + int cbLeaveSpan(int spanType, void* detail); + int cbText(int textType, const char* text, unsigned size); private: QTextDocument *m_doc = nullptr; @@ -115,7 +114,7 @@ private: int m_tableRowCount = 0; int m_tableCol = -1; // because relative cell movements (e.g. m_cursor->movePosition(QTextCursor::NextCell)) don't work Features m_features; - MD_BLOCKTYPE m_blockType = MD_BLOCK_DOC; + int m_blockType = 0; bool m_emptyList = false; // true when the last thing we did was insertList bool m_imageSpan = false; }; -- cgit v1.2.3 From 040dd7fe26bfa34aae19e2db698ff0d69346ed56 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Fri, 26 Apr 2019 07:40:34 +0200 Subject: Markdown: fix several issues with lists and continuations Importer fixes: - the first list item after a heading doesn't keep the heading font - the first text fragment after a bullet is the bullet text, not a separate paragraph - detect continuation lines and append to the list item text - detect continuation paragraphs and indent them properly - indent nested list items properly - add a test for QTextMarkdownImporter Writer fixes: - after bullet items, continuation lines and paragraphs are indented - indentation of continuations isn't affected by checkboxes - add extra newlines between list items in "loose" lists - avoid writing triple newlines - enhance the test for QTextMarkdownWriter Change-Id: Ib1dda514832f6dc0cdad177aa9a423a7038ac8c6 Reviewed-by: Gatis Paeglis --- src/gui/text/qtextmarkdownimporter.cpp | 59 +++++++++++++++--- src/gui/text/qtextmarkdownimporter_p.h | 2 + src/gui/text/qtextmarkdownwriter.cpp | 107 +++++++++++++++++++++++++++------ src/gui/text/qtextmarkdownwriter_p.h | 11 ++++ 4 files changed, 152 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/gui/text/qtextmarkdownimporter.cpp b/src/gui/text/qtextmarkdownimporter.cpp index 2c520a71c9..a65d8f270e 100644 --- a/src/gui/text/qtextmarkdownimporter.cpp +++ b/src/gui/text/qtextmarkdownimporter.cpp @@ -52,6 +52,9 @@ QT_BEGIN_NAMESPACE Q_LOGGING_CATEGORY(lcMD, "qt.text.markdown") +static const QChar Newline = QLatin1Char('\n'); +static const QChar Space = QLatin1Char(' '); + // -------------------------------------------------------- // MD4C callback function wrappers @@ -141,18 +144,33 @@ int QTextMarkdownImporter::cbEnterBlock(int blockType, void *det) { m_blockType = blockType; switch (blockType) { - case MD_BLOCK_P: { - QTextBlockFormat blockFmt; - int margin = m_doc->defaultFont().pointSize() / 2; - blockFmt.setTopMargin(margin); - blockFmt.setBottomMargin(margin); - m_cursor->insertBlock(blockFmt, QTextCharFormat()); - } break; + case MD_BLOCK_P: + if (m_listStack.isEmpty()) { + QTextBlockFormat blockFmt; + int margin = m_doc->defaultFont().pointSize() / 2; + blockFmt.setTopMargin(margin); + blockFmt.setBottomMargin(margin); + m_cursor->insertBlock(blockFmt, QTextCharFormat()); + qCDebug(lcMD, "P"); + } else { + if (m_emptyListItem) { + qCDebug(lcMD, "LI text block at level %d -> BlockIndent %d", + m_listStack.count(), m_cursor->blockFormat().indent()); + m_emptyListItem = false; + } else { + qCDebug(lcMD, "P inside LI at level %d", m_listStack.count()); + QTextBlockFormat blockFmt; + blockFmt.setIndent(m_listStack.count()); + m_cursor->insertBlock(blockFmt, QTextCharFormat()); + } + } + break; case MD_BLOCK_CODE: { QTextBlockFormat blockFmt; QTextCharFormat charFmt; charFmt.setFont(m_monoFont); m_cursor->insertBlock(blockFmt, charFmt); + qCDebug(lcMD, "CODE"); } break; case MD_BLOCK_H: { MD_BLOCK_H_DETAIL *detail = static_cast(det); @@ -163,6 +181,7 @@ int QTextMarkdownImporter::cbEnterBlock(int blockType, void *det) charFmt.setFontWeight(QFont::Bold); blockFmt.setHeadingLevel(int(detail->level)); m_cursor->insertBlock(blockFmt, charFmt); + qCDebug(lcMD, "H%d", detail->level); } break; case MD_BLOCK_LI: { MD_BLOCK_LI_DETAIL *detail = static_cast(det); @@ -176,7 +195,10 @@ int QTextMarkdownImporter::cbEnterBlock(int blockType, void *det) list->add(m_cursor->block()); } m_cursor->setBlockFormat(bfmt); + qCDebug(lcMD) << (m_emptyList ? "LI (first in list)" : "LI"); m_emptyList = false; // Avoid insertBlock for the first item (because insertList already did that) + m_listItem = true; + m_emptyListItem = true; } break; case MD_BLOCK_UL: { MD_BLOCK_UL_DETAIL *detail = static_cast(det); @@ -193,6 +215,7 @@ int QTextMarkdownImporter::cbEnterBlock(int blockType, void *det) fmt.setStyle(QTextListFormat::ListDisc); break; } + qCDebug(lcMD, "UL %c level %d", detail->mark, m_listStack.count()); m_listStack.push(m_cursor->insertList(fmt)); m_emptyList = true; } break; @@ -202,6 +225,7 @@ int QTextMarkdownImporter::cbEnterBlock(int blockType, void *det) fmt.setIndent(m_listStack.count() + 1); fmt.setNumberSuffix(QChar::fromLatin1(detail->mark_delimiter)); fmt.setStyle(QTextListFormat::ListDecimal); + qCDebug(lcMD, "OL xx%d level %d", detail->mark_delimiter, m_listStack.count()); m_listStack.push(m_cursor->insertList(fmt)); m_emptyList = true; } break; @@ -265,6 +289,7 @@ int QTextMarkdownImporter::cbLeaveBlock(int blockType, void *detail) switch (blockType) { case MD_BLOCK_UL: case MD_BLOCK_OL: + qCDebug(lcMD, "list at level %d ended", m_listStack.count()); m_listStack.pop(); break; case MD_BLOCK_TR: { @@ -299,6 +324,14 @@ int QTextMarkdownImporter::cbLeaveBlock(int blockType, void *detail) m_currentTable = nullptr; m_cursor->movePosition(QTextCursor::End); break; + case MD_BLOCK_LI: + qCDebug(lcMD, "LI at level %d ended", m_listStack.count()); + m_listItem = false; + break; + case MD_BLOCK_CODE: + case MD_BLOCK_H: + m_cursor->setCharFormat(QTextCharFormat()); + break; default: break; } @@ -381,10 +414,10 @@ int QTextMarkdownImporter::cbText(int textType, const char *text, unsigned size) s = QString(QChar(0xFFFD)); // CommonMark-required replacement for null break; case MD_TEXT_BR: - s = QLatin1String("\n"); + s = QString(Newline); break; case MD_TEXT_SOFTBR: - s = QLatin1String(" "); + s = QString(Space); break; case MD_TEXT_CODE: // We'll see MD_SPAN_CODE too, which will set the char format, and that's enough. @@ -431,6 +464,14 @@ int QTextMarkdownImporter::cbText(int textType, const char *text, unsigned size) if (!s.isEmpty()) m_cursor->insertText(s); + if (m_cursor->currentList()) { + // The list item will indent the list item's text, so we don't need indentation on the block. + QTextBlockFormat blockFmt = m_cursor->blockFormat(); + blockFmt.setIndent(0); + m_cursor->setBlockFormat(blockFmt); + } + qCDebug(lcMD) << textType << "in block" << m_blockType << s << "in list?" << m_cursor->currentList() + << "indent" << m_cursor->blockFormat().indent(); return 0; // no error } diff --git a/src/gui/text/qtextmarkdownimporter_p.h b/src/gui/text/qtextmarkdownimporter_p.h index dee24a8e22..8ab119d051 100644 --- a/src/gui/text/qtextmarkdownimporter_p.h +++ b/src/gui/text/qtextmarkdownimporter_p.h @@ -116,6 +116,8 @@ private: Features m_features; int m_blockType = 0; bool m_emptyList = false; // true when the last thing we did was insertList + bool m_listItem = false; + bool m_emptyListItem = false; bool m_imageSpan = false; }; diff --git a/src/gui/text/qtextmarkdownwriter.cpp b/src/gui/text/qtextmarkdownwriter.cpp index 313d62bb8a..2f4c8587ad 100644 --- a/src/gui/text/qtextmarkdownwriter.cpp +++ b/src/gui/text/qtextmarkdownwriter.cpp @@ -46,12 +46,17 @@ #include "qtexttable.h" #include "qtextcursor.h" #include "qtextimagehandler_p.h" +#include "qloggingcategory.h" QT_BEGIN_NAMESPACE +Q_LOGGING_CATEGORY(lcMDW, "qt.text.markdown.writer") + static const QChar Space = QLatin1Char(' '); static const QChar Newline = QLatin1Char('\n'); +static const QChar LineBreak = QChar(0x2028); static const QChar Backtick = QLatin1Char('`'); +static const QChar Period = QLatin1Char('.'); QTextMarkdownWriter::QTextMarkdownWriter(QTextStream &stream, QTextDocument::MarkdownFeatures features) : m_stream(stream), m_features(features) @@ -93,6 +98,7 @@ void QTextMarkdownWriter::writeTable(const QAbstractTableModel &table) } m_stream << '|'<< Qt::endl; } + m_listInfo.clear(); } void QTextMarkdownWriter::writeFrame(const QTextFrame *frame) @@ -144,6 +150,7 @@ void QTextMarkdownWriter::writeFrame(const QTextFrame *frame) m_stream << Newline; } int endingCol = writeBlock(block, !table, table && tableRow == 0); + m_doubleNewlineWritten = false; if (table) { QTextTableCell cell = table->cellAt(block.position()); int paddingLen = -endingCol; @@ -158,14 +165,48 @@ void QTextMarkdownWriter::writeFrame(const QTextFrame *frame) m_stream << Newline; } else if (endingCol > 0) { m_stream << Newline << Newline; + m_doubleNewlineWritten = true; } lastWasList = block.textList(); } child = iterator.currentFrame(); ++iterator; } - if (table) + if (table) { m_stream << Newline << Newline; + m_doubleNewlineWritten = true; + } + m_listInfo.clear(); +} + +QTextMarkdownWriter::ListInfo QTextMarkdownWriter::listInfo(QTextList *list) +{ + if (!m_listInfo.contains(list)) { + // decide whether this list is loose or tight + ListInfo info; + info.loose = false; + if (list->count() > 1) { + QTextBlock first = list->item(0); + QTextBlock last = list->item(list->count() - 1); + QTextBlock next = first.next(); + while (next.isValid()) { + if (next == last) + break; + qCDebug(lcMDW) << "next block in list" << list << next.text() << "part of list?" << next.textList(); + if (!next.textList()) { + // If we find a continuation paragraph, this list is "loose" + // because it will need a blank line to separate that paragraph. + qCDebug(lcMDW) << "decided list beginning with" << first.text() << "is loose after" << next.text(); + info.loose = true; + break; + } + next = next.next(); + } + } + m_listInfo.insert(list, info); + return info; + } + return m_listInfo.value(list); } static int nearestWordWrapIndex(const QString &s, int before) @@ -211,7 +252,6 @@ static void maybeEscapeFirstChar(QString &s) int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ignoreFormat) { int ColumnLimit = 80; - int wrapIndent = 0; if (block.textList()) { // it's a list-item auto fmt = block.textList()->format(); const int listLevel = fmt.indent(); @@ -219,9 +259,18 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign QByteArray bullet = " "; bool numeric = false; switch (fmt.style()) { - case QTextListFormat::ListDisc: bullet = "-"; break; - case QTextListFormat::ListCircle: bullet = "*"; break; - case QTextListFormat::ListSquare: bullet = "+"; break; + case QTextListFormat::ListDisc: + bullet = "-"; + m_wrappedLineIndent = 2; + break; + case QTextListFormat::ListCircle: + bullet = "*"; + m_wrappedLineIndent = 2; + break; + case QTextListFormat::ListSquare: + bullet = "+"; + m_wrappedLineIndent = 2; + break; case QTextListFormat::ListStyleUndefined: break; case QTextListFormat::ListDecimal: case QTextListFormat::ListLowerAlpha: @@ -229,6 +278,7 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign case QTextListFormat::ListLowerRoman: case QTextListFormat::ListUpperRoman: numeric = true; + m_wrappedLineIndent = 4; break; } switch (block.blockFormat().marker()) { @@ -241,23 +291,36 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign default: break; } - QString prefix((listLevel - 1) * (numeric ? 4 : 2), Space); - if (numeric) - prefix += QString::number(number) + fmt.numberSuffix() + Space; - else + int indentFirstLine = (listLevel - 1) * (numeric ? 4 : 2); + m_wrappedLineIndent += indentFirstLine; + if (m_lastListIndent != listLevel && !m_doubleNewlineWritten && listInfo(block.textList()).loose) + m_stream << Newline; + m_lastListIndent = listLevel; + QString prefix(indentFirstLine, Space); + if (numeric) { + QString suffix = fmt.numberSuffix(); + if (suffix.isEmpty()) + suffix = QString(Period); + QString numberStr = QString::number(number) + suffix + Space; + if (numberStr.length() == 3) + numberStr += Space; + prefix += numberStr; + } else { prefix += QLatin1String(bullet) + Space; + } m_stream << prefix; - wrapIndent = prefix.length(); + } else if (!block.blockFormat().indent()) { + m_wrappedLineIndent = 0; } if (block.blockFormat().headingLevel()) m_stream << QByteArray(block.blockFormat().headingLevel(), '#') << ' '; - QString wrapIndentString(wrapIndent, Space); + QString wrapIndentString(m_wrappedLineIndent, Space); // It would be convenient if QTextStream had a lineCharPos() accessor, // to keep track of how many characters (not bytes) have been written on the current line, // but it doesn't. So we have to keep track with this col variable. - int col = wrapIndent; + int col = m_wrappedLineIndent; bool mono = false; bool startsOrEndsWithBacktick = false; bool bold = false; @@ -267,8 +330,16 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign QString backticks(Backtick); for (QTextBlock::Iterator frag = block.begin(); !frag.atEnd(); ++frag) { QString fragmentText = frag.fragment().text(); - while (fragmentText.endsWith(QLatin1Char('\n'))) + while (fragmentText.endsWith(Newline)) fragmentText.chop(1); + if (block.textList()) { //
  • first line
    continuation
  • + QString newlineIndent = QString(Newline) + QString(m_wrappedLineIndent, Space); + fragmentText.replace(QString(LineBreak), newlineIndent); + } else if (block.blockFormat().indent() > 0) { //
  • first line

    continuation

  • + m_stream << QString(m_wrappedLineIndent, Space); + } else { + fragmentText.replace(LineBreak, Newline); + } startsOrEndsWithBacktick |= fragmentText.startsWith(Backtick) || fragmentText.endsWith(Backtick); QTextCharFormat fmt = frag.fragment().charFormat(); if (fmt.isImageFormat()) { @@ -276,7 +347,7 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign QString s = QLatin1String("![image](") + ifmt.name() + QLatin1Char(')'); if (wrap && col + s.length() > ColumnLimit) { m_stream << Newline << wrapIndentString; - col = wrapIndent; + col = m_wrappedLineIndent; } m_stream << s; col += s.length(); @@ -285,7 +356,7 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign fmt.property(QTextFormat::AnchorHref).toString() + QLatin1Char(')'); if (wrap && col + s.length() > ColumnLimit) { m_stream << Newline << wrapIndentString; - col = wrapIndent; + col = m_wrappedLineIndent; } m_stream << s; col += s.length(); @@ -296,7 +367,7 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign if (!ignoreFormat) { if (monoFrag != mono) { if (monoFrag) - backticks = QString::fromLatin1(QByteArray(adjacentBackticksCount(fragmentText) + 1, '`')); + backticks = QString(adjacentBackticksCount(fragmentText) + 1, Backtick); markers += backticks; if (startsOrEndsWithBacktick) markers += Space; @@ -347,12 +418,12 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign m_stream << markers; col += markers.length(); } - if (col == wrapIndent) + if (col == m_wrappedLineIndent) maybeEscapeFirstChar(subfrag); m_stream << subfrag; if (breakingLine) { m_stream << Newline << wrapIndentString; - col = wrapIndent; + col = m_wrappedLineIndent; } else { col += subfrag.length(); } diff --git a/src/gui/text/qtextmarkdownwriter_p.h b/src/gui/text/qtextmarkdownwriter_p.h index 2a9388ca2d..250288bcff 100644 --- a/src/gui/text/qtextmarkdownwriter_p.h +++ b/src/gui/text/qtextmarkdownwriter_p.h @@ -70,9 +70,20 @@ public: int writeBlock(const QTextBlock &block, bool table, bool ignoreFormat); void writeFrame(const QTextFrame *frame); +private: + struct ListInfo { + bool loose; + }; + + ListInfo listInfo(QTextList *list); + private: QTextStream &m_stream; QTextDocument::MarkdownFeatures m_features; + QMap m_listInfo; + int m_wrappedLineIndent = 0; + int m_lastListIndent = 1; + bool m_doubleNewlineWritten = false; }; QT_END_NAMESPACE -- cgit v1.2.3 From 76716c4a9adc3f9aeb251d3ebe4d1d0be38b97ee Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Fri, 26 Apr 2019 08:29:07 +0200 Subject: Markdown: deal with horizontal rules (thematic breaks) Change-Id: I14d4bcfe1a6c3bd87d1328f0abb81b2138545e4e Reviewed-by: Gatis Paeglis --- src/gui/text/qtextmarkdownimporter.cpp | 3 ++- src/gui/text/qtextmarkdownwriter.cpp | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/gui/text/qtextmarkdownimporter.cpp b/src/gui/text/qtextmarkdownimporter.cpp index a65d8f270e..5cee01d932 100644 --- a/src/gui/text/qtextmarkdownimporter.cpp +++ b/src/gui/text/qtextmarkdownimporter.cpp @@ -273,7 +273,8 @@ int QTextMarkdownImporter::cbEnterBlock(int blockType, void *det) m_currentTable = m_cursor->insertTable(1, 1); // we don't know the dimensions yet break; case MD_BLOCK_HR: { - QTextBlockFormat blockFmt = m_cursor->blockFormat(); + qCDebug(lcMD, "HR"); + QTextBlockFormat blockFmt; blockFmt.setProperty(QTextFormat::BlockTrailingHorizontalRulerWidth, 1); m_cursor->insertBlock(blockFmt, QTextCharFormat()); } break; diff --git a/src/gui/text/qtextmarkdownwriter.cpp b/src/gui/text/qtextmarkdownwriter.cpp index 2f4c8587ad..0634d324b1 100644 --- a/src/gui/text/qtextmarkdownwriter.cpp +++ b/src/gui/text/qtextmarkdownwriter.cpp @@ -309,6 +309,9 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign prefix += QLatin1String(bullet) + Space; } m_stream << prefix; + } else if (block.blockFormat().hasProperty(QTextFormat::BlockTrailingHorizontalRulerWidth)) { + m_stream << "- - -\n"; // unambiguous horizontal rule, not an underline under a heading + return 0; } else if (!block.blockFormat().indent()) { m_wrappedLineIndent = 0; } -- cgit v1.2.3 From 82b26444a456d4d5ddf5f483b7766977659bee35 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Tue, 7 May 2019 17:49:32 +0200 Subject: Change QTextMarkdownWriter to pass by const pointer and QAIM - QObjects are always passed by pointer not by reference, by convention - writeTable() takes QAIM rather than QATM to make testing via QStandardItemModel possible in the future Change-Id: I5bc6b8cd9709da4fb5d57d98fa22e0cb34360944 Reviewed-by: Gatis Paeglis --- src/gui/text/qtextdocument.cpp | 2 +- src/gui/text/qtextdocumentwriter.cpp | 2 +- src/gui/text/qtextmarkdownwriter.cpp | 26 +++++++++++++------------- src/gui/text/qtextmarkdownwriter_p.h | 4 ++-- 4 files changed, 17 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp index 0a59bfb838..b5ff72e706 100644 --- a/src/gui/text/qtextdocument.cpp +++ b/src/gui/text/qtextdocument.cpp @@ -3301,7 +3301,7 @@ QString QTextDocument::toMarkdown(QTextDocument::MarkdownFeatures features) cons QString ret; QTextStream s(&ret); QTextMarkdownWriter w(s, features); - if (w.writeAll(*this)) + if (w.writeAll(this)) return ret; return QString(); } diff --git a/src/gui/text/qtextdocumentwriter.cpp b/src/gui/text/qtextdocumentwriter.cpp index c82ff873cd..193d2c0dd3 100644 --- a/src/gui/text/qtextdocumentwriter.cpp +++ b/src/gui/text/qtextdocumentwriter.cpp @@ -278,7 +278,7 @@ bool QTextDocumentWriter::write(const QTextDocument *document) } QTextStream s(d->device); QTextMarkdownWriter writer(s, QTextDocument::MarkdownDialectGitHub); - return writer.writeAll(*document); + return writer.writeAll(document); } #endif // textmarkdownwriter diff --git a/src/gui/text/qtextmarkdownwriter.cpp b/src/gui/text/qtextmarkdownwriter.cpp index 0634d324b1..a445ee7e83 100644 --- a/src/gui/text/qtextmarkdownwriter.cpp +++ b/src/gui/text/qtextmarkdownwriter.cpp @@ -63,26 +63,26 @@ QTextMarkdownWriter::QTextMarkdownWriter(QTextStream &stream, QTextDocument::Mar { } -bool QTextMarkdownWriter::writeAll(const QTextDocument &document) +bool QTextMarkdownWriter::writeAll(const QTextDocument *document) { - writeFrame(document.rootFrame()); + writeFrame(document->rootFrame()); return true; } -void QTextMarkdownWriter::writeTable(const QAbstractTableModel &table) +void QTextMarkdownWriter::writeTable(const QAbstractItemModel *table) { - QVector tableColumnWidths(table.columnCount()); - for (int col = 0; col < table.columnCount(); ++col) { - tableColumnWidths[col] = table.headerData(col, Qt::Horizontal).toString().length(); - for (int row = 0; row < table.rowCount(); ++row) { + QVector tableColumnWidths(table->columnCount()); + for (int col = 0; col < table->columnCount(); ++col) { + tableColumnWidths[col] = table->headerData(col, Qt::Horizontal).toString().length(); + for (int row = 0; row < table->rowCount(); ++row) { tableColumnWidths[col] = qMax(tableColumnWidths[col], - table.data(table.index(row, col)).toString().length()); + table->data(table->index(row, col)).toString().length()); } } // write the header and separator - for (int col = 0; col < table.columnCount(); ++col) { - QString s = table.headerData(col, Qt::Horizontal).toString(); + for (int col = 0; col < table->columnCount(); ++col) { + QString s = table->headerData(col, Qt::Horizontal).toString(); m_stream << "|" << s << QString(tableColumnWidths[col] - s.length(), Space); } m_stream << "|" << Qt::endl; @@ -91,9 +91,9 @@ void QTextMarkdownWriter::writeTable(const QAbstractTableModel &table) m_stream << '|'<< Qt::endl; // write the body - for (int row = 0; row < table.rowCount(); ++row) { - for (int col = 0; col < table.columnCount(); ++col) { - QString s = table.data(table.index(row, col)).toString(); + for (int row = 0; row < table->rowCount(); ++row) { + for (int col = 0; col < table->columnCount(); ++col) { + QString s = table->data(table->index(row, col)).toString(); m_stream << "|" << s << QString(tableColumnWidths[col] - s.length(), Space); } m_stream << '|'<< Qt::endl; diff --git a/src/gui/text/qtextmarkdownwriter_p.h b/src/gui/text/qtextmarkdownwriter_p.h index 250288bcff..4c07bad2e7 100644 --- a/src/gui/text/qtextmarkdownwriter_p.h +++ b/src/gui/text/qtextmarkdownwriter_p.h @@ -64,8 +64,8 @@ class Q_GUI_EXPORT QTextMarkdownWriter { public: QTextMarkdownWriter(QTextStream &stream, QTextDocument::MarkdownFeatures features); - bool writeAll(const QTextDocument &document); - void writeTable(const QAbstractTableModel &table); + bool writeAll(const QTextDocument *document); + void writeTable(const QAbstractItemModel *table); int writeBlock(const QTextBlock &block, bool table, bool ignoreFormat); void writeFrame(const QTextFrame *frame); -- cgit v1.2.3 From 7dd71e812542c561a00dd792d314843a81c5687c Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Fri, 26 Apr 2019 08:12:18 +0200 Subject: Markdown: blockquotes, code blocks, and generalized nesting Can now detect nested quotes and code blocks inside quotes, and can rewrite the markdown too. QTextHtmlParser sets hard-coded left and right margins, so we need to do the same to be able to read HTML and write markdown, or vice-versa, and to ensure that all views (QTextEdit, QTextBrowser, QML Text etc.) will render it with margins. But now we add a semantic memory too: BlockQuoteLevel is similar to HeadingLevel, which was added in 310daae53926628f80c08e4415b94b90ad525c8f to preserve H1..H6 heading levels, because detecting it via font size didn't make sense in QTextMarkdownWriter. Likewise detecting quote level by its margins didn't make sense; markdown supports nesting quotes; and indenting nested quotes via 40 pixels may be a bit too much, so we should consider it subject to change (and perhaps be able to change it via CSS later on). Since we're adding BlockQuoteLevel and depending on it in QTextMarkdownWriter, it's necessary to set it in QTextHtmlParser to enable HTML->markdown conversion. (But so far, nested blockquotes in HTML are not supported.) Quotes (and nested quotes) can contain indented code blocks, but it seems the reverse is not true (according to https://spec.commonmark.org/0.29/#example-201 ) Quotes can contain fenced code blocks. Quotes can contain lists. Nested lists can be interrupted with nested code blocks and nested quotes. So far the writer assumes all code blocks are the indented type. It will be necessary to add another attribute to remember whether the code block is indented or fenced (assuming that's necessary). Fenced code blocks would work better for writing inside block quotes and list items because the fence is less ambiguous than the indent. Postponing cursor->insertBlock() as long as possible helps with nesting. cursor->insertBlock() needs to be done "just in time" before inserting text that will go in the block. The block and char formats aren't necessarily known until that time. When a nested block (such as a nested quote) ends, the context reverts to the previous block format, which then needs to be re-determined and set before we insert text into the outer block; but if no text will be inserted, no new block is necessary. But we can't use QTextBlockFormat itself as storage, because for some reason bullets become very "sticky" and it becomes impossible to have plain continuation paragraphs inside list items: they all get bullets. Somehow QTextBlockFormat remembers, if we copy it. But we can create a new one each time and it's OK. Change-Id: Icd0529eb90d2b6a3cb57f0104bf78a7be81ede52 Reviewed-by: Gatis Paeglis --- src/gui/text/qtextformat.h | 4 +- src/gui/text/qtexthtmlparser.cpp | 1 + src/gui/text/qtextmarkdownimporter.cpp | 103 ++++++++++++++++++++++++++------- src/gui/text/qtextmarkdownimporter_p.h | 8 +++ src/gui/text/qtextmarkdownwriter.cpp | 58 ++++++++++++------- src/gui/text/qtextmarkdownwriter_p.h | 1 + 6 files changed, 133 insertions(+), 42 deletions(-) (limited to 'src') diff --git a/src/gui/text/qtextformat.h b/src/gui/text/qtextformat.h index 1eb52a379c..a631309ae0 100644 --- a/src/gui/text/qtextformat.h +++ b/src/gui/text/qtextformat.h @@ -176,7 +176,9 @@ public: BlockNonBreakableLines = 0x1050, BlockTrailingHorizontalRulerWidth = 0x1060, HeadingLevel = 0x1070, - BlockMarker = 0x1080, + BlockQuoteLevel = 0x1080, + BlockCodeLanguage = 0x1090, + BlockMarker = 0x10A0, // character properties FirstFontProperty = 0x1FE0, diff --git a/src/gui/text/qtexthtmlparser.cpp b/src/gui/text/qtexthtmlparser.cpp index 895232e4c7..37051502fa 100644 --- a/src/gui/text/qtexthtmlparser.cpp +++ b/src/gui/text/qtexthtmlparser.cpp @@ -1125,6 +1125,7 @@ void QTextHtmlParserNode::initializeProperties(const QTextHtmlParserNode *parent margin[QTextHtmlParser::MarginBottom] = 12; margin[QTextHtmlParser::MarginLeft] = 40; margin[QTextHtmlParser::MarginRight] = 40; + blockFormat.setProperty(QTextFormat::BlockQuoteLevel, 1); break; case Html_dl: margin[QTextHtmlParser::MarginTop] = 8; diff --git a/src/gui/text/qtextmarkdownimporter.cpp b/src/gui/text/qtextmarkdownimporter.cpp index 5cee01d932..d8ffec2496 100644 --- a/src/gui/text/qtextmarkdownimporter.cpp +++ b/src/gui/text/qtextmarkdownimporter.cpp @@ -55,6 +55,9 @@ Q_LOGGING_CATEGORY(lcMD, "qt.text.markdown") static const QChar Newline = QLatin1Char('\n'); static const QChar Space = QLatin1Char(' '); +// TODO maybe eliminate the margins after all views recognize BlockQuoteLevel, CSS can format it, etc. +static const int BlockQuoteIndent = 40; // pixels, same as in QTextHtmlParserNode::initializeProperties + // -------------------------------------------------------- // MD4C callback function wrappers @@ -131,6 +134,7 @@ void QTextMarkdownImporter::import(QTextDocument *doc, const QString &markdown) nullptr // syntax }; m_doc = doc; + m_paragraphMargin = m_doc->defaultFont().pointSize() * 2 / 3; m_cursor = new QTextCursor(doc); doc->clear(); qCDebug(lcMD) << "default font" << doc->defaultFont() << "mono font" << m_monoFont; @@ -146,11 +150,7 @@ int QTextMarkdownImporter::cbEnterBlock(int blockType, void *det) switch (blockType) { case MD_BLOCK_P: if (m_listStack.isEmpty()) { - QTextBlockFormat blockFmt; - int margin = m_doc->defaultFont().pointSize() / 2; - blockFmt.setTopMargin(margin); - blockFmt.setBottomMargin(margin); - m_cursor->insertBlock(blockFmt, QTextCharFormat()); + m_needsInsertBlock = true; qCDebug(lcMD, "P"); } else { if (m_emptyListItem) { @@ -159,18 +159,25 @@ int QTextMarkdownImporter::cbEnterBlock(int blockType, void *det) m_emptyListItem = false; } else { qCDebug(lcMD, "P inside LI at level %d", m_listStack.count()); - QTextBlockFormat blockFmt; - blockFmt.setIndent(m_listStack.count()); - m_cursor->insertBlock(blockFmt, QTextCharFormat()); + m_needsInsertBlock = true; } } break; + case MD_BLOCK_QUOTE: { + ++m_blockQuoteDepth; + qCDebug(lcMD, "QUOTE level %d", m_blockQuoteDepth); + break; + } case MD_BLOCK_CODE: { - QTextBlockFormat blockFmt; - QTextCharFormat charFmt; - charFmt.setFont(m_monoFont); - m_cursor->insertBlock(blockFmt, charFmt); - qCDebug(lcMD, "CODE"); + MD_BLOCK_CODE_DETAIL *detail = static_cast(det); + m_codeBlock = true; + m_blockCodeLanguage = QLatin1String(detail->lang.text, int(detail->lang.size)); + QString info = QLatin1String(detail->info.text, int(detail->info.size)); + m_needsInsertBlock = true; + if (m_blockQuoteDepth) + qCDebug(lcMD, "CODE lang '%s' info '%s' inside QUOTE %d", qPrintable(m_blockCodeLanguage), qPrintable(info), m_blockQuoteDepth); + else + qCDebug(lcMD, "CODE lang '%s' info '%s'", qPrintable(m_blockCodeLanguage), qPrintable(info)); } break; case MD_BLOCK_H: { MD_BLOCK_H_DETAIL *detail = static_cast(det); @@ -180,10 +187,12 @@ int QTextMarkdownImporter::cbEnterBlock(int blockType, void *det) charFmt.setProperty(QTextFormat::FontSizeAdjustment, sizeAdjustment); charFmt.setFontWeight(QFont::Bold); blockFmt.setHeadingLevel(int(detail->level)); + m_needsInsertBlock = false; m_cursor->insertBlock(blockFmt, charFmt); qCDebug(lcMD, "H%d", detail->level); } break; case MD_BLOCK_LI: { + m_needsInsertBlock = false; MD_BLOCK_LI_DETAIL *detail = static_cast(det); QTextList *list = m_listStack.top(); QTextBlockFormat bfmt = list->item(list->count() - 1).blockFormat(); @@ -316,9 +325,9 @@ int QTextMarkdownImporter::cbLeaveBlock(int blockType, void *detail) } } break; case MD_BLOCK_QUOTE: { - QTextBlockFormat blockFmt = m_cursor->blockFormat(); - blockFmt.setIndent(1); - m_cursor->setBlockFormat(blockFmt); + qCDebug(lcMD, "QUOTE level %d ended", m_blockQuoteDepth); + --m_blockQuoteDepth; + m_needsInsertBlock = true; } break; case MD_BLOCK_TABLE: qCDebug(lcMD) << "table ended with" << m_currentTable->columns() << "cols and" << m_currentTable->rows() << "rows"; @@ -329,7 +338,15 @@ int QTextMarkdownImporter::cbLeaveBlock(int blockType, void *detail) qCDebug(lcMD, "LI at level %d ended", m_listStack.count()); m_listItem = false; break; - case MD_BLOCK_CODE: + case MD_BLOCK_CODE: { + m_codeBlock = false; + m_blockCodeLanguage.clear(); + if (m_blockQuoteDepth) + qCDebug(lcMD, "CODE ended inside QUOTE %d", m_blockQuoteDepth); + else + qCDebug(lcMD, "CODE ended"); + m_needsInsertBlock = true; + } break; case MD_BLOCK_H: m_cursor->setCharFormat(QTextCharFormat()); break; @@ -365,6 +382,8 @@ int QTextMarkdownImporter::cbEnterSpan(int spanType, void *det) QString title = QString::fromUtf8(detail->title.text, int(detail->title.size)); QTextImageFormat img; img.setName(src); + if (m_needsInsertBlock) + insertBlock(); qCDebug(lcMD) << "image" << src << "title" << title << "relative to" << m_doc->baseUrl(); m_cursor->insertImage(img); break; @@ -377,6 +396,8 @@ int QTextMarkdownImporter::cbEnterSpan(int spanType, void *det) break; } m_spanFormatStack.push(charFmt); + qCDebug(lcMD) << spanType << "setCharFormat" << charFmt.font().family() << charFmt.fontWeight() + << (charFmt.fontItalic() ? "italic" : "") << charFmt.foreground().color().name(); m_cursor->setCharFormat(charFmt); return 0; // no error } @@ -391,6 +412,8 @@ int QTextMarkdownImporter::cbLeaveSpan(int spanType, void *detail) charFmt = m_spanFormatStack.top(); } m_cursor->setCharFormat(charFmt); + qCDebug(lcMD) << spanType << "setCharFormat" << charFmt.font().family() << charFmt.fontWeight() + << (charFmt.fontItalic() ? "italic" : "") << charFmt.foreground().color().name(); if (spanType == int(MD_SPAN_IMG)) m_imageSpan = false; return 0; // no error @@ -400,6 +423,8 @@ int QTextMarkdownImporter::cbText(int textType, const char *text, unsigned size) { if (m_imageSpan) return 0; // it's the alt-text + if (m_needsInsertBlock) + insertBlock(); static const QRegularExpression openingBracket(QStringLiteral("<[a-zA-Z]")); static const QRegularExpression closingBracket(QStringLiteral("(/>|insertText(s); if (m_cursor->currentList()) { // The list item will indent the list item's text, so we don't need indentation on the block. - QTextBlockFormat blockFmt = m_cursor->blockFormat(); - blockFmt.setIndent(0); - m_cursor->setBlockFormat(blockFmt); + QTextBlockFormat bfmt = m_cursor->blockFormat(); + bfmt.setIndent(0); + m_cursor->setBlockFormat(bfmt); + } + if (lcMD().isEnabled(QtDebugMsg)) { + QTextBlockFormat bfmt = m_cursor->blockFormat(); + QString debugInfo; + if (m_cursor->currentList()) + debugInfo = QLatin1String("in list at depth ") + QString::number(m_cursor->currentList()->format().indent()); + if (bfmt.hasProperty(QTextFormat::BlockQuoteLevel)) + debugInfo += QLatin1String("in blockquote at depth ") + + QString::number(bfmt.intProperty(QTextFormat::BlockQuoteLevel)); + if (bfmt.hasProperty(QTextFormat::BlockCodeLanguage)) + debugInfo += QLatin1String("in a code block"); + qCDebug(lcMD) << textType << "in block" << m_blockType << s << qPrintable(debugInfo) + << "bindent" << bfmt.indent() << "tindent" << bfmt.textIndent() + << "margins" << bfmt.leftMargin() << bfmt.topMargin() << bfmt.bottomMargin() << bfmt.rightMargin(); } qCDebug(lcMD) << textType << "in block" << m_blockType << s << "in list?" << m_cursor->currentList() << "indent" << m_cursor->blockFormat().indent(); return 0; // no error } +void QTextMarkdownImporter::insertBlock() +{ + QTextCharFormat charFormat; + if (!m_spanFormatStack.isEmpty()) + charFormat = m_spanFormatStack.top(); + QTextBlockFormat blockFormat; + if (m_blockQuoteDepth) { + blockFormat.setProperty(QTextFormat::BlockQuoteLevel, m_blockQuoteDepth); + blockFormat.setLeftMargin(BlockQuoteIndent * m_blockQuoteDepth); + blockFormat.setRightMargin(BlockQuoteIndent); + } + if (m_listStack.count()) + blockFormat.setIndent(m_listStack.count()); + if (m_codeBlock) { + blockFormat.setProperty(QTextFormat::BlockCodeLanguage, m_blockCodeLanguage); + charFormat.setFont(m_monoFont); + } else { + blockFormat.setTopMargin(m_paragraphMargin); + blockFormat.setBottomMargin(m_paragraphMargin); + } + m_cursor->insertBlock(blockFormat, charFormat); + m_needsInsertBlock = false; +} + QT_END_NAMESPACE diff --git a/src/gui/text/qtextmarkdownimporter_p.h b/src/gui/text/qtextmarkdownimporter_p.h index 8ab119d051..1716530b1d 100644 --- a/src/gui/text/qtextmarkdownimporter_p.h +++ b/src/gui/text/qtextmarkdownimporter_p.h @@ -99,26 +99,34 @@ public: int cbLeaveSpan(int spanType, void* detail); int cbText(int textType, const char* text, unsigned size); +private: + void insertBlock(); + private: QTextDocument *m_doc = nullptr; QTextCursor *m_cursor = nullptr; QTextTable *m_currentTable = nullptr; // because m_cursor->currentTable() doesn't work QString m_htmlAccumulator; + QString m_blockCodeLanguage; QVector m_nonEmptyTableCells; // in the current row QStack m_listStack; QStack m_spanFormatStack; QFont m_monoFont; QPalette m_palette; int m_htmlTagDepth = 0; + int m_blockQuoteDepth = 0; int m_tableColumnCount = 0; int m_tableRowCount = 0; int m_tableCol = -1; // because relative cell movements (e.g. m_cursor->movePosition(QTextCursor::NextCell)) don't work + int m_paragraphMargin = 0; Features m_features; int m_blockType = 0; bool m_emptyList = false; // true when the last thing we did was insertList bool m_listItem = false; bool m_emptyListItem = false; + bool m_codeBlock = false; bool m_imageSpan = false; + bool m_needsInsertBlock = false; }; Q_DECLARE_OPERATORS_FOR_FLAGS(QTextMarkdownImporter::Features) diff --git a/src/gui/text/qtextmarkdownwriter.cpp b/src/gui/text/qtextmarkdownwriter.cpp index a445ee7e83..f180098db2 100644 --- a/src/gui/text/qtextmarkdownwriter.cpp +++ b/src/gui/text/qtextmarkdownwriter.cpp @@ -106,7 +106,7 @@ void QTextMarkdownWriter::writeFrame(const QTextFrame *frame) Q_ASSERT(frame); const QTextTable *table = qobject_cast (frame); QTextFrame::iterator iterator = frame->begin(); - QTextFrame *child = 0; + QTextFrame *child = nullptr; int tableRow = -1; bool lastWasList = false; QVector tableColumnWidths; @@ -161,7 +161,7 @@ void QTextMarkdownWriter::writeFrame(const QTextFrame *frame) m_stream << QString(paddingLen, Space); for (int col = cell.column(); col < spanEndCol; ++col) m_stream << "|"; - } else if (block.textList()) { + } else if (block.textList() || block.blockFormat().hasProperty(QTextFormat::BlockCodeLanguage)) { m_stream << Newline; } else if (endingCol > 0) { m_stream << Newline << Newline; @@ -252,6 +252,8 @@ static void maybeEscapeFirstChar(QString &s) int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ignoreFormat) { int ColumnLimit = 80; + QTextBlockFormat blockFmt = block.blockFormat(); + bool indentedCodeBlock = false; if (block.textList()) { // it's a list-item auto fmt = block.textList()->format(); const int listLevel = fmt.indent(); @@ -281,7 +283,7 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign m_wrappedLineIndent = 4; break; } - switch (block.blockFormat().marker()) { + switch (blockFmt.marker()) { case QTextBlockFormat::Checked: bullet += " [x]"; break; @@ -309,21 +311,35 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign prefix += QLatin1String(bullet) + Space; } m_stream << prefix; - } else if (block.blockFormat().hasProperty(QTextFormat::BlockTrailingHorizontalRulerWidth)) { + } else if (blockFmt.hasProperty(QTextFormat::BlockTrailingHorizontalRulerWidth)) { m_stream << "- - -\n"; // unambiguous horizontal rule, not an underline under a heading return 0; - } else if (!block.blockFormat().indent()) { + } else if (!blockFmt.indent()) { m_wrappedLineIndent = 0; + m_linePrefix.clear(); + if (blockFmt.hasProperty(QTextFormat::BlockQuoteLevel)) { + int level = blockFmt.intProperty(QTextFormat::BlockQuoteLevel); + QString quoteMarker = QStringLiteral("> "); + m_linePrefix.reserve(level * 2); + for (int i = 0; i < level; ++i) + m_linePrefix += quoteMarker; + } + if (blockFmt.hasProperty(QTextFormat::BlockCodeLanguage)) { + // A block quote can contain an indented code block, but not vice-versa. + m_linePrefix += QString(4, Space); + indentedCodeBlock = true; + } } + if (blockFmt.headingLevel()) + m_stream << QByteArray(blockFmt.headingLevel(), '#') << ' '; + else + m_stream << m_linePrefix; - if (block.blockFormat().headingLevel()) - m_stream << QByteArray(block.blockFormat().headingLevel(), '#') << ' '; - - QString wrapIndentString(m_wrappedLineIndent, Space); + QString wrapIndentString = m_linePrefix + QString(m_wrappedLineIndent, Space); // It would be convenient if QTextStream had a lineCharPos() accessor, // to keep track of how many characters (not bytes) have been written on the current line, // but it doesn't. So we have to keep track with this col variable. - int col = m_wrappedLineIndent; + int col = wrapIndentString.length(); bool mono = false; bool startsOrEndsWithBacktick = false; bool bold = false; @@ -338,7 +354,7 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign if (block.textList()) { //
  • first line
    continuation
  • QString newlineIndent = QString(Newline) + QString(m_wrappedLineIndent, Space); fragmentText.replace(QString(LineBreak), newlineIndent); - } else if (block.blockFormat().indent() > 0) { //
  • first line

    continuation

  • + } else if (blockFmt.indent() > 0) { //
  • first line

    continuation

  • m_stream << QString(m_wrappedLineIndent, Space); } else { fragmentText.replace(LineBreak, Newline); @@ -368,7 +384,7 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign bool monoFrag = fontInfo.fixedPitch(); QString markers; if (!ignoreFormat) { - if (monoFrag != mono) { + if (monoFrag != mono && !indentedCodeBlock) { if (monoFrag) backticks = QString(adjacentBackticksCount(fragmentText) + 1, Backtick); markers += backticks; @@ -376,25 +392,25 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign markers += Space; mono = monoFrag; } - if (!block.blockFormat().headingLevel() && !mono) { - if (fmt.font().bold() != bold) { + if (!blockFmt.headingLevel() && !mono) { + if (fontInfo.bold() != bold) { markers += QLatin1String("**"); - bold = fmt.font().bold(); + bold = fontInfo.bold(); } - if (fmt.font().italic() != italic) { + if (fontInfo.italic() != italic) { markers += QLatin1Char('*'); - italic = fmt.font().italic(); + italic = fontInfo.italic(); } - if (fmt.font().strikeOut() != strikeOut) { + if (fontInfo.strikeOut() != strikeOut) { markers += QLatin1String("~~"); - strikeOut = fmt.font().strikeOut(); + strikeOut = fontInfo.strikeOut(); } - if (fmt.font().underline() != underline) { + if (fontInfo.underline() != underline) { // Markdown doesn't support underline, but the parser will treat a single underline // the same as a single asterisk, and the marked fragment will be rendered in italics. // That will have to do. markers += QLatin1Char('_'); - underline = fmt.font().underline(); + underline = fontInfo.underline(); } } } diff --git a/src/gui/text/qtextmarkdownwriter_p.h b/src/gui/text/qtextmarkdownwriter_p.h index 4c07bad2e7..96ceb445cd 100644 --- a/src/gui/text/qtextmarkdownwriter_p.h +++ b/src/gui/text/qtextmarkdownwriter_p.h @@ -81,6 +81,7 @@ private: QTextStream &m_stream; QTextDocument::MarkdownFeatures m_features; QMap m_listInfo; + QString m_linePrefix; int m_wrappedLineIndent = 0; int m_lastListIndent = 1; bool m_doubleNewlineWritten = false; -- cgit v1.2.3 From 5652d33f973a03b93c9b5ce9e49db8cf0430b675 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 30 Apr 2019 11:54:31 +0200 Subject: Bump version to Qt 6 Needed to disable QT_NO_UNSHARABLE_CONTAINERS, as this triggers asserts. QMetaType also has some Qt 6 specific code disabled to get things to compile. Fix various details in autotests to accommodate for the changes with Qt 6. Add a workaround for black lists on macos, where QSysInfo::productType() now returns 'macos' and not 'osx' anymore. Change-Id: Ie26afb12a2aac36521472715934a7e34639ea4d0 Reviewed-by: Simon Hausmann --- src/corelib/global/qglobal.h | 3 ++- src/corelib/global/qlogging.cpp | 2 +- src/corelib/io/qfileselector.cpp | 7 ------- src/corelib/io/qfilesystemwatcher_win.cpp | 2 +- src/corelib/itemmodels/qabstractitemmodel.cpp | 4 ++++ src/corelib/itemmodels/qabstractproxymodel.h | 6 +++++- src/corelib/kernel/qcoreapplication.cpp | 6 +++--- src/corelib/kernel/qmetatype.h | 2 +- src/corelib/mimetypes/qmimedatabase_p.h | 1 + src/corelib/plugin/qlibrary.cpp | 4 ++-- src/gui/image/qimage_p.h | 2 +- src/gui/itemmodels/qstandarditemmodel.h | 7 +++++-- src/network/ssl/qsslsocket_winrt.cpp | 6 +++--- src/plugins/platforms/cocoa/qcocoaintegration.mm | 2 +- src/testlib/qtestblacklist.cpp | 10 ++++++++++ 15 files changed, 40 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 0a0c434a07..499558d7e6 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -87,7 +87,8 @@ #define QT_REQUIRE_CONFIG(feature) Q_STATIC_ASSERT_X(QT_FEATURE_##feature == 1, "Required feature " #feature " for file " __FILE__ " not available.") #if QT_VERSION >= QT_VERSION_CHECK(6,0,0) -# define QT_NO_UNSHARABLE_CONTAINERS +// ### Qt6: FIXME and get rid of unsharable containers +//# define QT_NO_UNSHARABLE_CONTAINERS # define QT6_VIRTUAL virtual # define QT6_NOT_VIRTUAL #else diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp index 4941ca45aa..23cb5ba61e 100644 --- a/src/corelib/global/qlogging.cpp +++ b/src/corelib/global/qlogging.cpp @@ -1318,7 +1318,7 @@ static QStringList backtraceFramesForLogMessage(int frameCount) QString function = m.captured(2); // skip the trace from QtCore that are because of the qDebug itself - if (!numberPrinted && library.contains(QLatin1String("Qt5Core")) + if (!numberPrinted && library.contains(QLatin1String("Qt6Core")) && (function.isEmpty() || function.contains(QLatin1String("Message"), Qt::CaseInsensitive) || function.contains(QLatin1String("QDebug")))) { continue; diff --git a/src/corelib/io/qfileselector.cpp b/src/corelib/io/qfileselector.cpp index ce06c8e00b..7f65b0f8f7 100644 --- a/src/corelib/io/qfileselector.cpp +++ b/src/corelib/io/qfileselector.cpp @@ -331,7 +331,6 @@ void QFileSelectorPrivate::updateSelectors() QStringList QFileSelectorPrivate::platformSelectors() { // similar, but not identical to QSysInfo::osType - // ### Qt6: remove macOS fallbacks to "mac" and the future compatibility QStringList ret; #if defined(Q_OS_WIN) ret << QStringLiteral("windows"); @@ -344,16 +343,10 @@ QStringList QFileSelectorPrivate::platformSelectors() # if !defined(Q_OS_ANDROID) && !defined(Q_OS_QNX) // we don't want "linux" for Android or two instances of "qnx" for QNX ret << QSysInfo::kernelType(); -# ifdef Q_OS_MAC - ret << QStringLiteral("mac"); // compatibility, since kernelType() is "darwin" -# endif # endif QString productName = QSysInfo::productType(); if (productName != QLatin1String("unknown")) ret << productName; // "opensuse", "fedora", "osx", "ios", "android" -# if defined(Q_OS_MACOS) - ret << QStringLiteral("macos"); // future compatibility -# endif #endif return ret; } diff --git a/src/corelib/io/qfilesystemwatcher_win.cpp b/src/corelib/io/qfilesystemwatcher_win.cpp index eb626fd541..e1949e9697 100644 --- a/src/corelib/io/qfilesystemwatcher_win.cpp +++ b/src/corelib/io/qfilesystemwatcher_win.cpp @@ -79,7 +79,7 @@ static Qt::HANDLE createChangeNotification(const QString &path, uint flags) nativePath.append(QLatin1Char('\\')); const HANDLE result = FindFirstChangeNotification(reinterpret_cast(nativePath.utf16()), FALSE, flags); - DEBUG() << __FUNCTION__ << nativePath << Qt::hex <invalidatePersistentIndexes(); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + resetInternalData(); +#else QMetaObject::invokeMethod(this, "resetInternalData"); +#endif emit modelReset(QPrivateSignal()); } diff --git a/src/corelib/itemmodels/qabstractproxymodel.h b/src/corelib/itemmodels/qabstractproxymodel.h index c9a73b6a31..f6f6e45c1a 100644 --- a/src/corelib/itemmodels/qabstractproxymodel.h +++ b/src/corelib/itemmodels/qabstractproxymodel.h @@ -103,7 +103,11 @@ Q_SIGNALS: void sourceModelChanged(QPrivateSignal); protected Q_SLOTS: - void resetInternalData(); + void resetInternalData() +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + override +#endif + ; protected: QAbstractProxyModel(QAbstractProxyModelPrivate &, QObject *parent); diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 7a6faf2e2b..fc8b9227d4 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -152,10 +152,10 @@ private: extern QString qAppFileName(); #endif -#if QT_VERSION >= 0x060000 -# error "Bump QCoreApplicatoinPrivate::app_compile_version to 0x060000" +#if QT_VERSION >= 0x070000 +# error "Bump QCoreApplicatoinPrivate::app_compile_version to 0x070000" #endif -int QCoreApplicationPrivate::app_compile_version = 0x050000; //we don't know exactly, but it's at least 5.0.0 +int QCoreApplicationPrivate::app_compile_version = 0x060000; //we don't know exactly, but it's at least 6.0.0 bool QCoreApplicationPrivate::setuidAllowed = false; diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index 79ee5eec11..7f512b6cb1 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -493,7 +493,7 @@ public: typedef void (*Deleter)(void *); typedef void *(*Creator)(const void *); -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) +#if 1 || QT_VERSION < QT_VERSION_CHECK(6, 0, 0) // ### Qt6: fix this typedef void (*Destructor)(void *); typedef void *(*Constructor)(void *, const void *); // TODO Qt6: remove me #endif diff --git a/src/corelib/mimetypes/qmimedatabase_p.h b/src/corelib/mimetypes/qmimedatabase_p.h index d9cf446d44..831390de1f 100644 --- a/src/corelib/mimetypes/qmimedatabase_p.h +++ b/src/corelib/mimetypes/qmimedatabase_p.h @@ -63,6 +63,7 @@ QT_REQUIRE_CONFIG(mimetype); #include #include +#include #include QT_BEGIN_NAMESPACE diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp index 0e32776c71..c059851fce 100644 --- a/src/corelib/plugin/qlibrary.cpp +++ b/src/corelib/plugin/qlibrary.cpp @@ -692,7 +692,7 @@ static bool qt_get_metadata(QLibraryPrivate *priv, QString *errMsg) }; #else auto getMetaData = [](QFunctionPointer fptr) { - auto f = reinterpret_cast (*)()>(fptr); + auto f = reinterpret_cast(fptr); return f(); }; #endif @@ -702,7 +702,7 @@ static bool qt_get_metadata(QLibraryPrivate *priv, QString *errMsg) return false; auto metaData = getMetaData(pfn); - QJsonDocument doc = qJsonFromRawLibraryMetaData(metaData.first, metaData.second, errMsg); + QJsonDocument doc = qJsonFromRawLibraryMetaData(reinterpret_cast(metaData.data), metaData.size, errMsg); if (doc.isNull()) return false; priv->metaData = doc.object(); diff --git a/src/gui/image/qimage_p.h b/src/gui/image/qimage_p.h index 9da6acd0a7..1cd0e8e0aa 100644 --- a/src/gui/image/qimage_p.h +++ b/src/gui/image/qimage_p.h @@ -140,7 +140,7 @@ QImageData::calculateImageParameters(qsizetype width, qsizetype height, qsizetyp qsizetype dummy; if (mul_overflow(height, qsizetype(sizeof(uchar *)), &dummy)) return invalid; // why is this here? -#if QT_VERSION < QT_VERSION_CHECK(6,0,0) +#if 1 || QT_VERSION < QT_VERSION_CHECK(6,0,0) // ### can only fix this if QImage dimensions are not int anymore // Disallow images where width * depth calculations might overflow if (width > (INT_MAX - 31) / depth) return invalid; diff --git a/src/gui/itemmodels/qstandarditemmodel.h b/src/gui/itemmodels/qstandarditemmodel.h index a9ee25da75..435b66591c 100644 --- a/src/gui/itemmodels/qstandarditemmodel.h +++ b/src/gui/itemmodels/qstandarditemmodel.h @@ -344,8 +344,11 @@ public: QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; - // Qt 6: add override keyword - bool clearItemData(const QModelIndex &index); + bool clearItemData(const QModelIndex &index) +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + override +#endif + ; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; diff --git a/src/network/ssl/qsslsocket_winrt.cpp b/src/network/ssl/qsslsocket_winrt.cpp index d54ac2ad73..0bbe6fe57d 100644 --- a/src/network/ssl/qsslsocket_winrt.cpp +++ b/src/network/ssl/qsslsocket_winrt.cpp @@ -274,7 +274,7 @@ void QSslSocketBackendPrivate::startClientEncryption() } // Sync custom certificates - const QSet caCertificates = configuration.caCertificates.toSet(); + const QSet caCertificates(configuration.caCertificates.constBegin(), configuration.caCertificates.constEnd()); const QSet newCertificates = caCertificates - previousCaCertificates; const QSet oldCertificates = previousCaCertificates - caCertificates; g->syncCaCertificates(newCertificates, oldCertificates); @@ -397,7 +397,7 @@ void QSslSocketBackendPrivate::continueHandshake() hr = control2->get_IgnorableServerCertificateErrors(&ignoreList); Q_ASSERT_SUCCEEDED(hr); - QSet ignoreErrors = ignoreErrorsList.toSet(); + QSet ignoreErrors(ignoreErrorsList.constBegin(), ignoreErrorsList.constEnd()); for (int i = ChainValidationResult_Untrusted; i < ChainValidationResult_OtherErrors + 1; ++i) { // Populate the native ignore list - break to add, continue to skip switch (i) { @@ -600,7 +600,7 @@ HRESULT QSslSocketBackendPrivate::onSslUpgrade(IAsyncAction *action, AsyncStatus } } - sslErrors = errors.toList(); + sslErrors = QList(errors.constBegin(), errors.constEnd()); // Peer validation if (!configuration.peerCertificate.isNull()) { diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index fb3d05d3e4..eb18e573ea 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -272,7 +272,7 @@ void QCocoaIntegration::updateScreens() [screens addObject:[NSScreen mainScreen]]; if ([screens count] == 0) return; - QSet remainingScreens = QSet::fromList(mScreens); + QSet remainingScreens = QSet(mScreens.constBegin(), mScreens.constEnd()); QList siblings; uint screenCount = [screens count]; for (uint i = 0; i < screenCount; i++) { diff --git a/src/testlib/qtestblacklist.cpp b/src/testlib/qtestblacklist.cpp index 886f1f75b9..72bb5688ef 100644 --- a/src/testlib/qtestblacklist.cpp +++ b/src/testlib/qtestblacklist.cpp @@ -186,10 +186,20 @@ static QSet activeConditions() if (!distributionName.isEmpty()) { if (result.find(distributionName) == result.end()) result.insert(distributionName); + // backwards compatibility with Qt 5 + if (distributionName == "macos") { + if (result.find(distributionName) == result.end()) + result.insert("osx"); + } if (!distributionRelease.isEmpty()) { QByteArray versioned = distributionName + "-" + distributionRelease; if (result.find(versioned) == result.end()) result.insert(versioned); + if (distributionName == "macos") { + QByteArray versioned = "osx-" + distributionRelease; + if (result.find(versioned) == result.end()) + result.insert(versioned); + } } } -- cgit v1.2.3 From 1dde5a7b9523ab7f62a6965edfd7b87ed40eecb8 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Wed, 13 Mar 2019 09:46:20 +0100 Subject: Remove deprecated QEasingCurve::cubicBezierSpline() function It has been deprecated since Qt 5.0 so hopefully nobody is using it anymore. Change-Id: If3466f8a2d25ea87cd51ca71606d2a27a428efcf Reviewed-by: Christian Ehrlicher --- src/corelib/tools/qeasingcurve.cpp | 5 ----- src/corelib/tools/qeasingcurve.h | 7 ------- 2 files changed, 12 deletions(-) (limited to 'src') diff --git a/src/corelib/tools/qeasingcurve.cpp b/src/corelib/tools/qeasingcurve.cpp index 9169b5c7f1..c807bbd2e1 100644 --- a/src/corelib/tools/qeasingcurve.cpp +++ b/src/corelib/tools/qeasingcurve.cpp @@ -1365,11 +1365,6 @@ void QEasingCurve::addTCBSegment(const QPointF &nextPoint, qreal t, qreal c, qre } -/*! - \fn QList QEasingCurve::cubicBezierSpline() const - \obsolete Use toCubicSpline() instead. - */ - /*! \since 5.0 diff --git a/src/corelib/tools/qeasingcurve.h b/src/corelib/tools/qeasingcurve.h index 725ddd5dcc..f7a1d6bdc0 100644 --- a/src/corelib/tools/qeasingcurve.h +++ b/src/corelib/tools/qeasingcurve.h @@ -43,10 +43,6 @@ #include #include #include -#if QT_DEPRECATED_SINCE(5, 0) -# include -# include -#endif QT_BEGIN_NAMESPACE @@ -102,9 +98,6 @@ public: void addCubicBezierSegment(const QPointF & c1, const QPointF & c2, const QPointF & endPoint); void addTCBSegment(const QPointF &nextPoint, qreal t, qreal c, qreal b); QVector toCubicSpline() const; -#if QT_DEPRECATED_SINCE(5, 0) - QT_DEPRECATED QList cubicBezierSpline() const { return toCubicSpline().toList(); } -#endif Type type() const; void setType(Type type); -- cgit v1.2.3 From 237fa21feef63884043bd6cf32682b2b08c78454 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Mon, 20 May 2019 12:58:36 +0200 Subject: Markdown and HTML: support image alt text and title It's a required CommonMark feature: https://spec.commonmark.org/0.29/#images and alt text is also required in HTML: https://www.w3.org/wiki/Html/Elements/img#Requirements_for_providing_text_to_act_as_an_alternative_for_images Now we are able to read these attributes from either html or markdown and rewrite either an html or markdown document that preserves them. This patch does not add viewing or editing support in QTextEdit etc. Change-Id: I51307389f8f9fc00809808390e583a83111a7b33 Reviewed-by: Gatis Paeglis --- src/gui/text/qtextdocument.cpp | 6 ++++++ src/gui/text/qtextdocumentfragment.cpp | 4 ++++ src/gui/text/qtextformat.cpp | 8 +++++++- src/gui/text/qtextformat.h | 2 ++ src/gui/text/qtexthtmlparser.cpp | 4 ++++ src/gui/text/qtexthtmlparser_p.h | 1 + src/gui/text/qtextmarkdownimporter.cpp | 24 ++++++++++++++---------- src/gui/text/qtextmarkdownimporter_p.h | 1 + src/gui/text/qtextmarkdownwriter.cpp | 10 +++++++++- 9 files changed, 48 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp index c800cea3f6..899801ca39 100644 --- a/src/gui/text/qtextdocument.cpp +++ b/src/gui/text/qtextdocument.cpp @@ -2709,6 +2709,12 @@ void QTextHtmlExporter::emitFragment(const QTextFragment &fragment) if (imgFmt.hasProperty(QTextFormat::ImageName)) emitAttribute("src", imgFmt.name()); + if (imgFmt.hasProperty(QTextFormat::ImageAltText)) + emitAttribute("alt", imgFmt.stringProperty(QTextFormat::ImageAltText)); + + if (imgFmt.hasProperty(QTextFormat::ImageTitle)) + emitAttribute("title", imgFmt.stringProperty(QTextFormat::ImageTitle)); + if (imgFmt.hasProperty(QTextFormat::ImageWidth)) emitAttribute("width", QString::number(imgFmt.width())); diff --git a/src/gui/text/qtextdocumentfragment.cpp b/src/gui/text/qtextdocumentfragment.cpp index aef4ea1522..1905d9a1b1 100644 --- a/src/gui/text/qtextdocumentfragment.cpp +++ b/src/gui/text/qtextdocumentfragment.cpp @@ -715,6 +715,10 @@ QTextHtmlImporter::ProcessNodeResult QTextHtmlImporter::processSpecialNodes() case Html_img: { QTextImageFormat fmt; fmt.setName(currentNode->imageName); + if (!currentNode->text.isEmpty()) + fmt.setProperty(QTextFormat::ImageTitle, currentNode->text); + if (!currentNode->imageAlt.isEmpty()) + fmt.setProperty(QTextFormat::ImageAltText, currentNode->imageAlt); fmt.merge(currentNode->charFormat); diff --git a/src/gui/text/qtextformat.cpp b/src/gui/text/qtextformat.cpp index 895b9034e0..644dd5558d 100644 --- a/src/gui/text/qtextformat.cpp +++ b/src/gui/text/qtextformat.cpp @@ -659,7 +659,13 @@ Q_GUI_EXPORT QDataStream &operator>>(QDataStream &stream, QTextFormat &fmt) Image properties - \value ImageName + \value ImageName The filename or source of the image. + \value ImageTitle The title attribute of an HTML image tag, or + the quoted string that comes after the URL in a Markdown image link. + This enum value has been added in Qt 5.14. + \value ImageAltText The alt attribute of an HTML image tag, or + the image description in a Markdown image link. + This enum value has been added in Qt 5.14. \value ImageWidth \value ImageHeight \value ImageQuality diff --git a/src/gui/text/qtextformat.h b/src/gui/text/qtextformat.h index a631309ae0..4f534fb65d 100644 --- a/src/gui/text/qtextformat.h +++ b/src/gui/text/qtextformat.h @@ -253,6 +253,8 @@ public: // image properties ImageName = 0x5000, + ImageTitle = 0x5001, + ImageAltText = 0x5002, ImageWidth = 0x5010, ImageHeight = 0x5011, ImageQuality = 0x5014, diff --git a/src/gui/text/qtexthtmlparser.cpp b/src/gui/text/qtexthtmlparser.cpp index 37051502fa..49ee6394ee 100644 --- a/src/gui/text/qtexthtmlparser.cpp +++ b/src/gui/text/qtexthtmlparser.cpp @@ -1556,6 +1556,10 @@ void QTextHtmlParser::applyAttributes(const QStringList &attributes) } else if (key == QLatin1String("height")) { node->imageHeight = -2; // register that there is a value for it. setFloatAttribute(&node->imageHeight, value); + } else if (key == QLatin1String("alt")) { + node->imageAlt = value; + } else if (key == QLatin1String("title")) { + node->text = value; } break; case Html_tr: diff --git a/src/gui/text/qtexthtmlparser_p.h b/src/gui/text/qtexthtmlparser_p.h index 73dac38b82..6ce294d211 100644 --- a/src/gui/text/qtexthtmlparser_p.h +++ b/src/gui/text/qtexthtmlparser_p.h @@ -184,6 +184,7 @@ struct QTextHtmlParserNode { QString textListNumberPrefix; QString textListNumberSuffix; QString imageName; + QString imageAlt; qreal imageWidth; qreal imageHeight; QTextLength width; diff --git a/src/gui/text/qtextmarkdownimporter.cpp b/src/gui/text/qtextmarkdownimporter.cpp index b96acba0e6..223eb01e55 100644 --- a/src/gui/text/qtextmarkdownimporter.cpp +++ b/src/gui/text/qtextmarkdownimporter.cpp @@ -362,15 +362,10 @@ int QTextMarkdownImporter::cbEnterSpan(int spanType, void *det) } break; case MD_SPAN_IMG: { m_imageSpan = true; + m_imageFormat = QTextImageFormat(); MD_SPAN_IMG_DETAIL *detail = static_cast(det); - QString src = QString::fromUtf8(detail->src.text, int(detail->src.size)); - QString title = QString::fromUtf8(detail->title.text, int(detail->title.size)); - QTextImageFormat img; - img.setName(src); - if (m_needsInsertBlock) - insertBlock(); - qCDebug(lcMD) << "image" << src << "title" << title << "relative to" << m_doc->baseUrl(); - m_cursor->insertImage(img); + m_imageFormat.setName(QString::fromUtf8(detail->src.text, int(detail->src.size))); + m_imageFormat.setProperty(QTextFormat::ImageTitle, QString::fromUtf8(detail->title.text, int(detail->title.size))); break; } case MD_SPAN_CODE: @@ -406,8 +401,6 @@ int QTextMarkdownImporter::cbLeaveSpan(int spanType, void *detail) int QTextMarkdownImporter::cbText(int textType, const char *text, unsigned size) { - if (m_imageSpan) - return 0; // it's the alt-text if (m_needsInsertBlock) insertBlock(); #if QT_CONFIG(regularexpression) @@ -481,6 +474,17 @@ int QTextMarkdownImporter::cbText(int textType, const char *text, unsigned size) break; } + if (m_imageSpan) { + // TODO we don't yet support alt text with formatting, because of the cases where m_cursor + // already inserted the text above. Rather need to accumulate it in case we need it here. + m_imageFormat.setProperty(QTextFormat::ImageAltText, s); + qCDebug(lcMD) << "image" << m_imageFormat.name() + << "title" << m_imageFormat.stringProperty(QTextFormat::ImageTitle) + << "alt" << s << "relative to" << m_doc->baseUrl(); + m_cursor->insertImage(m_imageFormat); + return 0; // no error + } + if (!s.isEmpty()) m_cursor->insertText(s); if (m_cursor->currentList()) { diff --git a/src/gui/text/qtextmarkdownimporter_p.h b/src/gui/text/qtextmarkdownimporter_p.h index f905aa0f87..fdce74483b 100644 --- a/src/gui/text/qtextmarkdownimporter_p.h +++ b/src/gui/text/qtextmarkdownimporter_p.h @@ -125,6 +125,7 @@ private: int m_paragraphMargin = 0; int m_blockType = 0; Features m_features; + QTextImageFormat m_imageFormat; QTextListFormat m_listFormat; QTextBlockFormat::MarkerType m_markerType = QTextBlockFormat::NoMarker; bool m_needsInsertBlock = false; diff --git a/src/gui/text/qtextmarkdownwriter.cpp b/src/gui/text/qtextmarkdownwriter.cpp index 02643acdca..58e0c86b95 100644 --- a/src/gui/text/qtextmarkdownwriter.cpp +++ b/src/gui/text/qtextmarkdownwriter.cpp @@ -55,6 +55,7 @@ Q_LOGGING_CATEGORY(lcMDW, "qt.text.markdown.writer") static const QChar Space = QLatin1Char(' '); static const QChar Newline = QLatin1Char('\n'); static const QChar LineBreak = QChar(0x2028); +static const QChar DoubleQuote = QLatin1Char('"'); static const QChar Backtick = QLatin1Char('`'); static const QChar Period = QLatin1Char('.'); @@ -372,7 +373,14 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign QTextCharFormat fmt = frag.fragment().charFormat(); if (fmt.isImageFormat()) { QTextImageFormat ifmt = fmt.toImageFormat(); - QString s = QLatin1String("![image](") + ifmt.name() + QLatin1Char(')'); + QString desc = ifmt.stringProperty(QTextFormat::ImageAltText); + if (desc.isEmpty()) + desc = QLatin1String("image"); + QString s = QLatin1String("![") + desc + QLatin1String("](") + ifmt.name(); + QString title = ifmt.stringProperty(QTextFormat::ImageTitle); + if (!title.isEmpty()) + s += Space + DoubleQuote + title + DoubleQuote; + s += QLatin1Char(')'); if (wrap && col + s.length() > ColumnLimit) { m_stream << Newline << wrapIndentString; col = m_wrappedLineIndent; -- cgit v1.2.3 From 3af85b92d7ae19cc229ebccb3291799c4d9b23cf Mon Sep 17 00:00:00 2001 From: Mikhail Svetkin Date: Tue, 20 Mar 2018 14:03:54 +0100 Subject: rtems: Fix pcre2 build (madvise undefined) RTEMS does not have madvise. We can use only posix_madvise Change-Id: Ia18b7cd2d7f9db84331f7e2350d060b9e85b30c8 Reviewed-by: Volker Hilsheimer --- .../0001-fix-rtems-build-undefine-madvise.patch | 28 ++++++++++++++++++++++ src/3rdparty/pcre2/src/sljit/sljitUtils.c | 2 +- 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 src/3rdparty/pcre2/patches/0001-fix-rtems-build-undefine-madvise.patch (limited to 'src') diff --git a/src/3rdparty/pcre2/patches/0001-fix-rtems-build-undefine-madvise.patch b/src/3rdparty/pcre2/patches/0001-fix-rtems-build-undefine-madvise.patch new file mode 100644 index 0000000000..074b39df85 --- /dev/null +++ b/src/3rdparty/pcre2/patches/0001-fix-rtems-build-undefine-madvise.patch @@ -0,0 +1,28 @@ +From ac10063196685fe6124055feb1275e13a78f562e Mon Sep 17 00:00:00 2001 +From: Mikhail Svetkin +Date: Tue, 20 Mar 2018 14:03:54 +0100 +Subject: [PATCH] rtems: Fix pcre2 build (madvise undefined) + +RTEMS does not have madvise. We can use only posix_madvise + +Change-Id: Ia18b7cd2d7f9db84331f7e2350d060b9e85b30c8 +--- + src/3rdparty/pcre2/src/sljit/sljitUtils.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/3rdparty/pcre2/src/sljit/sljitUtils.c b/src/3rdparty/pcre2/src/sljit/sljitUtils.c +index 5c2a838932..2ead044b1b 100644 +--- a/src/3rdparty/pcre2/src/sljit/sljitUtils.c ++++ b/src/3rdparty/pcre2/src/sljit/sljitUtils.c +@@ -315,7 +315,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_u8 *SLJIT_FUNC sljit_stack_resize(struct sljit_st + aligned_new_start = (sljit_uw)new_start & ~sljit_page_align; + aligned_old_start = ((sljit_uw)stack->start) & ~sljit_page_align; + /* If madvise is available, we release the unnecessary space. */ +-#if defined(MADV_DONTNEED) ++#if defined(MADV_DONTNEED) && !defined(__rtems__) + if (aligned_new_start > aligned_old_start) + madvise((void*)aligned_old_start, aligned_new_start - aligned_old_start, MADV_DONTNEED); + #elif defined(POSIX_MADV_DONTNEED) +-- +2.21.0 + diff --git a/src/3rdparty/pcre2/src/sljit/sljitUtils.c b/src/3rdparty/pcre2/src/sljit/sljitUtils.c index 5c2a838932..2ead044b1b 100644 --- a/src/3rdparty/pcre2/src/sljit/sljitUtils.c +++ b/src/3rdparty/pcre2/src/sljit/sljitUtils.c @@ -315,7 +315,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_u8 *SLJIT_FUNC sljit_stack_resize(struct sljit_st aligned_new_start = (sljit_uw)new_start & ~sljit_page_align; aligned_old_start = ((sljit_uw)stack->start) & ~sljit_page_align; /* If madvise is available, we release the unnecessary space. */ -#if defined(MADV_DONTNEED) +#if defined(MADV_DONTNEED) && !defined(__rtems__) if (aligned_new_start > aligned_old_start) madvise((void*)aligned_old_start, aligned_new_start - aligned_old_start, MADV_DONTNEED); #elif defined(POSIX_MADV_DONTNEED) -- cgit v1.2.3 From b3cc9403c4f7814d3e14915fdacee42b3a805073 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Mon, 20 May 2019 17:40:12 +0200 Subject: QTextMarkdownWriter: write fenced code blocks with language declaration MD4C now makes it possible to detect indented and fenced code blocks: https://github.com/mity/md4c/issues/81 Fenced code blocks have the advantages of being easier to write by hand, and having an "info string" following the opening fence, which is commonly used to declare the language. Also, the HTML parser now recognizes tags of the form
    which is one convention for declaring the programming language
    (as opposed to human language, for which the lang attribute would be used):
    https://stackoverflow.com/questions/5134242/semantics-standards-and-using-the-lang-attribute-for-source-code-in-markup
    So it's possible to read HTML and write markdown without losing this information.
    
    It's also possible to read markdown with any type of code block:
    fenced with ``` or ~~~, or indented, and rewrite it the same way.
    
    Change-Id: I33c2bf7d7b66c8f3ba5bdd41ab32572f09349c47
    Reviewed-by: Gatis Paeglis 
    ---
     src/gui/text/qtextformat.cpp           |  3 ++
     src/gui/text/qtextformat.h             |  1 +
     src/gui/text/qtexthtmlparser.cpp       |  4 ++
     src/gui/text/qtextmarkdownimporter.cpp |  8 +++-
     src/gui/text/qtextmarkdownimporter_p.h |  1 +
     src/gui/text/qtextmarkdownwriter.cpp   | 68 ++++++++++++++++++++++++++++++----
     src/gui/text/qtextmarkdownwriter_p.h   |  5 ++-
     7 files changed, 79 insertions(+), 11 deletions(-)
    
    (limited to 'src')
    
    diff --git a/src/gui/text/qtextformat.cpp b/src/gui/text/qtextformat.cpp
    index 644dd5558d..090c6cc4ce 100644
    --- a/src/gui/text/qtextformat.cpp
    +++ b/src/gui/text/qtextformat.cpp
    @@ -564,6 +564,9 @@ Q_GUI_EXPORT QDataStream &operator>>(QDataStream &stream, QTextFormat &fmt)
         \value BlockTrailingHorizontalRulerWidth The width of a horizontal ruler element.
         \value HeadingLevel     The level of a heading, for example 1 corresponds to an HTML H1 tag; otherwise 0.
                                 This enum value has been added in Qt 5.12.
    +    \value BlockCodeFence   The character that was used in the "fences" around a Markdown code block.
    +                            If the code block was indented rather than fenced, the block should not have this property.
    +                            This enum value has been added in Qt 5.14.
     
         \value BlockQuoteLevel  The depth of nested quoting on this block: 1 means the block is a top-level block quote.
                                 Blocks that are not block quotes should not have this property.
    diff --git a/src/gui/text/qtextformat.h b/src/gui/text/qtextformat.h
    index 4f534fb65d..a91461dcae 100644
    --- a/src/gui/text/qtextformat.h
    +++ b/src/gui/text/qtextformat.h
    @@ -178,6 +178,7 @@ public:
             HeadingLevel = 0x1070,
             BlockQuoteLevel = 0x1080,
             BlockCodeLanguage = 0x1090,
    +        BlockCodeFence = 0x1091,
             BlockMarker = 0x10A0,
     
             // character properties
    diff --git a/src/gui/text/qtexthtmlparser.cpp b/src/gui/text/qtexthtmlparser.cpp
    index 49ee6394ee..642f0893b4 100644
    --- a/src/gui/text/qtexthtmlparser.cpp
    +++ b/src/gui/text/qtexthtmlparser.cpp
    @@ -1635,6 +1635,10 @@ void QTextHtmlParser::applyAttributes(const QStringList &attributes)
                     else if (key == QLatin1String("type"))
                         linkType = value;
                     break;
    +            case Html_pre:
    +                if (key == QLatin1String("class") && value.startsWith(QLatin1String("language-")))
    +                    node->blockFormat.setProperty(QTextFormat::BlockCodeLanguage, value.mid(9));
    +                break;
                 default:
                     break;
             }
    diff --git a/src/gui/text/qtextmarkdownimporter.cpp b/src/gui/text/qtextmarkdownimporter.cpp
    index 223eb01e55..8a9bb3953c 100644
    --- a/src/gui/text/qtextmarkdownimporter.cpp
    +++ b/src/gui/text/qtextmarkdownimporter.cpp
    @@ -165,12 +165,13 @@ int QTextMarkdownImporter::cbEnterBlock(int blockType, void *det)
             MD_BLOCK_CODE_DETAIL *detail = static_cast(det);
             m_codeBlock = true;
             m_blockCodeLanguage = QLatin1String(detail->lang.text, int(detail->lang.size));
    +        m_blockCodeFence = detail->fence_char;
             QString info = QLatin1String(detail->info.text, int(detail->info.size));
             m_needsInsertBlock = true;
             if (m_blockQuoteDepth)
    -            qCDebug(lcMD, "CODE lang '%s' info '%s' inside QUOTE %d", qPrintable(m_blockCodeLanguage), qPrintable(info), m_blockQuoteDepth);
    +            qCDebug(lcMD, "CODE lang '%s' info '%s' fenced with '%c' inside QUOTE %d", qPrintable(m_blockCodeLanguage), qPrintable(info), m_blockCodeFence, m_blockQuoteDepth);
             else
    -            qCDebug(lcMD, "CODE lang '%s' info '%s'", qPrintable(m_blockCodeLanguage), qPrintable(info));
    +            qCDebug(lcMD, "CODE lang '%s' info '%s' fenced with '%c'", qPrintable(m_blockCodeLanguage), qPrintable(info), m_blockCodeFence);
         } break;
         case MD_BLOCK_H: {
             MD_BLOCK_H_DETAIL *detail = static_cast(det);
    @@ -326,6 +327,7 @@ int QTextMarkdownImporter::cbLeaveBlock(int blockType, void *detail)
         case MD_BLOCK_CODE: {
             m_codeBlock = false;
             m_blockCodeLanguage.clear();
    +        m_blockCodeFence = 0;
             if (m_blockQuoteDepth)
                 qCDebug(lcMD, "CODE ended inside QUOTE %d", m_blockQuoteDepth);
             else
    @@ -540,6 +542,8 @@ void QTextMarkdownImporter::insertBlock()
         }
         if (m_codeBlock) {
             blockFormat.setProperty(QTextFormat::BlockCodeLanguage, m_blockCodeLanguage);
    +        if (m_blockCodeFence)
    +            blockFormat.setProperty(QTextFormat::BlockCodeFence, QString(QLatin1Char(m_blockCodeFence)));
             charFormat.setFont(m_monoFont);
         } else {
             blockFormat.setTopMargin(m_paragraphMargin);
    diff --git a/src/gui/text/qtextmarkdownimporter_p.h b/src/gui/text/qtextmarkdownimporter_p.h
    index fdce74483b..1b8c2ca354 100644
    --- a/src/gui/text/qtextmarkdownimporter_p.h
    +++ b/src/gui/text/qtextmarkdownimporter_p.h
    @@ -124,6 +124,7 @@ private:
         int m_tableCol = -1; // because relative cell movements (e.g. m_cursor->movePosition(QTextCursor::NextCell)) don't work
         int m_paragraphMargin = 0;
         int m_blockType = 0;
    +    char m_blockCodeFence = 0;
         Features m_features;
         QTextImageFormat m_imageFormat;
         QTextListFormat m_listFormat;
    diff --git a/src/gui/text/qtextmarkdownwriter.cpp b/src/gui/text/qtextmarkdownwriter.cpp
    index 58e0c86b95..f351c8d20b 100644
    --- a/src/gui/text/qtextmarkdownwriter.cpp
    +++ b/src/gui/text/qtextmarkdownwriter.cpp
    @@ -134,6 +134,24 @@ void QTextMarkdownWriter::writeFrame(const QTextFrame *frame)
                 writeFrame(iterator.currentFrame());
             else { // no frame, it's a block
                 QTextBlock block = iterator.currentBlock();
    +            // Look ahead and detect some cases when we should
    +            // suppress needless blank lines, when there will be a big change in block format
    +            bool nextIsDifferent = false;
    +            bool ending = false;
    +            {
    +                QTextFrame::iterator next = iterator;
    +                ++next;
    +                if (next.atEnd()) {
    +                    nextIsDifferent = true;
    +                    ending = true;
    +                } else {
    +                    QTextBlockFormat format = iterator.currentBlock().blockFormat();
    +                    QTextBlockFormat nextFormat = next.currentBlock().blockFormat();
    +                    if (nextFormat.indent() != format.indent() ||
    +                            nextFormat.property(QTextFormat::BlockCodeLanguage) != format.property(QTextFormat::BlockCodeLanguage))
    +                        nextIsDifferent = true;
    +                }
    +            }
                 if (table) {
                     QTextTableCell cell = table->cellAt(block.position());
                     if (tableRow < cell.row()) {
    @@ -150,7 +168,7 @@ void QTextMarkdownWriter::writeFrame(const QTextFrame *frame)
                     if (lastWasList)
                         m_stream << Newline;
                 }
    -            int endingCol = writeBlock(block, !table, table && tableRow == 0);
    +            int endingCol = writeBlock(block, !table, table && tableRow == 0, nextIsDifferent);
                 m_doubleNewlineWritten = false;
                 if (table) {
                     QTextTableCell cell = table->cellAt(block.position());
    @@ -162,11 +180,19 @@ void QTextMarkdownWriter::writeFrame(const QTextFrame *frame)
                         m_stream << QString(paddingLen, Space);
                     for (int col = cell.column(); col < spanEndCol; ++col)
                         m_stream << "|";
    -            } else if (block.textList() || block.blockFormat().hasProperty(QTextFormat::BlockCodeLanguage)) {
    +            } else if (m_fencedCodeBlock && ending) {
    +                m_stream << m_linePrefix << QString(m_wrappedLineIndent, Space)
    +                         << m_codeBlockFence << Newline << Newline;
    +                m_codeBlockFence.clear();
    +            } else if (m_indentedCodeBlock && nextIsDifferent) {
                     m_stream << Newline;
                 } else if (endingCol > 0) {
    -                m_stream << Newline << Newline;
    -                m_doubleNewlineWritten = true;
    +                if (block.textList() || block.blockFormat().hasProperty(QTextFormat::BlockCodeLanguage)) {
    +                    m_stream << Newline;
    +                } else {
    +                    m_stream << Newline << Newline;
    +                    m_doubleNewlineWritten = true;
    +                }
                 }
                 lastWasList = block.textList();
             }
    @@ -259,11 +285,13 @@ static void maybeEscapeFirstChar(QString &s)
         }
     }
     
    -int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ignoreFormat)
    +int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ignoreFormat, bool ignoreEmpty)
     {
    +    if (block.text().isEmpty() && ignoreEmpty)
    +        return 0;
         const int ColumnLimit = 80;
         QTextBlockFormat blockFmt = block.blockFormat();
    -    bool indentedCodeBlock = false;
    +    bool missedBlankCodeBlockLine = false;
         if (block.textList()) { // it's a list-item
             auto fmt = block.textList()->format();
             const int listLevel = fmt.indent();
    @@ -324,7 +352,28 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign
         } else if (blockFmt.hasProperty(QTextFormat::BlockTrailingHorizontalRulerWidth)) {
             m_stream << "- - -\n"; // unambiguous horizontal rule, not an underline under a heading
             return 0;
    +    } else if (blockFmt.hasProperty(QTextFormat::BlockCodeFence) || blockFmt.stringProperty(QTextFormat::BlockCodeLanguage).length() > 0) {
    +        // It's important to preserve blank lines in code blocks.  But blank lines in code blocks
    +        // inside block quotes are getting preserved anyway (along with the "> " prefix).
    +        if (!blockFmt.hasProperty(QTextFormat::BlockQuoteLevel))
    +            missedBlankCodeBlockLine = true; // only if we don't get any fragments below
    +        if (!m_fencedCodeBlock) {
    +            QString fenceChar = blockFmt.stringProperty(QTextFormat::BlockCodeFence);
    +            if (fenceChar.isEmpty())
    +                fenceChar = QLatin1String("`");
    +            m_codeBlockFence = QString(3, fenceChar.at(0));
    +            // A block quote can contain an indented code block, but not vice-versa.
    +            m_stream << m_linePrefix << QString(m_wrappedLineIndent, Space) << m_codeBlockFence
    +                     << Space << blockFmt.stringProperty(QTextFormat::BlockCodeLanguage) << Newline;
    +            m_fencedCodeBlock = true;
    +        }
         } else if (!blockFmt.indent()) {
    +        if (m_fencedCodeBlock) {
    +            m_stream << m_linePrefix << QString(m_wrappedLineIndent, Space)
    +                     << m_codeBlockFence << Newline;
    +            m_fencedCodeBlock = false;
    +            m_codeBlockFence.clear();
    +        }
             m_wrappedLineIndent = 0;
             m_linePrefix.clear();
             if (blockFmt.hasProperty(QTextFormat::BlockQuoteLevel)) {
    @@ -337,7 +386,7 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign
             if (blockFmt.hasProperty(QTextFormat::BlockCodeLanguage)) {
                 // A block quote can contain an indented code block, but not vice-versa.
                 m_linePrefix += QString(4, Space);
    -            indentedCodeBlock = true;
    +            m_indentedCodeBlock = true;
             }
         }
         if (blockFmt.headingLevel())
    @@ -358,6 +407,7 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign
         bool strikeOut = false;
         QString backticks(Backtick);
         for (QTextBlock::Iterator frag = block.begin(); !frag.atEnd(); ++frag) {
    +        missedBlankCodeBlockLine = false;
             QString fragmentText = frag.fragment().text();
             while (fragmentText.endsWith(Newline))
                 fragmentText.chop(1);
    @@ -401,7 +451,7 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign
                 bool monoFrag = fontInfo.fixedPitch();
                 QString markers;
                 if (!ignoreFormat) {
    -                if (monoFrag != mono && !indentedCodeBlock) {
    +                if (monoFrag != mono && !m_indentedCodeBlock && !m_fencedCodeBlock) {
                         if (monoFrag)
                             backticks = QString(adjacentBackticksCount(fragmentText) + 1, Backtick);
                         markers += backticks;
    @@ -501,6 +551,8 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign
             m_stream << "~~";
             col += 2;
         }
    +    if (missedBlankCodeBlockLine)
    +        m_stream << Newline;
         return col;
     }
     
    diff --git a/src/gui/text/qtextmarkdownwriter_p.h b/src/gui/text/qtextmarkdownwriter_p.h
    index 96ceb445cd..90310250ac 100644
    --- a/src/gui/text/qtextmarkdownwriter_p.h
    +++ b/src/gui/text/qtextmarkdownwriter_p.h
    @@ -67,7 +67,7 @@ public:
         bool writeAll(const QTextDocument *document);
         void writeTable(const QAbstractItemModel *table);
     
    -    int writeBlock(const QTextBlock &block, bool table, bool ignoreFormat);
    +    int writeBlock(const QTextBlock &block, bool table, bool ignoreFormat, bool ignoreEmpty);
         void writeFrame(const QTextFrame *frame);
     
     private:
    @@ -82,9 +82,12 @@ private:
         QTextDocument::MarkdownFeatures m_features;
         QMap m_listInfo;
         QString m_linePrefix;
    +    QString m_codeBlockFence;
         int m_wrappedLineIndent = 0;
         int m_lastListIndent = 1;
         bool m_doubleNewlineWritten = false;
    +    bool m_indentedCodeBlock = false;
    +    bool m_fencedCodeBlock = false;
     };
     
     QT_END_NAMESPACE
    -- 
    cgit v1.2.3
    
    
    From 548513a4bd050d3df0a85fed6e2d1a00ce06d2ab Mon Sep 17 00:00:00 2001
    From: Edward Welbourne 
    Date: Mon, 27 May 2019 17:47:22 +0200
    Subject: Separate out the time, zone, date code from corelib/tools/
    
    We'll be adding calendar code here as well, and tools/ was getting
    rather crowded, so it looks like time to move out a reasonably
    coherent sub-bundle of it all.
    
    Change-Id: I7e8030f38c31aa307f519dd918a43fc44baa6aa1
    Reviewed-by: Lars Knoll 
    ---
     src/corelib/corelib.pro                        |    1 +
     src/corelib/time/qdatetime.cpp                 | 5685 ++++++++++++++++++++++++
     src/corelib/time/qdatetime.h                   |  426 ++
     src/corelib/time/qdatetime_p.h                 |  151 +
     src/corelib/time/qdatetimeparser.cpp           | 2047 +++++++++
     src/corelib/time/qdatetimeparser_p.h           |  310 ++
     src/corelib/time/qtimezone.cpp                 |  997 +++++
     src/corelib/time/qtimezone.h                   |  188 +
     src/corelib/time/qtimezoneprivate.cpp          |  926 ++++
     src/corelib/time/qtimezoneprivate_android.cpp  |  257 ++
     src/corelib/time/qtimezoneprivate_data_p.h     | 1257 ++++++
     src/corelib/time/qtimezoneprivate_icu.cpp      |  508 +++
     src/corelib/time/qtimezoneprivate_mac.mm       |  333 ++
     src/corelib/time/qtimezoneprivate_p.h          |  493 ++
     src/corelib/time/qtimezoneprivate_tz.cpp       | 1154 +++++
     src/corelib/time/qtimezoneprivate_win.cpp      |  927 ++++
     src/corelib/time/time.pri                      |   34 +
     src/corelib/tools/qdatetime.cpp                | 5685 ------------------------
     src/corelib/tools/qdatetime.h                  |  426 --
     src/corelib/tools/qdatetime_p.h                |  151 -
     src/corelib/tools/qdatetimeparser.cpp          | 2047 ---------
     src/corelib/tools/qdatetimeparser_p.h          |  310 --
     src/corelib/tools/qlocale.cpp                  |    2 +-
     src/corelib/tools/qtimezone.cpp                |  997 -----
     src/corelib/tools/qtimezone.h                  |  188 -
     src/corelib/tools/qtimezoneprivate.cpp         |  926 ----
     src/corelib/tools/qtimezoneprivate_android.cpp |  257 --
     src/corelib/tools/qtimezoneprivate_data_p.h    | 1257 ------
     src/corelib/tools/qtimezoneprivate_icu.cpp     |  508 ---
     src/corelib/tools/qtimezoneprivate_mac.mm      |  333 --
     src/corelib/tools/qtimezoneprivate_p.h         |  493 --
     src/corelib/tools/qtimezoneprivate_tz.cpp      | 1155 -----
     src/corelib/tools/qtimezoneprivate_win.cpp     |  927 ----
     src/corelib/tools/tools.pri                    |   30 -
     src/tools/bootstrap/bootstrap.pro              |    2 +-
     35 files changed, 15696 insertions(+), 15692 deletions(-)
     create mode 100644 src/corelib/time/qdatetime.cpp
     create mode 100644 src/corelib/time/qdatetime.h
     create mode 100644 src/corelib/time/qdatetime_p.h
     create mode 100644 src/corelib/time/qdatetimeparser.cpp
     create mode 100644 src/corelib/time/qdatetimeparser_p.h
     create mode 100644 src/corelib/time/qtimezone.cpp
     create mode 100644 src/corelib/time/qtimezone.h
     create mode 100644 src/corelib/time/qtimezoneprivate.cpp
     create mode 100644 src/corelib/time/qtimezoneprivate_android.cpp
     create mode 100644 src/corelib/time/qtimezoneprivate_data_p.h
     create mode 100644 src/corelib/time/qtimezoneprivate_icu.cpp
     create mode 100644 src/corelib/time/qtimezoneprivate_mac.mm
     create mode 100644 src/corelib/time/qtimezoneprivate_p.h
     create mode 100644 src/corelib/time/qtimezoneprivate_tz.cpp
     create mode 100644 src/corelib/time/qtimezoneprivate_win.cpp
     create mode 100644 src/corelib/time/time.pri
     delete mode 100644 src/corelib/tools/qdatetime.cpp
     delete mode 100644 src/corelib/tools/qdatetime.h
     delete mode 100644 src/corelib/tools/qdatetime_p.h
     delete mode 100644 src/corelib/tools/qdatetimeparser.cpp
     delete mode 100644 src/corelib/tools/qdatetimeparser_p.h
     delete mode 100644 src/corelib/tools/qtimezone.cpp
     delete mode 100644 src/corelib/tools/qtimezone.h
     delete mode 100644 src/corelib/tools/qtimezoneprivate.cpp
     delete mode 100644 src/corelib/tools/qtimezoneprivate_android.cpp
     delete mode 100644 src/corelib/tools/qtimezoneprivate_data_p.h
     delete mode 100644 src/corelib/tools/qtimezoneprivate_icu.cpp
     delete mode 100644 src/corelib/tools/qtimezoneprivate_mac.mm
     delete mode 100644 src/corelib/tools/qtimezoneprivate_p.h
     delete mode 100644 src/corelib/tools/qtimezoneprivate_tz.cpp
     delete mode 100644 src/corelib/tools/qtimezoneprivate_win.cpp
    
    (limited to 'src')
    
    diff --git a/src/corelib/corelib.pro b/src/corelib/corelib.pro
    index 6babbac8f5..521f840292 100644
    --- a/src/corelib/corelib.pro
    +++ b/src/corelib/corelib.pro
    @@ -36,6 +36,7 @@ qtConfig(animation): include(animation/animation.pri)
     include(global/global.pri)
     include(thread/thread.pri)
     include(tools/tools.pri)
    +include(time/time.pri)
     include(io/io.pri)
     include(itemmodels/itemmodels.pri)
     include(plugin/plugin.pri)
    diff --git a/src/corelib/time/qdatetime.cpp b/src/corelib/time/qdatetime.cpp
    new file mode 100644
    index 0000000000..9220d210f1
    --- /dev/null
    +++ b/src/corelib/time/qdatetime.cpp
    @@ -0,0 +1,5685 @@
    +/****************************************************************************
    +**
    +** Copyright (C) 2019 The Qt Company Ltd.
    +** Copyright (C) 2016 Intel Corporation.
    +** Contact: https://www.qt.io/licensing/
    +**
    +** This file is part of the QtCore module of the Qt Toolkit.
    +**
    +** $QT_BEGIN_LICENSE:LGPL$
    +** Commercial License Usage
    +** Licensees holding valid commercial Qt licenses may use this file in
    +** accordance with the commercial license agreement provided with the
    +** Software or, alternatively, in accordance with the terms contained in
    +** a written agreement between you and The Qt Company. For licensing terms
    +** and conditions see https://www.qt.io/terms-conditions. For further
    +** information use the contact form at https://www.qt.io/contact-us.
    +**
    +** GNU Lesser General Public License Usage
    +** Alternatively, this file may be used under the terms of the GNU Lesser
    +** General Public License version 3 as published by the Free Software
    +** Foundation and appearing in the file LICENSE.LGPL3 included in the
    +** packaging of this file. Please review the following information to
    +** ensure the GNU Lesser General Public License version 3 requirements
    +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
    +**
    +** GNU General Public License Usage
    +** Alternatively, this file may be used under the terms of the GNU
    +** General Public License version 2.0 or (at your option) the GNU General
    +** Public license version 3 or any later version approved by the KDE Free
    +** Qt Foundation. The licenses are as published by the Free Software
    +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
    +** included in the packaging of this file. Please review the following
    +** information to ensure the GNU General Public License requirements will
    +** be met: https://www.gnu.org/licenses/gpl-2.0.html and
    +** https://www.gnu.org/licenses/gpl-3.0.html.
    +**
    +** $QT_END_LICENSE$
    +**
    +****************************************************************************/
    +
    +#include "qplatformdefs.h"
    +#include "private/qdatetime_p.h"
    +#if QT_CONFIG(datetimeparser)
    +#include "private/qdatetimeparser_p.h"
    +#endif
    +
    +#include "qdatastream.h"
    +#include "qset.h"
    +#include "qlocale.h"
    +#include "qdatetime.h"
    +#if QT_CONFIG(timezone)
    +#include "qtimezoneprivate_p.h"
    +#endif
    +#include "qregexp.h"
    +#include "qdebug.h"
    +#ifndef Q_OS_WIN
    +#include 
    +#endif
    +
    +#include 
    +#ifdef Q_CC_MINGW
    +#  include  // Define _POSIX_THREAD_SAFE_FUNCTIONS to obtain localtime_r()
    +#endif
    +#include 
    +#ifdef Q_OS_WIN
    +#  include 
    +#  ifdef Q_OS_WINRT
    +#    include "qfunctions_winrt.h"
    +#  endif
    +#endif
    +
    +#if defined(Q_OS_MAC)
    +#include 
    +#endif
    +
    +QT_BEGIN_NAMESPACE
    +
    +/*****************************************************************************
    +  Date/Time Constants
    + *****************************************************************************/
    +
    +enum {
    +    SECS_PER_DAY = 86400,
    +    MSECS_PER_DAY = 86400000,
    +    SECS_PER_HOUR = 3600,
    +    MSECS_PER_HOUR = 3600000,
    +    SECS_PER_MIN = 60,
    +    MSECS_PER_MIN = 60000,
    +    TIME_T_MAX = 2145916799,  // int maximum 2037-12-31T23:59:59 UTC
    +    JULIAN_DAY_FOR_EPOCH = 2440588 // result of julianDayFromDate(1970, 1, 1)
    +};
    +
    +/*****************************************************************************
    +  QDate static helper functions
    + *****************************************************************************/
    +
    +static inline QDate fixedDate(int y, int m, int d)
    +{
    +    QDate result(y, m, 1);
    +    result.setDate(y, m, qMin(d, result.daysInMonth()));
    +    return result;
    +}
    +
    +/*
    +  Division, rounding down (rather than towards zero).
    +
    +  From C++11 onwards, integer division is defined to round towards zero, so we
    +  can rely on that when implementing this.  This is only used with denominator b
    +  > 0, so we only have to treat negative numerator, a, specially.
    + */
    +static inline qint64 floordiv(qint64 a, int b)
    +{
    +    return (a - (a < 0 ? b - 1 : 0)) / b;
    +}
    +
    +static inline int floordiv(int a, int b)
    +{
    +    return (a - (a < 0 ? b - 1 : 0)) / b;
    +}
    +
    +static inline qint64 julianDayFromDate(int year, int month, int day)
    +{
    +    // Adjust for no year 0
    +    if (year < 0)
    +        ++year;
    +
    +/*
    + * Math from The Calendar FAQ at http://www.tondering.dk/claus/cal/julperiod.php
    + * This formula is correct for all julian days, when using mathematical integer
    + * division (round to negative infinity), not c++11 integer division (round to zero)
    + */
    +    int    a = floordiv(14 - month, 12);
    +    qint64 y = (qint64)year + 4800 - a;
    +    int    m = month + 12 * a - 3;
    +    return day + floordiv(153 * m + 2, 5) + 365 * y + floordiv(y, 4) - floordiv(y, 100) + floordiv(y, 400) - 32045;
    +}
    +
    +struct ParsedDate
    +{
    +    int year, month, day;
    +};
    +
    +// prevent this function from being inlined into all 10 users
    +Q_NEVER_INLINE
    +static ParsedDate getDateFromJulianDay(qint64 julianDay)
    +{
    +/*
    + * Math from The Calendar FAQ at http://www.tondering.dk/claus/cal/julperiod.php
    + * This formula is correct for all julian days, when using mathematical integer
    + * division (round to negative infinity), not c++11 integer division (round to zero)
    + */
    +    qint64 a = julianDay + 32044;
    +    qint64 b = floordiv(4 * a + 3, 146097);
    +    int    c = a - floordiv(146097 * b, 4);
    +
    +    int    d = floordiv(4 * c + 3, 1461);
    +    int    e = c - floordiv(1461 * d, 4);
    +    int    m = floordiv(5 * e + 2, 153);
    +
    +    int    day = e - floordiv(153 * m + 2, 5) + 1;
    +    int    month = m + 3 - 12 * floordiv(m, 10);
    +    int    year = 100 * b + d - 4800 + floordiv(m, 10);
    +
    +    // Adjust for no year 0
    +    if (year <= 0)
    +        --year ;
    +
    +    return { year, month, day };
    +}
    +
    +/*****************************************************************************
    +  Date/Time formatting helper functions
    + *****************************************************************************/
    +
    +#if QT_CONFIG(textdate)
    +static const char qt_shortMonthNames[][4] = {
    +    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
    +    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
    +};
    +
    +static int qt_monthNumberFromShortName(QStringRef shortName)
    +{
    +    for (unsigned int i = 0; i < sizeof(qt_shortMonthNames) / sizeof(qt_shortMonthNames[0]); ++i) {
    +        if (shortName == QLatin1String(qt_shortMonthNames[i], 3))
    +            return i + 1;
    +    }
    +    return -1;
    +}
    +static int qt_monthNumberFromShortName(const QString &shortName)
    +{ return qt_monthNumberFromShortName(QStringRef(&shortName)); }
    +
    +static int fromShortMonthName(const QStringRef &monthName)
    +{
    +    // Assume that English monthnames are the default
    +    int month = qt_monthNumberFromShortName(monthName);
    +    if (month != -1)
    +        return month;
    +    // If English names can't be found, search the localized ones
    +    for (int i = 1; i <= 12; ++i) {
    +        if (monthName == QLocale::system().monthName(i, QLocale::ShortFormat))
    +            return i;
    +    }
    +    return -1;
    +}
    +#endif // textdate
    +
    +#if QT_CONFIG(datestring)
    +struct ParsedRfcDateTime {
    +    QDate date;
    +    QTime time;
    +    int utcOffset;
    +};
    +
    +static ParsedRfcDateTime rfcDateImpl(const QString &s)
    +{
    +    ParsedRfcDateTime result;
    +
    +    // Matches "Wdy, dd Mon yyyy HH:mm:ss ±hhmm" (Wdy, being optional)
    +    QRegExp rex(QStringLiteral("^(?:[A-Z][a-z]+,)?[ \\t]*(\\d{1,2})[ \\t]+([A-Z][a-z]+)[ \\t]+(\\d\\d\\d\\d)(?:[ \\t]+(\\d\\d):(\\d\\d)(?::(\\d\\d))?)?[ \\t]*(?:([+-])(\\d\\d)(\\d\\d))?"));
    +    if (s.indexOf(rex) == 0) {
    +        const QStringList cap = rex.capturedTexts();
    +        result.date = QDate(cap[3].toInt(), qt_monthNumberFromShortName(cap[2]), cap[1].toInt());
    +        if (!cap[4].isEmpty())
    +            result.time = QTime(cap[4].toInt(), cap[5].toInt(), cap[6].toInt());
    +        const bool positiveOffset = (cap[7] == QLatin1String("+"));
    +        const int hourOffset = cap[8].toInt();
    +        const int minOffset = cap[9].toInt();
    +        result.utcOffset = ((hourOffset * 60 + minOffset) * (positiveOffset ? 60 : -60));
    +    } else {
    +        // Matches "Wdy Mon dd HH:mm:ss yyyy"
    +        QRegExp rex(QStringLiteral("^[A-Z][a-z]+[ \\t]+([A-Z][a-z]+)[ \\t]+(\\d\\d)(?:[ \\t]+(\\d\\d):(\\d\\d):(\\d\\d))?[ \\t]+(\\d\\d\\d\\d)[ \\t]*(?:([+-])(\\d\\d)(\\d\\d))?"));
    +        if (s.indexOf(rex) == 0) {
    +            const QStringList cap = rex.capturedTexts();
    +            result.date = QDate(cap[6].toInt(), qt_monthNumberFromShortName(cap[1]), cap[2].toInt());
    +            if (!cap[3].isEmpty())
    +                result.time = QTime(cap[3].toInt(), cap[4].toInt(), cap[5].toInt());
    +            const bool positiveOffset = (cap[7] == QLatin1String("+"));
    +            const int hourOffset = cap[8].toInt();
    +            const int minOffset = cap[9].toInt();
    +            result.utcOffset = ((hourOffset * 60 + minOffset) * (positiveOffset ? 60 : -60));
    +        }
    +    }
    +
    +    return result;
    +}
    +#endif // datestring
    +
    +// Return offset in [+-]HH:mm format
    +static QString toOffsetString(Qt::DateFormat format, int offset)
    +{
    +    return QString::asprintf("%c%02d%s%02d",
    +                             offset >= 0 ? '+' : '-',
    +                             qAbs(offset) / SECS_PER_HOUR,
    +                             // Qt::ISODate puts : between the hours and minutes, but Qt:TextDate does not:
    +                             format == Qt::TextDate ? "" : ":",
    +                             (qAbs(offset) / 60) % 60);
    +}
    +
    +#if QT_CONFIG(datestring)
    +// Parse offset in [+-]HH[[:]mm] format
    +static int fromOffsetString(const QStringRef &offsetString, bool *valid) noexcept
    +{
    +    *valid = false;
    +
    +    const int size = offsetString.size();
    +    if (size < 2 || size > 6)
    +        return 0;
    +
    +    // sign will be +1 for a positive and -1 for a negative offset
    +    int sign;
    +
    +    // First char must be + or -
    +    const QChar signChar = offsetString.at(0);
    +    if (signChar == QLatin1Char('+'))
    +        sign = 1;
    +    else if (signChar == QLatin1Char('-'))
    +        sign = -1;
    +    else
    +        return 0;
    +
    +    // Split the hour and minute parts
    +    const QStringRef time = offsetString.mid(1);
    +    int hhLen = time.indexOf(QLatin1Char(':'));
    +    int mmIndex;
    +    if (hhLen == -1)
    +        mmIndex = hhLen = 2; // [+-]HHmm or [+-]HH format
    +    else
    +        mmIndex = hhLen + 1;
    +
    +    const QStringRef hhRef = time.left(hhLen);
    +    bool ok = false;
    +    const int hour = hhRef.toInt(&ok);
    +    if (!ok)
    +        return 0;
    +
    +    const QStringRef mmRef = time.mid(mmIndex);
    +    const int minute = mmRef.isEmpty() ? 0 : mmRef.toInt(&ok);
    +    if (!ok || minute < 0 || minute > 59)
    +        return 0;
    +
    +    *valid = true;
    +    return sign * ((hour * 60) + minute) * 60;
    +}
    +#endif // datestring
    +
    +static constexpr int daysInUsualMonth(int month) // (February isn't usual.)
    +{
    +    // Long if odd up to July = 7, or if even from 8 = August onwards:
    +    return Q_ASSERT(month != 2 && month > 0 && month <= 12), 30 | ((month & 1) ^ (month >> 3));
    +}
    +
    +/*****************************************************************************
    +  QDate member functions
    + *****************************************************************************/
    +
    +/*!
    +    \since 4.5
    +
    +    \enum QDate::MonthNameType
    +
    +    This enum describes the types of the string representation used
    +    for the month name.
    +
    +    \value DateFormat This type of name can be used for date-to-string formatting.
    +    \value StandaloneFormat This type is used when you need to enumerate months or weekdays.
    +           Usually standalone names are represented in singular forms with
    +           capitalized first letter.
    +*/
    +
    +/*!
    +    \class QDate
    +    \inmodule QtCore
    +    \reentrant
    +    \brief The QDate class provides date functions.
    +
    +
    +    A QDate object encodes a calendar date, i.e. year, month, and day numbers,
    +    in the proleptic Gregorian calendar by default. It can read the current date
    +    from the system clock. It provides functions for comparing dates, and for
    +    manipulating dates. For example, it is possible to add and subtract days,
    +    months, and years to dates.
    +
    +    A QDate object is typically created by giving the year, month, and day
    +    numbers explicitly. Note that QDate interprets two digit years as presented,
    +    i.e., as years 0 through 99, without adding any offset.  A QDate can also be
    +    constructed with the static function currentDate(), which creates a QDate
    +    object containing the system clock's date.  An explicit date can also be set
    +    using setDate(). The fromString() function returns a QDate given a string
    +    and a date format which is used to interpret the date within the string.
    +
    +    The year(), month(), and day() functions provide access to the
    +    year, month, and day numbers. Also, dayOfWeek() and dayOfYear()
    +    functions are provided. The same information is provided in
    +    textual format by the toString(), shortDayName(), longDayName(),
    +    shortMonthName(), and longMonthName() functions.
    +
    +    QDate provides a full set of operators to compare two QDate
    +    objects where smaller means earlier, and larger means later.
    +
    +    You can increment (or decrement) a date by a given number of days
    +    using addDays(). Similarly you can use addMonths() and addYears().
    +    The daysTo() function returns the number of days between two
    +    dates.
    +
    +    The daysInMonth() and daysInYear() functions return how many days
    +    there are in this date's month and year, respectively. The
    +    isLeapYear() function indicates whether a date is in a leap year.
    +
    +    \section1 Remarks
    +
    +    \section2 No Year 0
    +
    +    There is no year 0. Dates in that year are considered invalid. The year -1
    +    is the year "1 before Christ" or "1 before current era." The day before 1
    +    January 1 CE, QDate(1, 1, 1), is 31 December 1 BCE, QDate(-1, 12, 31).
    +
    +    \section2 Range of Valid Dates
    +
    +    Dates are stored internally as a Julian Day number, an integer count of
    +    every day in a contiguous range, with 24 November 4714 BCE in the Gregorian
    +    calendar being Julian Day 0 (1 January 4713 BCE in the Julian calendar).
    +    As well as being an efficient and accurate way of storing an absolute date,
    +    it is suitable for converting a Date into other calendar systems such as
    +    Hebrew, Islamic or Chinese. The Julian Day number can be obtained using
    +    QDate::toJulianDay() and can be set using QDate::fromJulianDay().
    +
    +    The range of dates able to be stored by QDate as a Julian Day number is
    +    for technical reasons limited to between -784350574879 and 784354017364,
    +    which means from before 2 billion BCE to after 2 billion CE.
    +
    +    \sa QTime, QDateTime, QDateEdit, QDateTimeEdit, QCalendarWidget
    +*/
    +
    +/*!
    +    \fn QDate::QDate()
    +
    +    Constructs a null date. Null dates are invalid.
    +
    +    \sa isNull(), isValid()
    +*/
    +
    +/*!
    +    Constructs a date with year \a y, month \a m and day \a d.
    +
    +    If the specified date is invalid, the date is not set and
    +    isValid() returns \c false.
    +
    +    \warning Years 1 to 99 are interpreted as is. Year 0 is invalid.
    +
    +    \sa isValid()
    +*/
    +
    +QDate::QDate(int y, int m, int d)
    +{
    +    setDate(y, m, d);
    +}
    +
    +
    +/*!
    +    \fn bool QDate::isNull() const
    +
    +    Returns \c true if the date is null; otherwise returns \c false. A null
    +    date is invalid.
    +
    +    \note The behavior of this function is equivalent to isValid().
    +
    +    \sa isValid()
    +*/
    +
    +/*!
    +    \fn bool QDate::isValid() const
    +
    +    Returns \c true if this date is valid; otherwise returns \c false.
    +
    +    \sa isNull()
    +*/
    +
    +/*!
    +    Returns the year of this date. Negative numbers indicate years
    +    before 1 CE, such that year -44 is 44 BCE.
    +
    +    Returns 0 if the date is invalid.
    +
    +    \sa month(), day()
    +*/
    +
    +int QDate::year() const
    +{
    +    if (isNull())
    +        return 0;
    +
    +    return getDateFromJulianDay(jd).year;
    +}
    +
    +/*!
    +    Returns the number corresponding to the month of this date, using
    +    the following convention:
    +
    +    \list
    +    \li 1 = "January"
    +    \li 2 = "February"
    +    \li 3 = "March"
    +    \li 4 = "April"
    +    \li 5 = "May"
    +    \li 6 = "June"
    +    \li 7 = "July"
    +    \li 8 = "August"
    +    \li 9 = "September"
    +    \li 10 = "October"
    +    \li 11 = "November"
    +    \li 12 = "December"
    +    \endlist
    +
    +    Returns 0 if the date is invalid.
    +
    +    \sa year(), day()
    +*/
    +
    +int QDate::month() const
    +{
    +    if (isNull())
    +        return 0;
    +
    +    return getDateFromJulianDay(jd).month;
    +}
    +
    +/*!
    +    Returns the day of the month (1 to 31) of this date.
    +
    +    Returns 0 if the date is invalid.
    +
    +    \sa year(), month(), dayOfWeek()
    +*/
    +
    +int QDate::day() const
    +{
    +    if (isNull())
    +        return 0;
    +
    +    return getDateFromJulianDay(jd).day;
    +}
    +
    +/*!
    +    Returns the weekday (1 = Monday to 7 = Sunday) for this date.
    +
    +    Returns 0 if the date is invalid.
    +
    +    \sa day(), dayOfYear(), Qt::DayOfWeek
    +*/
    +
    +int QDate::dayOfWeek() const
    +{
    +    if (isNull())
    +        return 0;
    +
    +    if (jd >= 0)
    +        return (jd % 7) + 1;
    +    else
    +        return ((jd + 1) % 7) + 7;
    +}
    +
    +/*!
    +    Returns the day of the year (1 to 365 or 366 on leap years) for
    +    this date.
    +
    +    Returns 0 if the date is invalid.
    +
    +    \sa day(), dayOfWeek()
    +*/
    +
    +int QDate::dayOfYear() const
    +{
    +    if (isNull())
    +        return 0;
    +
    +    return jd - julianDayFromDate(year(), 1, 1) + 1;
    +}
    +
    +/*!
    +    Returns the number of days in the month (28 to 31) for this date.
    +
    +    Returns 0 if the date is invalid.
    +
    +    \sa day(), daysInYear()
    +*/
    +
    +int QDate::daysInMonth() const
    +{
    +    if (isNull())
    +        return 0;
    +
    +    const ParsedDate pd = getDateFromJulianDay(jd);
    +    if (pd.month == 2)
    +        return isLeapYear(pd.year) ? 29 : 28;
    +
    +    return daysInUsualMonth(pd.month);
    +}
    +
    +/*!
    +    Returns the number of days in the year (365 or 366) for this date.
    +
    +    Returns 0 if the date is invalid.
    +
    +    \sa day(), daysInMonth()
    +*/
    +
    +int QDate::daysInYear() const
    +{
    +    if (isNull())
    +        return 0;
    +
    +    return isLeapYear(getDateFromJulianDay(jd).year) ? 366 : 365;
    +}
    +
    +/*!
    +    Returns the week number (1 to 53), and stores the year in
    +    *\a{yearNumber} unless \a yearNumber is null (the default).
    +
    +    Returns 0 if the date is invalid.
    +
    +    In accordance with ISO 8601, weeks start on Monday and the first
    +    Thursday of a year is always in week 1 of that year. Most years
    +    have 52 weeks, but some have 53.
    +
    +    *\a{yearNumber} is not always the same as year(). For example, 1
    +    January 2000 has week number 52 in the year 1999, and 31 December
    +    2002 has week number 1 in the year 2003.
    +
    +    \sa isValid()
    +*/
    +
    +int QDate::weekNumber(int *yearNumber) const
    +{
    +    if (!isValid())
    +        return 0;
    +
    +    int year = QDate::year();
    +    int yday = dayOfYear();
    +    int wday = dayOfWeek();
    +
    +    int week = (yday - wday + 10) / 7;
    +
    +    if (week == 0) {
    +        // last week of previous year
    +        --year;
    +        week = (yday + 365 + (QDate::isLeapYear(year) ? 1 : 0) - wday + 10) / 7;
    +        Q_ASSERT(week == 52 || week == 53);
    +    } else if (week == 53) {
    +        // maybe first week of next year
    +        int w = (yday - 365 - (QDate::isLeapYear(year) ? 1 : 0) - wday + 10) / 7;
    +        if (w > 0) {
    +            ++year;
    +            week = w;
    +        }
    +        Q_ASSERT(week == 53 || week == 1);
    +    }
    +
    +    if (yearNumber != 0)
    +        *yearNumber = year;
    +    return week;
    +}
    +
    +static bool inDateTimeRange(qint64 jd, bool start)
    +{
    +    using Bounds = std::numeric_limits;
    +    if (jd < Bounds::min() + JULIAN_DAY_FOR_EPOCH)
    +        return false;
    +    jd -= JULIAN_DAY_FOR_EPOCH;
    +    const qint64 maxDay = Bounds::max() / MSECS_PER_DAY;
    +    const qint64 minDay = Bounds::min() / MSECS_PER_DAY - 1;
    +    // (Divisions rounded towards zero, as MSECS_PER_DAY has factors other than two.)
    +    // Range includes start of last day and end of first:
    +    if (start)
    +        return jd > minDay && jd <= maxDay;
    +    return jd >= minDay && jd < maxDay;
    +}
    +
    +static QDateTime toEarliest(const QDate &day, const QDateTime &form)
    +{
    +    const Qt::TimeSpec spec = form.timeSpec();
    +    const int offset = (spec == Qt::OffsetFromUTC) ? form.offsetFromUtc() : 0;
    +#if QT_CONFIG(timezone)
    +    QTimeZone zone;
    +    if (spec == Qt::TimeZone)
    +        zone = form.timeZone();
    +#endif
    +    auto moment = [=](QTime time) {
    +        switch (spec) {
    +        case Qt::OffsetFromUTC: return QDateTime(day, time, spec, offset);
    +#if QT_CONFIG(timezone)
    +        case Qt::TimeZone: return QDateTime(day, time, zone);
    +#endif
    +        default: return QDateTime(day, time, spec);
    +        }
    +    };
    +    // Longest routine time-zone transition is 2 hours:
    +    QDateTime when = moment(QTime(2, 0));
    +    if (!when.isValid()) {
    +        // Noon should be safe ...
    +        when = moment(QTime(12, 0));
    +        if (!when.isValid()) {
    +            // ... unless it's a 24-hour jump (moving the date-line)
    +            when = moment(QTime(23, 59, 59, 999));
    +            if (!when.isValid())
    +                return QDateTime();
    +        }
    +    }
    +    int high = when.time().msecsSinceStartOfDay() / 60000;
    +    int low = 0;
    +    // Binary chop to the right minute
    +    while (high > low + 1) {
    +        int mid = (high + low) / 2;
    +        QDateTime probe = moment(QTime(mid / 60, mid % 60));
    +        if (probe.isValid() && probe.date() == day) {
    +            high = mid;
    +            when = probe;
    +        } else {
    +            low = mid;
    +        }
    +    }
    +    return when;
    +}
    +
    +/*!
    +    \since 5.14
    +    \fn QDateTime QDate::startOfDay(Qt::TimeSpec spec, int offsetSeconds) const
    +    \fn QDateTime QDate::startOfDay(const QTimeZone &zone) const
    +
    +    Returns the start-moment of the day.  Usually, this shall be midnight at the
    +    start of the day: however, if a time-zone transition causes the given date
    +    to skip over that midnight (e.g. a DST spring-forward skipping from the end
    +    of the previous day to 01:00 of the new day), the actual earliest time in
    +    the day is returned.  This can only arise when the start-moment is specified
    +    in terms of a time-zone (by passing its QTimeZone as \a zone) or in terms of
    +    local time (by passing Qt::LocalTime as \a spec; this is its default).
    +
    +    The \a offsetSeconds is ignored unless \a spec is Qt::OffsetFromUTC, when it
    +    gives the implied zone's offset from UTC.  As UTC and such zones have no
    +    transitions, the start of the day is QTime(0, 0) in these cases.
    +
    +    In the rare case of a date that was entirely skipped (this happens when a
    +    zone east of the international date-line switches to being west of it), the
    +    return shall be invalid.  Passing Qt::TimeZone as \a spec (instead of
    +    passing a QTimeZone) or passing an invalid time-zone as \a zone will also
    +    produce an invalid result, as shall dates that start outside the range
    +    representable by QDateTime.
    +
    +    \sa endOfDay()
    +*/
    +QDateTime QDate::startOfDay(Qt::TimeSpec spec, int offsetSeconds) const
    +{
    +    if (!inDateTimeRange(jd, true))
    +        return QDateTime();
    +
    +    switch (spec) {
    +    case Qt::TimeZone: // should pass a QTimeZone instead of Qt::TimeZone
    +        qWarning() << "Called QDate::startOfDay(Qt::TimeZone) on" << *this;
    +        return QDateTime();
    +    case Qt::OffsetFromUTC:
    +    case Qt::UTC:
    +        return QDateTime(*this, QTime(0, 0), spec, offsetSeconds);
    +
    +    case Qt::LocalTime:
    +        if (offsetSeconds)
    +            qWarning("Ignoring offset (%d seconds) passed with Qt::LocalTime", offsetSeconds);
    +        break;
    +    }
    +    QDateTime when(*this, QTime(0, 0), spec);
    +    if (!when.isValid())
    +        when = toEarliest(*this, when);
    +
    +    return when.isValid() ? when : QDateTime();
    +}
    +
    +#if QT_CONFIG(timezone)
    +/*!
    +  \overload
    +  \since 5.14
    +*/
    +QDateTime QDate::startOfDay(const QTimeZone &zone) const
    +{
    +    if (!inDateTimeRange(jd, true) || !zone.isValid())
    +        return QDateTime();
    +
    +    QDateTime when(*this, QTime(0, 0), zone);
    +    if (when.isValid())
    +        return when;
    +
    +    // The start of the day must have fallen in a spring-forward's gap; find the spring-forward:
    +    if (zone.hasTransitions()) {
    +        QTimeZone::OffsetData tran = zone.previousTransition(QDateTime(*this, QTime(23, 59, 59, 999), zone));
    +        const QDateTime &at = tran.atUtc.toTimeZone(zone);
    +        if (at.isValid() && at.date() == *this)
    +            return at;
    +    }
    +
    +    when = toEarliest(*this, when);
    +    return when.isValid() ? when : QDateTime();
    +}
    +#endif // timezone
    +
    +static QDateTime toLatest(const QDate &day, const QDateTime &form)
    +{
    +    const Qt::TimeSpec spec = form.timeSpec();
    +    const int offset = (spec == Qt::OffsetFromUTC) ? form.offsetFromUtc() : 0;
    +#if QT_CONFIG(timezone)
    +    QTimeZone zone;
    +    if (spec == Qt::TimeZone)
    +        zone = form.timeZone();
    +#endif
    +    auto moment = [=](QTime time) {
    +        switch (spec) {
    +        case Qt::OffsetFromUTC: return QDateTime(day, time, spec, offset);
    +#if QT_CONFIG(timezone)
    +        case Qt::TimeZone: return QDateTime(day, time, zone);
    +#endif
    +        default: return QDateTime(day, time, spec);
    +        }
    +    };
    +    // Longest routine time-zone transition is 2 hours:
    +    QDateTime when = moment(QTime(21, 59, 59, 999));
    +    if (!when.isValid()) {
    +        // Noon should be safe ...
    +        when = moment(QTime(12, 0));
    +        if (!when.isValid()) {
    +            // ... unless it's a 24-hour jump (moving the date-line)
    +            when = moment(QTime(0, 0));
    +            if (!when.isValid())
    +                return QDateTime();
    +        }
    +    }
    +    int high = 24 * 60;
    +    int low = when.time().msecsSinceStartOfDay() / 60000;
    +    // Binary chop to the right minute
    +    while (high > low + 1) {
    +        int mid = (high + low) / 2;
    +        QDateTime probe = moment(QTime(mid / 60, mid % 60, 59, 999));
    +        if (probe.isValid() && probe.date() == day) {
    +            low = mid;
    +            when = probe;
    +        } else {
    +            high = mid;
    +        }
    +    }
    +    return when;
    +}
    +
    +/*!
    +    \since 5.14
    +    \fn QDateTime QDate::endOfDay(Qt::TimeSpec spec, int offsetSeconds) const
    +    \fn QDateTime QDate::endOfDay(const QTimeZone &zone) const
    +
    +    Returns the end-moment of the day.  Usually, this is one millisecond before
    +    the midnight at the end of the day: however, if a time-zone transition
    +    causes the given date to skip over that midnight (e.g. a DST spring-forward
    +    skipping from just before 23:00 to the start of the next day), the actual
    +    latest time in the day is returned.  This can only arise when the
    +    start-moment is specified in terms of a time-zone (by passing its QTimeZone
    +    as \a zone) or in terms of local time (by passing Qt::LocalTime as \a spec;
    +    this is its default).
    +
    +    The \a offsetSeconds is ignored unless \a spec is Qt::OffsetFromUTC, when it
    +    gives the implied zone's offset from UTC.  As UTC and such zones have no
    +    transitions, the end of the day is QTime(23, 59, 59, 999) in these cases.
    +
    +    In the rare case of a date that was entirely skipped (this happens when a
    +    zone east of the international date-line switches to being west of it), the
    +    return shall be invalid.  Passing Qt::TimeZone as \a spec (instead of
    +    passing a QTimeZone) will also produce an invalid result, as shall dates
    +    that end outside the range representable by QDateTime.
    +
    +    \sa startOfDay()
    +*/
    +QDateTime QDate::endOfDay(Qt::TimeSpec spec, int offsetSeconds) const
    +{
    +    if (!inDateTimeRange(jd, false))
    +        return QDateTime();
    +
    +    switch (spec) {
    +    case Qt::TimeZone: // should pass a QTimeZone instead of Qt::TimeZone
    +        qWarning() << "Called QDate::endOfDay(Qt::TimeZone) on" << *this;
    +        return QDateTime();
    +    case Qt::UTC:
    +    case Qt::OffsetFromUTC:
    +        return QDateTime(*this, QTime(23, 59, 59, 999), spec, offsetSeconds);
    +
    +    case Qt::LocalTime:
    +        if (offsetSeconds)
    +            qWarning("Ignoring offset (%d seconds) passed with Qt::LocalTime", offsetSeconds);
    +        break;
    +    }
    +    QDateTime when(*this, QTime(23, 59, 59, 999), spec);
    +    if (!when.isValid())
    +        when = toLatest(*this, when);
    +    return when.isValid() ? when : QDateTime();
    +}
    +
    +#if QT_CONFIG(timezone)
    +/*!
    +  \overload
    +  \since 5.14
    +*/
    +QDateTime QDate::endOfDay(const QTimeZone &zone) const
    +{
    +    if (!inDateTimeRange(jd, false) || !zone.isValid())
    +        return QDateTime();
    +
    +    QDateTime when(*this, QTime(23, 59, 59, 999), zone);
    +    if (when.isValid())
    +        return when;
    +
    +    // The end of the day must have fallen in a spring-forward's gap; find the spring-forward:
    +    if (zone.hasTransitions()) {
    +        QTimeZone::OffsetData tran = zone.nextTransition(QDateTime(*this, QTime(0, 0), zone));
    +        const QDateTime &at = tran.atUtc.toTimeZone(zone);
    +        if (at.isValid() && at.date() == *this)
    +            return at;
    +    }
    +
    +    when = toLatest(*this, when);
    +    return when.isValid() ? when : QDateTime();
    +}
    +#endif // timezone
    +
    +#if QT_DEPRECATED_SINCE(5, 11) && QT_CONFIG(textdate)
    +
    +/*!
    +    \since 4.5
    +    \deprecated
    +
    +    Returns the short name of the \a month for the representation specified
    +    by \a type.
    +
    +    The months are enumerated using the following convention:
    +
    +    \list
    +    \li 1 = "Jan"
    +    \li 2 = "Feb"
    +    \li 3 = "Mar"
    +    \li 4 = "Apr"
    +    \li 5 = "May"
    +    \li 6 = "Jun"
    +    \li 7 = "Jul"
    +    \li 8 = "Aug"
    +    \li 9 = "Sep"
    +    \li 10 = "Oct"
    +    \li 11 = "Nov"
    +    \li 12 = "Dec"
    +    \endlist
    +
    +    The month names will be localized according to the system's
    +    locale settings, i.e. using QLocale::system().
    +
    +    Returns an empty string if the date is invalid.
    +
    +    \sa toString(), longMonthName(), shortDayName(), longDayName()
    +*/
    +
    +QString QDate::shortMonthName(int month, QDate::MonthNameType type)
    +{
    +    switch (type) {
    +    case QDate::DateFormat:
    +        return QLocale::system().monthName(month, QLocale::ShortFormat);
    +    case QDate::StandaloneFormat:
    +        return QLocale::system().standaloneMonthName(month, QLocale::ShortFormat);
    +    }
    +    return QString();
    +}
    +
    +/*!
    +    \since 4.5
    +    \deprecated
    +
    +    Returns the long name of the \a month for the representation specified
    +    by \a type.
    +
    +    The months are enumerated using the following convention:
    +
    +    \list
    +    \li 1 = "January"
    +    \li 2 = "February"
    +    \li 3 = "March"
    +    \li 4 = "April"
    +    \li 5 = "May"
    +    \li 6 = "June"
    +    \li 7 = "July"
    +    \li 8 = "August"
    +    \li 9 = "September"
    +    \li 10 = "October"
    +    \li 11 = "November"
    +    \li 12 = "December"
    +    \endlist
    +
    +    The month names will be localized according to the system's
    +    locale settings, i.e. using QLocale::system().
    +
    +    Returns an empty string if the date is invalid.
    +
    +    \sa toString(), shortMonthName(), shortDayName(), longDayName()
    +*/
    +
    +QString QDate::longMonthName(int month, MonthNameType type)
    +{
    +    switch (type) {
    +    case QDate::DateFormat:
    +        return QLocale::system().monthName(month, QLocale::LongFormat);
    +    case QDate::StandaloneFormat:
    +        return QLocale::system().standaloneMonthName(month, QLocale::LongFormat);
    +    }
    +    return QString();
    +}
    +
    +/*!
    +    \since 4.5
    +    \deprecated
    +
    +    Returns the short name of the \a weekday for the representation specified
    +    by \a type.
    +
    +    The days are enumerated using the following convention:
    +
    +    \list
    +    \li 1 = "Mon"
    +    \li 2 = "Tue"
    +    \li 3 = "Wed"
    +    \li 4 = "Thu"
    +    \li 5 = "Fri"
    +    \li 6 = "Sat"
    +    \li 7 = "Sun"
    +    \endlist
    +
    +    The day names will be localized according to the system's
    +    locale settings, i.e. using QLocale::system().
    +
    +    Returns an empty string if the date is invalid.
    +
    +    \sa toString(), shortMonthName(), longMonthName(), longDayName()
    +*/
    +
    +QString QDate::shortDayName(int weekday, MonthNameType type)
    +{
    +    switch (type) {
    +    case QDate::DateFormat:
    +        return QLocale::system().dayName(weekday, QLocale::ShortFormat);
    +    case QDate::StandaloneFormat:
    +        return QLocale::system().standaloneDayName(weekday, QLocale::ShortFormat);
    +    }
    +    return QString();
    +}
    +
    +/*!
    +    \since 4.5
    +    \deprecated
    +
    +    Returns the long name of the \a weekday for the representation specified
    +    by \a type.
    +
    +    The days are enumerated using the following convention:
    +
    +    \list
    +    \li 1 = "Monday"
    +    \li 2 = "Tuesday"
    +    \li 3 = "Wednesday"
    +    \li 4 = "Thursday"
    +    \li 5 = "Friday"
    +    \li 6 = "Saturday"
    +    \li 7 = "Sunday"
    +    \endlist
    +
    +    The day names will be localized according to the system's
    +    locale settings, i.e. using QLocale::system().
    +
    +    Returns an empty string if the date is invalid.
    +
    +    \sa toString(), shortDayName(), shortMonthName(), longMonthName()
    +*/
    +
    +QString QDate::longDayName(int weekday, MonthNameType type)
    +{
    +    switch (type) {
    +    case QDate::DateFormat:
    +        return QLocale::system().dayName(weekday, QLocale::LongFormat);
    +    case QDate::StandaloneFormat:
    +        return QLocale::system().standaloneDayName(weekday, QLocale::LongFormat);
    +    }
    +    return QString();
    +}
    +#endif // textdate && deprecated
    +
    +#if QT_CONFIG(datestring)
    +
    +#if QT_CONFIG(textdate)
    +static QString toStringTextDate(QDate date)
    +{
    +    const ParsedDate pd = getDateFromJulianDay(date.toJulianDay());
    +    static const QLatin1Char sp(' ');
    +    return QLocale::system().dayName(date.dayOfWeek(), QLocale::ShortFormat) + sp
    +         + QLocale::system().monthName(pd.month, QLocale::ShortFormat) + sp
    +         + QString::number(pd.day) + sp
    +         + QString::number(pd.year);
    +}
    +#endif // textdate
    +
    +static QString toStringIsoDate(qint64 jd)
    +{
    +    const ParsedDate pd = getDateFromJulianDay(jd);
    +    if (pd.year >= 0 && pd.year <= 9999)
    +        return QString::asprintf("%04d-%02d-%02d", pd.year, pd.month, pd.day);
    +    else
    +        return QString();
    +}
    +
    +/*!
    +    \fn QString QDate::toString(Qt::DateFormat format) const
    +
    +    \overload
    +
    +    Returns the date as a string. The \a format parameter determines
    +    the format of the string.
    +
    +    If the \a format is Qt::TextDate, the string is formatted in
    +    the default way. QDate::shortDayName() and QDate::shortMonthName()
    +    are used to generate the string, so the day and month names will
    +    be localized names using the system locale, i.e. QLocale::system(). An
    +    example of this formatting is "Sat May 20 1995".
    +
    +    If the \a format is Qt::ISODate, the string format corresponds
    +    to the ISO 8601 extended specification for representations of
    +    dates and times, taking the form yyyy-MM-dd, where yyyy is the
    +    year, MM is the month of the year (between 01 and 12), and dd is
    +    the day of the month between 01 and 31.
    +
    +    If the \a format is Qt::SystemLocaleShortDate or
    +    Qt::SystemLocaleLongDate, the string format depends on the locale
    +    settings of the system. Identical to calling
    +    QLocale::system().toString(date, QLocale::ShortFormat) or
    +    QLocale::system().toString(date, QLocale::LongFormat).
    +
    +    If the \a format is Qt::DefaultLocaleShortDate or
    +    Qt::DefaultLocaleLongDate, the string format depends on the
    +    default application locale. This is the locale set with
    +    QLocale::setDefault(), or the system locale if no default locale
    +    has been set. Identical to calling
    +    \l {QLocale::toString()}{QLocale().toString(date, QLocale::ShortFormat) } or
    +    \l {QLocale::toString()}{QLocale().toString(date, QLocale::LongFormat)}.
    +
    +    If the \a format is Qt::RFC2822Date, the string is formatted in
    +    an \l{RFC 2822} compatible way. An example of this formatting is
    +    "20 May 1995".
    +
    +    If the date is invalid, an empty string will be returned.
    +
    +    \warning The Qt::ISODate format is only valid for years in the
    +    range 0 to 9999. This restriction may apply to locale-aware
    +    formats as well, depending on the locale settings.
    +
    +    \sa fromString(), shortDayName(), shortMonthName(), QLocale::toString()
    +*/
    +QString QDate::toString(Qt::DateFormat format) const
    +{
    +    if (!isValid())
    +        return QString();
    +
    +    switch (format) {
    +    case Qt::SystemLocaleDate:
    +    case Qt::SystemLocaleShortDate:
    +        return QLocale::system().toString(*this, QLocale::ShortFormat);
    +    case Qt::SystemLocaleLongDate:
    +        return QLocale::system().toString(*this, QLocale::LongFormat);
    +    case Qt::LocaleDate:
    +    case Qt::DefaultLocaleShortDate:
    +        return QLocale().toString(*this, QLocale::ShortFormat);
    +    case Qt::DefaultLocaleLongDate:
    +        return QLocale().toString(*this, QLocale::LongFormat);
    +    case Qt::RFC2822Date:
    +        return QLocale::c().toString(*this, QStringViewLiteral("dd MMM yyyy"));
    +    default:
    +#if QT_CONFIG(textdate)
    +    case Qt::TextDate:
    +        return toStringTextDate(*this);
    +#endif
    +    case Qt::ISODate:
    +    case Qt::ISODateWithMs:
    +        return toStringIsoDate(jd);
    +    }
    +}
    +
    +/*!
    +    \fn QString QDate::toString(const QString &format) const
    +    \fn QString QDate::toString(QStringView format) const
    +
    +    Returns the date as a string. The \a format parameter determines
    +    the format of the result string.
    +
    +    These expressions may be used:
    +
    +    \table
    +    \header \li Expression \li Output
    +    \row \li d \li the day as number without a leading zero (1 to 31)
    +    \row \li dd \li the day as number with a leading zero (01 to 31)
    +    \row \li ddd
    +         \li the abbreviated localized day name (e.g. 'Mon' to 'Sun').
    +             Uses the system locale to localize the name, i.e. QLocale::system().
    +    \row \li dddd
    +         \li the long localized day name (e.g. 'Monday' to 'Sunday').
    +             Uses the system locale to localize the name, i.e. QLocale::system().
    +    \row \li M \li the month as number without a leading zero (1 to 12)
    +    \row \li MM \li the month as number with a leading zero (01 to 12)
    +    \row \li MMM
    +         \li the abbreviated localized month name (e.g. 'Jan' to 'Dec').
    +             Uses the system locale to localize the name, i.e. QLocale::system().
    +    \row \li MMMM
    +         \li the long localized month name (e.g. 'January' to 'December').
    +             Uses the system locale to localize the name, i.e. QLocale::system().
    +    \row \li yy \li the year as two digit number (00 to 99)
    +    \row \li yyyy \li the year as four digit number. If the year is negative,
    +            a minus sign is prepended in addition.
    +    \endtable
    +
    +    Any sequence of characters enclosed in single quotes will be included
    +    verbatim in the output string (stripped of the quotes), even if it contains
    +    formatting characters. Two consecutive single quotes ("''") are replaced by
    +    a single quote in the output. All other characters in the format string are
    +    included verbatim in the output string.
    +
    +    Formats without separators (e.g. "ddMM") are supported but must be used with
    +    care, as the resulting strings aren't always reliably readable (e.g. if "dM"
    +    produces "212" it could mean either the 2nd of December or the 21st of
    +    February).
    +
    +    Example format strings (assuming that the QDate is the 20 July
    +    1969):
    +
    +    \table
    +    \header \li Format            \li Result
    +    \row    \li dd.MM.yyyy        \li 20.07.1969
    +    \row    \li ddd MMMM d yy     \li Sun July 20 69
    +    \row    \li 'The day is' dddd \li The day is Sunday
    +    \endtable
    +
    +    If the datetime is invalid, an empty string will be returned.
    +
    +    \sa fromString(), QDateTime::toString(), QTime::toString(), QLocale::toString()
    +
    +*/
    +QString QDate::toString(QStringView format) const
    +{
    +    return QLocale::system().toString(*this, format); // QLocale::c() ### Qt6
    +}
    +
    +#if QT_STRINGVIEW_LEVEL < 2
    +QString QDate::toString(const QString &format) const
    +{
    +    return toString(qToStringViewIgnoringNull(format));
    +}
    +#endif
    +
    +#endif // datestring
    +
    +/*!
    +    \fn bool QDate::setYMD(int y, int m, int d)
    +
    +    \deprecated in 5.0, use setDate() instead.
    +
    +    Sets the date's year \a y, month \a m, and day \a d.
    +
    +    If \a y is in the range 0 to 99, it is interpreted as 1900 to
    +    1999.
    +    Returns \c false if the date is invalid.
    +
    +    Use setDate() instead.
    +*/
    +
    +/*!
    +    \since 4.2
    +
    +    Sets the date's \a year, \a month, and \a day. Returns \c true if
    +    the date is valid; otherwise returns \c false.
    +
    +    If the specified date is invalid, the QDate object is set to be
    +    invalid.
    +
    +    \sa isValid()
    +*/
    +bool QDate::setDate(int year, int month, int day)
    +{
    +    if (isValid(year, month, day))
    +        jd = julianDayFromDate(year, month, day);
    +    else
    +        jd = nullJd();
    +
    +    return isValid();
    +}
    +
    +/*!
    +    \since 4.5
    +
    +    Extracts the date's year, month, and day, and assigns them to
    +    *\a year, *\a month, and *\a day. The pointers may be null.
    +
    +    Returns 0 if the date is invalid.
    +
    +    \note In Qt versions prior to 5.7, this function is marked as non-\c{const}.
    +
    +    \sa year(), month(), day(), isValid()
    +*/
    +void QDate::getDate(int *year, int *month, int *day) const
    +{
    +    ParsedDate pd = { 0, 0, 0 };
    +    if (isValid())
    +        pd = getDateFromJulianDay(jd);
    +
    +    if (year)
    +        *year = pd.year;
    +    if (month)
    +        *month = pd.month;
    +    if (day)
    +        *day = pd.day;
    +}
    +
    +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    +/*!
    +    \overload
    +    \internal
    +*/
    +void QDate::getDate(int *year, int *month, int *day)
    +{
    +    qAsConst(*this).getDate(year, month, day);
    +}
    +#endif // < Qt 6
    +
    +/*!
    +    Returns a QDate object containing a date \a ndays later than the
    +    date of this object (or earlier if \a ndays is negative).
    +
    +    Returns a null date if the current date is invalid or the new date is
    +    out of range.
    +
    +    \sa addMonths(), addYears(), daysTo()
    +*/
    +
    +QDate QDate::addDays(qint64 ndays) const
    +{
    +    if (isNull())
    +        return QDate();
    +
    +    // Due to limits on minJd() and maxJd() we know that any overflow
    +    // will be invalid and caught by fromJulianDay().
    +    return fromJulianDay(jd + ndays);
    +}
    +
    +/*!
    +    Returns a QDate object containing a date \a nmonths later than the
    +    date of this object (or earlier if \a nmonths is negative).
    +
    +    \note If the ending day/month combination does not exist in the
    +    resulting month/year, this function will return a date that is the
    +    latest valid date.
    +
    +    \sa addDays(), addYears()
    +*/
    +
    +QDate QDate::addMonths(int nmonths) const
    +{
    +    if (!isValid())
    +        return QDate();
    +    if (!nmonths)
    +        return *this;
    +
    +    int old_y, y, m, d;
    +    {
    +        const ParsedDate pd = getDateFromJulianDay(jd);
    +        y = pd.year;
    +        m = pd.month;
    +        d = pd.day;
    +    }
    +    old_y = y;
    +
    +    bool increasing = nmonths > 0;
    +
    +    while (nmonths != 0) {
    +        if (nmonths < 0 && nmonths + 12 <= 0) {
    +            y--;
    +            nmonths+=12;
    +        } else if (nmonths < 0) {
    +            m+= nmonths;
    +            nmonths = 0;
    +            if (m <= 0) {
    +                --y;
    +                m += 12;
    +            }
    +        } else if (nmonths - 12 >= 0) {
    +            y++;
    +            nmonths -= 12;
    +        } else if (m == 12) {
    +            y++;
    +            m = 0;
    +        } else {
    +            m += nmonths;
    +            nmonths = 0;
    +            if (m > 12) {
    +                ++y;
    +                m -= 12;
    +            }
    +        }
    +    }
    +
    +    // was there a sign change?
    +    if ((old_y > 0 && y <= 0) ||
    +        (old_y < 0 && y >= 0))
    +        // yes, adjust the date by +1 or -1 years
    +        y += increasing ? +1 : -1;
    +
    +    return fixedDate(y, m, d);
    +}
    +
    +/*!
    +    Returns a QDate object containing a date \a nyears later than the
    +    date of this object (or earlier if \a nyears is negative).
    +
    +    \note If the ending day/month combination does not exist in the
    +    resulting year (i.e., if the date was Feb 29 and the final year is
    +    not a leap year), this function will return a date that is the
    +    latest valid date (that is, Feb 28).
    +
    +    \sa addDays(), addMonths()
    +*/
    +
    +QDate QDate::addYears(int nyears) const
    +{
    +    if (!isValid())
    +        return QDate();
    +
    +    ParsedDate pd = getDateFromJulianDay(jd);
    +
    +    int old_y = pd.year;
    +    pd.year += nyears;
    +
    +    // was there a sign change?
    +    if ((old_y > 0 && pd.year <= 0) ||
    +        (old_y < 0 && pd.year >= 0))
    +        // yes, adjust the date by +1 or -1 years
    +        pd.year += nyears > 0 ? +1 : -1;
    +
    +    return fixedDate(pd.year, pd.month, pd.day);
    +}
    +
    +/*!
    +    Returns the number of days from this date to \a d (which is
    +    negative if \a d is earlier than this date).
    +
    +    Returns 0 if either date is invalid.
    +
    +    Example:
    +    \snippet code/src_corelib_tools_qdatetime.cpp 0
    +
    +    \sa addDays()
    +*/
    +
    +qint64 QDate::daysTo(const QDate &d) const
    +{
    +    if (isNull() || d.isNull())
    +        return 0;
    +
    +    // Due to limits on minJd() and maxJd() we know this will never overflow
    +    return d.jd - jd;
    +}
    +
    +
    +/*!
    +    \fn bool QDate::operator==(const QDate &d) const
    +
    +    Returns \c true if this date is equal to \a d; otherwise returns
    +    false.
    +
    +*/
    +
    +/*!
    +    \fn bool QDate::operator!=(const QDate &d) const
    +
    +    Returns \c true if this date is different from \a d; otherwise
    +    returns \c false.
    +*/
    +
    +/*!
    +    \fn bool QDate::operator<(const QDate &d) const
    +
    +    Returns \c true if this date is earlier than \a d; otherwise returns
    +    false.
    +*/
    +
    +/*!
    +    \fn bool QDate::operator<=(const QDate &d) const
    +
    +    Returns \c true if this date is earlier than or equal to \a d;
    +    otherwise returns \c false.
    +*/
    +
    +/*!
    +    \fn bool QDate::operator>(const QDate &d) const
    +
    +    Returns \c true if this date is later than \a d; otherwise returns
    +    false.
    +*/
    +
    +/*!
    +    \fn bool QDate::operator>=(const QDate &d) const
    +
    +    Returns \c true if this date is later than or equal to \a d;
    +    otherwise returns \c false.
    +*/
    +
    +/*!
    +    \fn QDate::currentDate()
    +    Returns the current date, as reported by the system clock.
    +
    +    \sa QTime::currentTime(), QDateTime::currentDateTime()
    +*/
    +
    +#if QT_CONFIG(datestring)
    +/*!
    +    Returns the QDate represented by the \a string, using the
    +    \a format given, or an invalid date if the string cannot be
    +    parsed.
    +
    +    Note for Qt::TextDate: It is recommended that you use the
    +    English short month names (e.g. "Jan"). Although localized month
    +    names can also be used, they depend on the user's locale settings.
    +
    +    \sa toString(), QLocale::toDate()
    +*/
    +
    +QDate QDate::fromString(const QString &string, Qt::DateFormat format)
    +{
    +    if (string.isEmpty())
    +        return QDate();
    +
    +    switch (format) {
    +    case Qt::SystemLocaleDate:
    +    case Qt::SystemLocaleShortDate:
    +        return QLocale::system().toDate(string, QLocale::ShortFormat);
    +    case Qt::SystemLocaleLongDate:
    +        return QLocale::system().toDate(string, QLocale::LongFormat);
    +    case Qt::LocaleDate:
    +    case Qt::DefaultLocaleShortDate:
    +        return QLocale().toDate(string, QLocale::ShortFormat);
    +    case Qt::DefaultLocaleLongDate:
    +        return QLocale().toDate(string, QLocale::LongFormat);
    +    case Qt::RFC2822Date:
    +        return rfcDateImpl(string).date;
    +    default:
    +#if QT_CONFIG(textdate)
    +    case Qt::TextDate: {
    +        QVector parts = string.splitRef(QLatin1Char(' '), QString::SkipEmptyParts);
    +
    +        if (parts.count() != 4)
    +            return QDate();
    +
    +        QStringRef monthName = parts.at(1);
    +        const int month = fromShortMonthName(monthName);
    +        if (month == -1) {
    +            // Month name matches neither English nor other localised name.
    +            return QDate();
    +        }
    +
    +        bool ok = false;
    +        int year = parts.at(3).toInt(&ok);
    +        if (!ok)
    +            return QDate();
    +
    +        return QDate(year, month, parts.at(2).toInt());
    +        }
    +#endif // textdate
    +    case Qt::ISODate: {
    +        // Semi-strict parsing, must be long enough and have non-numeric separators
    +        if (string.size() < 10 || string.at(4).isDigit() || string.at(7).isDigit()
    +            || (string.size() > 10 && string.at(10).isDigit())) {
    +            return QDate();
    +        }
    +        const int year = string.midRef(0, 4).toInt();
    +        if (year <= 0 || year > 9999)
    +            return QDate();
    +        return QDate(year, string.midRef(5, 2).toInt(), string.midRef(8, 2).toInt());
    +        }
    +    }
    +    return QDate();
    +}
    +
    +/*!
    +    Returns the QDate represented by the \a string, using the \a
    +    format given, or an invalid date if the string cannot be parsed.
    +
    +    These expressions may be used for the format:
    +
    +    \table
    +    \header \li Expression \li Output
    +    \row \li d \li The day as a number without a leading zero (1 to 31)
    +    \row \li dd \li The day as a number with a leading zero (01 to 31)
    +    \row \li ddd
    +         \li The abbreviated localized day name (e.g. 'Mon' to 'Sun').
    +             Uses the system locale to localize the name, i.e. QLocale::system().
    +    \row \li dddd
    +         \li The long localized day name (e.g. 'Monday' to 'Sunday').
    +             Uses the system locale to localize the name, i.e. QLocale::system().
    +    \row \li M \li The month as a number without a leading zero (1 to 12)
    +    \row \li MM \li The month as a number with a leading zero (01 to 12)
    +    \row \li MMM
    +         \li The abbreviated localized month name (e.g. 'Jan' to 'Dec').
    +             Uses the system locale to localize the name, i.e. QLocale::system().
    +    \row \li MMMM
    +         \li The long localized month name (e.g. 'January' to 'December').
    +             Uses the system locale to localize the name, i.e. QLocale::system().
    +    \row \li yy \li The year as two digit number (00 to 99)
    +    \row \li yyyy \li The year as four digit number. If the year is negative,
    +            a minus sign is prepended in addition.
    +    \endtable
    +
    +    All other input characters will be treated as text. Any sequence
    +    of characters that are enclosed in single quotes will also be
    +    treated as text and will not be used as an expression. For example:
    +
    +    \snippet code/src_corelib_tools_qdatetime.cpp 1
    +
    +    If the format is not satisfied, an invalid QDate is returned. The
    +    expressions that don't expect leading zeroes (d, M) will be
    +    greedy. This means that they will use two digits even if this
    +    will put them outside the accepted range of values and leaves too
    +    few digits for other sections. For example, the following format
    +    string could have meant January 30 but the M will grab two
    +    digits, resulting in an invalid date:
    +
    +    \snippet code/src_corelib_tools_qdatetime.cpp 2
    +
    +    For any field that is not represented in the format the following
    +    defaults are used:
    +
    +    \table
    +    \header \li Field  \li Default value
    +    \row    \li Year   \li 1900
    +    \row    \li Month  \li 1
    +    \row    \li Day    \li 1
    +    \endtable
    +
    +    The following examples demonstrate the default values:
    +
    +    \snippet code/src_corelib_tools_qdatetime.cpp 3
    +
    +    \sa toString(), QDateTime::fromString(), QTime::fromString(),
    +        QLocale::toDate()
    +*/
    +
    +QDate QDate::fromString(const QString &string, const QString &format)
    +{
    +    QDate date;
    +#if QT_CONFIG(datetimeparser)
    +    QDateTimeParser dt(QVariant::Date, QDateTimeParser::FromString);
    +    // dt.setDefaultLocale(QLocale::c()); ### Qt 6
    +    if (dt.parseFormat(format))
    +        dt.fromString(string, &date, 0);
    +#else
    +    Q_UNUSED(string);
    +    Q_UNUSED(format);
    +#endif
    +    return date;
    +}
    +#endif // datestring
    +
    +/*!
    +    \overload
    +
    +    Returns \c true if the specified date (\a year, \a month, and \a
    +    day) is valid; otherwise returns \c false.
    +
    +    Example:
    +    \snippet code/src_corelib_tools_qdatetime.cpp 4
    +
    +    \sa isNull(), setDate()
    +*/
    +
    +bool QDate::isValid(int year, int month, int day)
    +{
    +    // There is no year 0 in the Gregorian calendar.
    +    return year && day > 0 && month > 0 && month <= 12 &&
    +        day <= (month == 2 ? isLeapYear(year) ? 29 : 28 : daysInUsualMonth(month));
    +}
    +
    +/*!
    +    \fn bool QDate::isLeapYear(int year)
    +
    +    Returns \c true if the specified \a year is a leap year; otherwise
    +    returns \c false.
    +*/
    +
    +bool QDate::isLeapYear(int y)
    +{
    +    // No year 0 in Gregorian calendar, so -1, -5, -9 etc are leap years
    +    if ( y < 1)
    +        ++y;
    +
    +    return (y % 4 == 0 && y % 100 != 0) || y % 400 == 0;
    +}
    +
    +/*! \fn static QDate QDate::fromJulianDay(qint64 jd)
    +
    +    Converts the Julian day \a jd to a QDate.
    +
    +    \sa toJulianDay()
    +*/
    +
    +/*! \fn int QDate::toJulianDay() const
    +
    +    Converts the date to a Julian day.
    +
    +    \sa fromJulianDay()
    +*/
    +
    +/*****************************************************************************
    +  QTime member functions
    + *****************************************************************************/
    +
    +/*!
    +    \class QTime
    +    \inmodule QtCore
    +    \reentrant
    +
    +    \brief The QTime class provides clock time functions.
    +
    +
    +    A QTime object contains a clock time, which it can express as the numbers of
    +    hours, minutes, seconds, and milliseconds since midnight. It provides
    +    functions for comparing times and for manipulating a time by adding a number
    +    of milliseconds.
    +
    +    QTime uses the 24-hour clock format; it has no concept of AM/PM.
    +    Unlike QDateTime, QTime knows nothing about time zones or
    +    daylight-saving time (DST).
    +
    +    A QTime object is typically created either by giving the number
    +    of hours, minutes, seconds, and milliseconds explicitly, or by
    +    using the static function currentTime(), which creates a QTime
    +    object that contains the system's local time. Note that the
    +    accuracy depends on the accuracy of the underlying operating
    +    system; not all systems provide 1-millisecond accuracy.
    +
    +    The hour(), minute(), second(), and msec() functions provide
    +    access to the number of hours, minutes, seconds, and milliseconds
    +    of the time. The same information is provided in textual format by
    +    the toString() function.
    +
    +    The addSecs() and addMSecs() functions provide the time a given
    +    number of seconds or milliseconds later than a given time.
    +    Correspondingly, the number of seconds or milliseconds
    +    between two times can be found using secsTo() or msecsTo().
    +
    +    QTime provides a full set of operators to compare two QTime
    +    objects; an earlier time is considered smaller than a later one;
    +    if A.msecsTo(B) is positive, then A < B.
    +
    +    \sa QDate, QDateTime
    +*/
    +
    +/*!
    +    \fn QTime::QTime()
    +
    +    Constructs a null time object. For a null time, isNull() returns \c true and
    +    isValid() returns \c false. If you need a zero time, use QTime(0, 0).  For
    +    the start of a day, see QDate::startOfDay().
    +
    +    \sa isNull(), isValid()
    +*/
    +
    +/*!
    +    Constructs a time with hour \a h, minute \a m, seconds \a s and
    +    milliseconds \a ms.
    +
    +    \a h must be in the range 0 to 23, \a m and \a s must be in the
    +    range 0 to 59, and \a ms must be in the range 0 to 999.
    +
    +    \sa isValid()
    +*/
    +
    +QTime::QTime(int h, int m, int s, int ms)
    +{
    +    setHMS(h, m, s, ms);
    +}
    +
    +
    +/*!
    +    \fn bool QTime::isNull() const
    +
    +    Returns \c true if the time is null (i.e., the QTime object was
    +    constructed using the default constructor); otherwise returns
    +    false. A null time is also an invalid time.
    +
    +    \sa isValid()
    +*/
    +
    +/*!
    +    Returns \c true if the time is valid; otherwise returns \c false. For example,
    +    the time 23:30:55.746 is valid, but 24:12:30 is invalid.
    +
    +    \sa isNull()
    +*/
    +
    +bool QTime::isValid() const
    +{
    +    return mds > NullTime && mds < MSECS_PER_DAY;
    +}
    +
    +
    +/*!
    +    Returns the hour part (0 to 23) of the time.
    +
    +    Returns -1 if the time is invalid.
    +
    +    \sa minute(), second(), msec()
    +*/
    +
    +int QTime::hour() const
    +{
    +    if (!isValid())
    +        return -1;
    +
    +    return ds() / MSECS_PER_HOUR;
    +}
    +
    +/*!
    +    Returns the minute part (0 to 59) of the time.
    +
    +    Returns -1 if the time is invalid.
    +
    +    \sa hour(), second(), msec()
    +*/
    +
    +int QTime::minute() const
    +{
    +    if (!isValid())
    +        return -1;
    +
    +    return (ds() % MSECS_PER_HOUR) / MSECS_PER_MIN;
    +}
    +
    +/*!
    +    Returns the second part (0 to 59) of the time.
    +
    +    Returns -1 if the time is invalid.
    +
    +    \sa hour(), minute(), msec()
    +*/
    +
    +int QTime::second() const
    +{
    +    if (!isValid())
    +        return -1;
    +
    +    return (ds() / 1000)%SECS_PER_MIN;
    +}
    +
    +/*!
    +    Returns the millisecond part (0 to 999) of the time.
    +
    +    Returns -1 if the time is invalid.
    +
    +    \sa hour(), minute(), second()
    +*/
    +
    +int QTime::msec() const
    +{
    +    if (!isValid())
    +        return -1;
    +
    +    return ds() % 1000;
    +}
    +
    +#if QT_CONFIG(datestring)
    +/*!
    +    \overload
    +
    +    Returns the time as a string. The \a format parameter determines
    +    the format of the string.
    +
    +    If \a format is Qt::TextDate, the string format is HH:mm:ss;
    +    e.g. 1 second before midnight would be "23:59:59".
    +
    +    If \a format is Qt::ISODate, the string format corresponds to the
    +    ISO 8601 extended specification for representations of dates,
    +    represented by HH:mm:ss. To include milliseconds in the ISO 8601
    +    date, use the \a format Qt::ISODateWithMs, which corresponds to
    +    HH:mm:ss.zzz.
    +
    +    If the \a format is Qt::SystemLocaleShortDate or
    +    Qt::SystemLocaleLongDate, the string format depends on the locale
    +    settings of the system. Identical to calling
    +    QLocale::system().toString(time, QLocale::ShortFormat) or
    +    QLocale::system().toString(time, QLocale::LongFormat).
    +
    +    If the \a format is Qt::DefaultLocaleShortDate or
    +    Qt::DefaultLocaleLongDate, the string format depends on the
    +    default application locale. This is the locale set with
    +    QLocale::setDefault(), or the system locale if no default locale
    +    has been set. Identical to calling
    +
    +    \l {QLocale::toString()}{QLocale().toString(time, QLocale::ShortFormat)} or
    +    \l {QLocale::toString()}{QLocale().toString(time, QLocale::LongFormat)}.
    +
    +    If the \a format is Qt::RFC2822Date, the string is formatted in
    +    an \l{RFC 2822} compatible way. An example of this formatting is
    +    "23:59:20".
    +
    +    If the time is invalid, an empty string will be returned.
    +
    +    \sa fromString(), QDate::toString(), QDateTime::toString(), QLocale::toString()
    +*/
    +
    +QString QTime::toString(Qt::DateFormat format) const
    +{
    +    if (!isValid())
    +        return QString();
    +
    +    switch (format) {
    +    case Qt::SystemLocaleDate:
    +    case Qt::SystemLocaleShortDate:
    +        return QLocale::system().toString(*this, QLocale::ShortFormat);
    +    case Qt::SystemLocaleLongDate:
    +        return QLocale::system().toString(*this, QLocale::LongFormat);
    +    case Qt::LocaleDate:
    +    case Qt::DefaultLocaleShortDate:
    +        return QLocale().toString(*this, QLocale::ShortFormat);
    +    case Qt::DefaultLocaleLongDate:
    +        return QLocale().toString(*this, QLocale::LongFormat);
    +    case Qt::ISODateWithMs:
    +        return QString::asprintf("%02d:%02d:%02d.%03d", hour(), minute(), second(), msec());
    +    case Qt::RFC2822Date:
    +    case Qt::ISODate:
    +    case Qt::TextDate:
    +    default:
    +        return QString::asprintf("%02d:%02d:%02d", hour(), minute(), second());
    +    }
    +}
    +
    +/*!
    +    \fn QString QTime::toString(const QString &format) const
    +    \fn QString QTime::toString(QStringView format) const
    +
    +    Returns the time as a string. The \a format parameter determines
    +    the format of the result string.
    +
    +    These expressions may be used:
    +
    +    \table
    +    \header \li Expression \li Output
    +    \row \li h
    +         \li the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
    +    \row \li hh
    +         \li the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
    +    \row \li H
    +         \li the hour without a leading zero (0 to 23, even with AM/PM display)
    +    \row \li HH
    +         \li the hour with a leading zero (00 to 23, even with AM/PM display)
    +    \row \li m \li the minute without a leading zero (0 to 59)
    +    \row \li mm \li the minute with a leading zero (00 to 59)
    +    \row \li s \li the whole second, without any leading zero (0 to 59)
    +    \row \li ss \li the whole second, with a leading zero where applicable (00 to 59)
    +    \row \li z \li the fractional part of the second, to go after a decimal
    +                point, without trailing zeroes (0 to 999).  Thus "\c{s.z}"
    +                reports the seconds to full available (millisecond) precision
    +                without trailing zeroes.
    +    \row \li zzz \li the fractional part of the second, to millisecond
    +                precision, including trailing zeroes where applicable (000 to 999).
    +    \row \li AP or A
    +         \li use AM/PM display. \e A/AP will be replaced by either
    +             QLocale::amText() or QLocale::pmText().
    +    \row \li ap or a
    +         \li use am/pm display. \e a/ap will be replaced by a lower-case version of
    +             QLocale::amText() or QLocale::pmText().
    +    \row \li t \li the timezone (for example "CEST")
    +    \endtable
    +
    +    Any sequence of characters enclosed in single quotes will be included
    +    verbatim in the output string (stripped of the quotes), even if it contains
    +    formatting characters. Two consecutive single quotes ("''") are replaced by
    +    a single quote in the output. All other characters in the format string are
    +    included verbatim in the output string.
    +
    +    Formats without separators (e.g. "ddMM") are supported but must be used with
    +    care, as the resulting strings aren't always reliably readable (e.g. if "dM"
    +    produces "212" it could mean either the 2nd of December or the 21st of
    +    February).
    +
    +    Example format strings (assuming that the QTime is 14:13:09.042 and the system
    +    locale is \c{en_US})
    +
    +    \table
    +    \header \li Format \li Result
    +    \row \li hh:mm:ss.zzz \li 14:13:09.042
    +    \row \li h:m:s ap     \li 2:13:9 pm
    +    \row \li H:m:s a      \li 14:13:9 pm
    +    \endtable
    +
    +    If the time is invalid, an empty string will be returned.
    +    If \a format is empty, the default format "hh:mm:ss" is used.
    +
    +    \sa fromString(), QDate::toString(), QDateTime::toString(), QLocale::toString()
    +*/
    +QString QTime::toString(QStringView format) const
    +{
    +    return QLocale::system().toString(*this, format); // QLocale::c() ### Qt6
    +}
    +
    +#if QT_STRINGVIEW_VERSION < 2
    +QString QTime::toString(const QString &format) const
    +{
    +    return toString(qToStringViewIgnoringNull(format));
    +}
    +#endif
    +
    +#endif // datestring
    +
    +/*!
    +    Sets the time to hour \a h, minute \a m, seconds \a s and
    +    milliseconds \a ms.
    +
    +    \a h must be in the range 0 to 23, \a m and \a s must be in the
    +    range 0 to 59, and \a ms must be in the range 0 to 999.
    +    Returns \c true if the set time is valid; otherwise returns \c false.
    +
    +    \sa isValid()
    +*/
    +
    +bool QTime::setHMS(int h, int m, int s, int ms)
    +{
    +    if (!isValid(h,m,s,ms)) {
    +        mds = NullTime;                // make this invalid
    +        return false;
    +    }
    +    mds = (h*SECS_PER_HOUR + m*SECS_PER_MIN + s)*1000 + ms;
    +    return true;
    +}
    +
    +/*!
    +    Returns a QTime object containing a time \a s seconds later
    +    than the time of this object (or earlier if \a s is negative).
    +
    +    Note that the time will wrap if it passes midnight.
    +
    +    Returns a null time if this time is invalid.
    +
    +    Example:
    +
    +    \snippet code/src_corelib_tools_qdatetime.cpp 5
    +
    +    \sa addMSecs(), secsTo(), QDateTime::addSecs()
    +*/
    +
    +QTime QTime::addSecs(int s) const
    +{
    +    s %= SECS_PER_DAY;
    +    return addMSecs(s * 1000);
    +}
    +
    +/*!
    +    Returns the number of seconds from this time to \a t.
    +    If \a t is earlier than this time, the number of seconds returned
    +    is negative.
    +
    +    Because QTime measures time within a day and there are 86400
    +    seconds in a day, the result is always between -86400 and 86400.
    +
    +    secsTo() does not take into account any milliseconds.
    +
    +    Returns 0 if either time is invalid.
    +
    +    \sa addSecs(), QDateTime::secsTo()
    +*/
    +
    +int QTime::secsTo(const QTime &t) const
    +{
    +    if (!isValid() || !t.isValid())
    +        return 0;
    +
    +    // Truncate milliseconds as we do not want to consider them.
    +    int ourSeconds = ds() / 1000;
    +    int theirSeconds = t.ds() / 1000;
    +    return theirSeconds - ourSeconds;
    +}
    +
    +/*!
    +    Returns a QTime object containing a time \a ms milliseconds later
    +    than the time of this object (or earlier if \a ms is negative).
    +
    +    Note that the time will wrap if it passes midnight. See addSecs()
    +    for an example.
    +
    +    Returns a null time if this time is invalid.
    +
    +    \sa addSecs(), msecsTo(), QDateTime::addMSecs()
    +*/
    +
    +QTime QTime::addMSecs(int ms) const
    +{
    +    QTime t;
    +    if (isValid()) {
    +        if (ms < 0) {
    +            // %,/ not well-defined for -ve, so always work with +ve.
    +            int negdays = (MSECS_PER_DAY - ms) / MSECS_PER_DAY;
    +            t.mds = (ds() + ms + negdays * MSECS_PER_DAY) % MSECS_PER_DAY;
    +        } else {
    +            t.mds = (ds() + ms) % MSECS_PER_DAY;
    +        }
    +    }
    +    return t;
    +}
    +
    +/*!
    +    Returns the number of milliseconds from this time to \a t.
    +    If \a t is earlier than this time, the number of milliseconds returned
    +    is negative.
    +
    +    Because QTime measures time within a day and there are 86400
    +    seconds in a day, the result is always between -86400000 and
    +    86400000 ms.
    +
    +    Returns 0 if either time is invalid.
    +
    +    \sa secsTo(), addMSecs(), QDateTime::msecsTo()
    +*/
    +
    +int QTime::msecsTo(const QTime &t) const
    +{
    +    if (!isValid() || !t.isValid())
    +        return 0;
    +    return t.ds() - ds();
    +}
    +
    +
    +/*!
    +    \fn bool QTime::operator==(const QTime &t) const
    +
    +    Returns \c true if this time is equal to \a t; otherwise returns \c false.
    +*/
    +
    +/*!
    +    \fn bool QTime::operator!=(const QTime &t) const
    +
    +    Returns \c true if this time is different from \a t; otherwise returns \c false.
    +*/
    +
    +/*!
    +    \fn bool QTime::operator<(const QTime &t) const
    +
    +    Returns \c true if this time is earlier than \a t; otherwise returns \c false.
    +*/
    +
    +/*!
    +    \fn bool QTime::operator<=(const QTime &t) const
    +
    +    Returns \c true if this time is earlier than or equal to \a t;
    +    otherwise returns \c false.
    +*/
    +
    +/*!
    +    \fn bool QTime::operator>(const QTime &t) const
    +
    +    Returns \c true if this time is later than \a t; otherwise returns \c false.
    +*/
    +
    +/*!
    +    \fn bool QTime::operator>=(const QTime &t) const
    +
    +    Returns \c true if this time is later than or equal to \a t;
    +    otherwise returns \c false.
    +*/
    +
    +/*!
    +    \fn QTime QTime::fromMSecsSinceStartOfDay(int msecs)
    +
    +    Returns a new QTime instance with the time set to the number of \a msecs
    +    since the start of the day, i.e. since 00:00:00.
    +
    +    If \a msecs falls outside the valid range an invalid QTime will be returned.
    +
    +    \sa msecsSinceStartOfDay()
    +*/
    +
    +/*!
    +    \fn int QTime::msecsSinceStartOfDay() const
    +
    +    Returns the number of msecs since the start of the day, i.e. since 00:00:00.
    +
    +    \sa fromMSecsSinceStartOfDay()
    +*/
    +
    +/*!
    +    \fn QTime::currentTime()
    +
    +    Returns the current time as reported by the system clock.
    +
    +    Note that the accuracy depends on the accuracy of the underlying
    +    operating system; not all systems provide 1-millisecond accuracy.
    +*/
    +
    +#if QT_CONFIG(datestring)
    +
    +static QTime fromIsoTimeString(const QStringRef &string, Qt::DateFormat format, bool *isMidnight24)
    +{
    +    if (isMidnight24)
    +        *isMidnight24 = false;
    +
    +    const int size = string.size();
    +    if (size < 5)
    +        return QTime();
    +
    +    bool ok = false;
    +    int hour = string.mid(0, 2).toInt(&ok);
    +    if (!ok)
    +        return QTime();
    +    const int minute = string.mid(3, 2).toInt(&ok);
    +    if (!ok)
    +        return QTime();
    +    int second = 0;
    +    int msec = 0;
    +
    +    if (size == 5) {
    +        // HH:mm format
    +        second = 0;
    +        msec = 0;
    +    } else if (string.at(5) == QLatin1Char(',') || string.at(5) == QLatin1Char('.')) {
    +        if (format == Qt::TextDate)
    +            return QTime();
    +        // ISODate HH:mm.ssssss format
    +        // We only want 5 digits worth of fraction of minute. This follows the existing
    +        // behavior that determines how milliseconds are read; 4 millisecond digits are
    +        // read and then rounded to 3. If we read at most 5 digits for fraction of minute,
    +        // the maximum amount of millisecond digits it will expand to once converted to
    +        // seconds is 4. E.g. 12:34,99999 will expand to 12:34:59.9994. The milliseconds
    +        // will then be rounded up AND clamped to 999.
    +
    +        const QStringRef minuteFractionStr = string.mid(6, 5);
    +        const long minuteFractionInt = minuteFractionStr.toLong(&ok);
    +        if (!ok)
    +            return QTime();
    +        const float minuteFraction = double(minuteFractionInt) / (std::pow(double(10), minuteFractionStr.count()));
    +
    +        const float secondWithMs = minuteFraction * 60;
    +        const float secondNoMs = std::floor(secondWithMs);
    +        const float secondFraction = secondWithMs - secondNoMs;
    +        second = secondNoMs;
    +        msec = qMin(qRound(secondFraction * 1000.0), 999);
    +    } else {
    +        // HH:mm:ss or HH:mm:ss.zzz
    +        second = string.mid(6, 2).toInt(&ok);
    +        if (!ok)
    +            return QTime();
    +        if (size > 8 && (string.at(8) == QLatin1Char(',') || string.at(8) == QLatin1Char('.'))) {
    +            const QStringRef msecStr(string.mid(9, 4));
    +            int msecInt = msecStr.isEmpty() ? 0 : msecStr.toInt(&ok);
    +            if (!ok)
    +                return QTime();
    +            const double secondFraction(msecInt / (std::pow(double(10), msecStr.count())));
    +            msec = qMin(qRound(secondFraction * 1000.0), 999);
    +        }
    +    }
    +
    +    const bool isISODate = format == Qt::ISODate || format == Qt::ISODateWithMs;
    +    if (isISODate && hour == 24 && minute == 0 && second == 0 && msec == 0) {
    +        if (isMidnight24)
    +            *isMidnight24 = true;
    +        hour = 0;
    +    }
    +
    +    return QTime(hour, minute, second, msec);
    +}
    +
    +/*!
    +    Returns the time represented in the \a string as a QTime using the
    +    \a format given, or an invalid time if this is not possible.
    +
    +    Note that fromString() uses a "C" locale encoded string to convert
    +    milliseconds to a float value. If the default locale is not "C",
    +    this may result in two conversion attempts (if the conversion
    +    fails for the default locale). This should be considered an
    +    implementation detail.
    +
    +    \sa toString(), QLocale::toTime()
    +*/
    +QTime QTime::fromString(const QString &string, Qt::DateFormat format)
    +{
    +    if (string.isEmpty())
    +        return QTime();
    +
    +    switch (format) {
    +    case Qt::SystemLocaleDate:
    +    case Qt::SystemLocaleShortDate:
    +        return QLocale::system().toTime(string, QLocale::ShortFormat);
    +    case Qt::SystemLocaleLongDate:
    +        return QLocale::system().toTime(string, QLocale::LongFormat);
    +    case Qt::LocaleDate:
    +    case Qt::DefaultLocaleShortDate:
    +        return QLocale().toTime(string, QLocale::ShortFormat);
    +    case Qt::DefaultLocaleLongDate:
    +        return QLocale().toTime(string, QLocale::LongFormat);
    +    case Qt::RFC2822Date:
    +        return rfcDateImpl(string).time;
    +    case Qt::ISODate:
    +    case Qt::ISODateWithMs:
    +    case Qt::TextDate:
    +    default:
    +        return fromIsoTimeString(QStringRef(&string), format, 0);
    +    }
    +}
    +
    +/*!
    +    Returns the QTime represented by the \a string, using the \a
    +    format given, or an invalid time if the string cannot be parsed.
    +
    +    These expressions may be used for the format:
    +
    +    \table
    +    \header \li Expression \li Output
    +    \row \li h
    +         \li the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
    +    \row \li hh
    +         \li the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
    +    \row \li m \li the minute without a leading zero (0 to 59)
    +    \row \li mm \li the minute with a leading zero (00 to 59)
    +    \row \li s \li the whole second, without any leading zero (0 to 59)
    +    \row \li ss \li the whole second, with a leading zero where applicable (00 to 59)
    +    \row \li z \li the fractional part of the second, to go after a decimal
    +                point, without trailing zeroes (0 to 999).  Thus "\c{s.z}"
    +                reports the seconds to full available (millisecond) precision
    +                without trailing zeroes.
    +    \row \li zzz \li the fractional part of the second, to millisecond
    +                precision, including trailing zeroes where applicable (000 to 999).
    +    \row \li AP
    +         \li interpret as an AM/PM time. \e AP must be either "AM" or "PM".
    +    \row \li ap
    +         \li Interpret as an AM/PM time. \e ap must be either "am" or "pm".
    +    \endtable
    +
    +    All other input characters will be treated as text. Any sequence
    +    of characters that are enclosed in single quotes will also be
    +    treated as text and not be used as an expression.
    +
    +    \snippet code/src_corelib_tools_qdatetime.cpp 6
    +
    +    If the format is not satisfied, an invalid QTime is returned.
    +    Expressions that do not expect leading zeroes to be given (h, m, s
    +    and z) are greedy. This means that they will use two digits even if
    +    this puts them outside the range of accepted values and leaves too
    +    few digits for other sections. For example, the following string
    +    could have meant 00:07:10, but the m will grab two digits, resulting
    +    in an invalid time:
    +
    +    \snippet code/src_corelib_tools_qdatetime.cpp 7
    +
    +    Any field that is not represented in the format will be set to zero.
    +    For example:
    +
    +    \snippet code/src_corelib_tools_qdatetime.cpp 8
    +
    +    \sa toString(), QDateTime::fromString(), QDate::fromString(),
    +    QLocale::toTime()
    +*/
    +
    +QTime QTime::fromString(const QString &string, const QString &format)
    +{
    +    QTime time;
    +#if QT_CONFIG(datetimeparser)
    +    QDateTimeParser dt(QVariant::Time, QDateTimeParser::FromString);
    +    // dt.setDefaultLocale(QLocale::c()); ### Qt 6
    +    if (dt.parseFormat(format))
    +        dt.fromString(string, 0, &time);
    +#else
    +    Q_UNUSED(string);
    +    Q_UNUSED(format);
    +#endif
    +    return time;
    +}
    +
    +#endif // datestring
    +
    +
    +/*!
    +    \overload
    +
    +    Returns \c true if the specified time is valid; otherwise returns
    +    false.
    +
    +    The time is valid if \a h is in the range 0 to 23, \a m and
    +    \a s are in the range 0 to 59, and \a ms is in the range 0 to 999.
    +
    +    Example:
    +
    +    \snippet code/src_corelib_tools_qdatetime.cpp 9
    +*/
    +
    +bool QTime::isValid(int h, int m, int s, int ms)
    +{
    +    return (uint)h < 24 && (uint)m < 60 && (uint)s < 60 && (uint)ms < 1000;
    +}
    +
    +#if QT_DEPRECATED_SINCE(5, 14) // ### Qt 6: remove
    +/*!
    +    Sets this time to the current time. This is practical for timing:
    +
    +    \snippet code/src_corelib_tools_qdatetime.cpp 10
    +
    +    \sa restart(), elapsed(), currentTime()
    +*/
    +
    +void QTime::start()
    +{
    +    *this = currentTime();
    +}
    +
    +/*!
    +    Sets this time to the current time and returns the number of
    +    milliseconds that have elapsed since the last time start() or
    +    restart() was called.
    +
    +    This function is guaranteed to be atomic and is thus very handy
    +    for repeated measurements. Call start() to start the first
    +    measurement, and restart() for each later measurement.
    +
    +    Note that the counter wraps to zero 24 hours after the last call
    +    to start() or restart().
    +
    +    \warning If the system's clock setting has been changed since the
    +    last time start() or restart() was called, the result is
    +    undefined. This can happen when daylight-saving time is turned on
    +    or off.
    +
    +    \sa start(), elapsed(), currentTime()
    +*/
    +
    +int QTime::restart()
    +{
    +    QTime t = currentTime();
    +    int n = msecsTo(t);
    +    if (n < 0)                                // passed midnight
    +        n += 86400*1000;
    +    *this = t;
    +    return n;
    +}
    +
    +/*!
    +    Returns the number of milliseconds that have elapsed since the
    +    last time start() or restart() was called.
    +
    +    Note that the counter wraps to zero 24 hours after the last call
    +    to start() or restart.
    +
    +    Note that the accuracy depends on the accuracy of the underlying
    +    operating system; not all systems provide 1-millisecond accuracy.
    +
    +    \warning If the system's clock setting has been changed since the
    +    last time start() or restart() was called, the result is
    +    undefined. This can happen when daylight-saving time is turned on
    +    or off.
    +
    +    \sa start(), restart()
    +*/
    +
    +int QTime::elapsed() const
    +{
    +    int n = msecsTo(currentTime());
    +    if (n < 0)                                // passed midnight
    +        n += 86400 * 1000;
    +    return n;
    +}
    +#endif // Use QElapsedTimer instead !
    +
    +/*****************************************************************************
    +  QDateTime static helper functions
    + *****************************************************************************/
    +
    +// get the types from QDateTime (through QDateTimePrivate)
    +typedef QDateTimePrivate::QDateTimeShortData ShortData;
    +typedef QDateTimePrivate::QDateTimeData QDateTimeData;
    +
    +// Returns the platform variant of timezone, i.e. the standard time offset
    +// The timezone external variable is documented as always holding the
    +// Standard Time offset as seconds west of Greenwich, i.e. UTC+01:00 is -3600
    +// Note this may not be historicaly accurate.
    +// Relies on tzset, mktime, or localtime having been called to populate timezone
    +static int qt_timezone()
    +{
    +#if defined(_MSC_VER)
    +        long offset;
    +        _get_timezone(&offset);
    +        return offset;
    +#elif defined(Q_OS_BSD4) && !defined(Q_OS_DARWIN)
    +        time_t clock = time(NULL);
    +        struct tm t;
    +        localtime_r(&clock, &t);
    +        // QTBUG-36080 Workaround for systems without the POSIX timezone
    +        // variable. This solution is not very efficient but fixing it is up to
    +        // the libc implementations.
    +        //
    +        // tm_gmtoff has some important differences compared to the timezone
    +        // variable:
    +        // - It returns the number of seconds east of UTC, and we want the
    +        //   number of seconds west of UTC.
    +        // - It also takes DST into account, so we need to adjust it to always
    +        //   get the Standard Time offset.
    +        return -t.tm_gmtoff + (t.tm_isdst ? (long)SECS_PER_HOUR : 0L);
    +#elif defined(Q_OS_INTEGRITY)
    +        return 0;
    +#else
    +        return timezone;
    +#endif // Q_OS_WIN
    +}
    +
    +// Returns the tzname, assume tzset has been called already
    +static QString qt_tzname(QDateTimePrivate::DaylightStatus daylightStatus)
    +{
    +    int isDst = (daylightStatus == QDateTimePrivate::DaylightTime) ? 1 : 0;
    +#if defined(Q_CC_MSVC)
    +    size_t s = 0;
    +    char name[512];
    +    if (_get_tzname(&s, name, 512, isDst))
    +        return QString();
    +    return QString::fromLocal8Bit(name);
    +#else
    +    return QString::fromLocal8Bit(tzname[isDst]);
    +#endif // Q_OS_WIN
    +}
    +
    +#if QT_CONFIG(datetimeparser) && QT_CONFIG(timezone)
    +/*
    +  \internal
    +  Implemented here to share qt_tzname()
    +*/
    +int QDateTimeParser::startsWithLocalTimeZone(const QStringRef name)
    +{
    +    QDateTimePrivate::DaylightStatus zones[2] = {
    +        QDateTimePrivate::StandardTime,
    +        QDateTimePrivate::DaylightTime
    +    };
    +    for (const auto z : zones) {
    +        QString zone(qt_tzname(z));
    +        if (name.startsWith(zone))
    +            return zone.size();
    +    }
    +    return 0;
    +}
    +#endif // datetimeparser && timezone
    +
    +// Calls the platform variant of mktime for the given date, time and daylightStatus,
    +// and updates the date, time, daylightStatus and abbreviation with the returned values
    +// If the date falls outside the 1970 to 2037 range supported by mktime / time_t
    +// then null date/time will be returned, you should adjust the date first if
    +// you need a guaranteed result.
    +static qint64 qt_mktime(QDate *date, QTime *time, QDateTimePrivate::DaylightStatus *daylightStatus,
    +                        QString *abbreviation, bool *ok = 0)
    +{
    +    const qint64 msec = time->msec();
    +    int yy, mm, dd;
    +    date->getDate(&yy, &mm, &dd);
    +
    +    // All other platforms provide standard C library time functions
    +    tm local;
    +    memset(&local, 0, sizeof(local)); // tm_[wy]day plus any non-standard fields
    +    local.tm_sec = time->second();
    +    local.tm_min = time->minute();
    +    local.tm_hour = time->hour();
    +    local.tm_mday = dd;
    +    local.tm_mon = mm - 1;
    +    local.tm_year = yy - 1900;
    +    if (daylightStatus)
    +        local.tm_isdst = int(*daylightStatus);
    +    else
    +        local.tm_isdst = -1;
    +
    +#if defined(Q_OS_WIN)
    +    int hh = local.tm_hour;
    +#endif // Q_OS_WIN
    +    time_t secsSinceEpoch = qMkTime(&local);
    +    if (secsSinceEpoch != time_t(-1)) {
    +        *date = QDate(local.tm_year + 1900, local.tm_mon + 1, local.tm_mday);
    +        *time = QTime(local.tm_hour, local.tm_min, local.tm_sec, msec);
    +#if defined(Q_OS_WIN)
    +        // Windows mktime for the missing hour subtracts 1 hour from the time
    +        // instead of adding 1 hour.  If time differs and is standard time then
    +        // this has happened, so add 2 hours to the time and 1 hour to the msecs
    +        if (local.tm_isdst == 0 && local.tm_hour != hh) {
    +            if (time->hour() >= 22)
    +                *date = date->addDays(1);
    +            *time = time->addSecs(2 * SECS_PER_HOUR);
    +            secsSinceEpoch += SECS_PER_HOUR;
    +            local.tm_isdst = 1;
    +        }
    +#endif // Q_OS_WIN
    +        if (local.tm_isdst >= 1) {
    +            if (daylightStatus)
    +                *daylightStatus = QDateTimePrivate::DaylightTime;
    +            if (abbreviation)
    +                *abbreviation = qt_tzname(QDateTimePrivate::DaylightTime);
    +        } else if (local.tm_isdst == 0) {
    +            if (daylightStatus)
    +                *daylightStatus = QDateTimePrivate::StandardTime;
    +            if (abbreviation)
    +                *abbreviation = qt_tzname(QDateTimePrivate::StandardTime);
    +        } else {
    +            if (daylightStatus)
    +                *daylightStatus = QDateTimePrivate::UnknownDaylightTime;
    +            if (abbreviation)
    +                *abbreviation = qt_tzname(QDateTimePrivate::StandardTime);
    +        }
    +        if (ok)
    +            *ok = true;
    +    } else {
    +        *date = QDate();
    +        *time = QTime();
    +        if (daylightStatus)
    +            *daylightStatus = QDateTimePrivate::UnknownDaylightTime;
    +        if (abbreviation)
    +            *abbreviation = QString();
    +        if (ok)
    +            *ok = false;
    +    }
    +
    +    return ((qint64)secsSinceEpoch * 1000) + msec;
    +}
    +
    +// Calls the platform variant of localtime for the given msecs, and updates
    +// the date, time, and DST status with the returned values.
    +static bool qt_localtime(qint64 msecsSinceEpoch, QDate *localDate, QTime *localTime,
    +                         QDateTimePrivate::DaylightStatus *daylightStatus)
    +{
    +    const time_t secsSinceEpoch = msecsSinceEpoch / 1000;
    +    const int msec = msecsSinceEpoch % 1000;
    +
    +    tm local;
    +    bool valid = false;
    +
    +    // localtime() is specified to work as if it called tzset().
    +    // localtime_r() does not have this constraint, so make an explicit call.
    +    // The explicit call should also request the timezone info be re-parsed.
    +    qTzSet();
    +#if QT_CONFIG(thread) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
    +    // Use the reentrant version of localtime() where available
    +    // as is thread-safe and doesn't use a shared static data area
    +    tm *res = 0;
    +    res = localtime_r(&secsSinceEpoch, &local);
    +    if (res)
    +        valid = true;
    +#elif defined(Q_CC_MSVC)
    +    if (!_localtime64_s(&local, &secsSinceEpoch))
    +        valid = true;
    +#else
    +    // Returns shared static data which may be overwritten at any time
    +    // So copy the result asap
    +    tm *res = 0;
    +    res = localtime(&secsSinceEpoch);
    +    if (res) {
    +        local = *res;
    +        valid = true;
    +    }
    +#endif
    +    if (valid) {
    +        *localDate = QDate(local.tm_year + 1900, local.tm_mon + 1, local.tm_mday);
    +        *localTime = QTime(local.tm_hour, local.tm_min, local.tm_sec, msec);
    +        if (daylightStatus) {
    +            if (local.tm_isdst > 0)
    +                *daylightStatus = QDateTimePrivate::DaylightTime;
    +            else if (local.tm_isdst < 0)
    +                *daylightStatus = QDateTimePrivate::UnknownDaylightTime;
    +            else
    +                *daylightStatus = QDateTimePrivate::StandardTime;
    +        }
    +        return true;
    +    } else {
    +        *localDate = QDate();
    +        *localTime = QTime();
    +        if (daylightStatus)
    +            *daylightStatus = QDateTimePrivate::UnknownDaylightTime;
    +        return false;
    +    }
    +}
    +
    +// Converts an msecs value into a date and time
    +static void msecsToTime(qint64 msecs, QDate *date, QTime *time)
    +{
    +    qint64 jd = JULIAN_DAY_FOR_EPOCH;
    +    qint64 ds = 0;
    +
    +    if (msecs >= MSECS_PER_DAY || msecs <= -MSECS_PER_DAY) {
    +        jd += msecs / MSECS_PER_DAY;
    +        msecs %= MSECS_PER_DAY;
    +    }
    +
    +    if (msecs < 0) {
    +        ds = MSECS_PER_DAY - msecs - 1;
    +        jd -= ds / MSECS_PER_DAY;
    +        ds = ds % MSECS_PER_DAY;
    +        ds = MSECS_PER_DAY - ds - 1;
    +    } else {
    +        ds = msecs;
    +    }
    +
    +    if (date)
    +        *date = QDate::fromJulianDay(jd);
    +    if (time)
    +        *time = QTime::fromMSecsSinceStartOfDay(ds);
    +}
    +
    +// Converts a date/time value into msecs
    +static qint64 timeToMSecs(const QDate &date, const QTime &time)
    +{
    +    return ((date.toJulianDay() - JULIAN_DAY_FOR_EPOCH) * MSECS_PER_DAY)
    +           + time.msecsSinceStartOfDay();
    +}
    +
    +// Convert an MSecs Since Epoch into Local Time
    +static bool epochMSecsToLocalTime(qint64 msecs, QDate *localDate, QTime *localTime,
    +                                  QDateTimePrivate::DaylightStatus *daylightStatus = 0)
    +{
    +    if (msecs < 0) {
    +        // Docs state any LocalTime before 1970-01-01 will *not* have any Daylight Time applied
    +        // Instead just use the standard offset from UTC to convert to UTC time
    +        qTzSet();
    +        msecsToTime(msecs - qt_timezone() * 1000, localDate, localTime);
    +        if (daylightStatus)
    +            *daylightStatus = QDateTimePrivate::StandardTime;
    +        return true;
    +    } else if (msecs > (qint64(TIME_T_MAX) * 1000)) {
    +        // Docs state any LocalTime after 2037-12-31 *will* have any DST applied
    +        // but this may fall outside the supported time_t range, so need to fake it.
    +        // Use existing method to fake the conversion, but this is deeply flawed as it may
    +        // apply the conversion from the wrong day number, e.g. if rule is last Sunday of month
    +        // TODO Use QTimeZone when available to apply the future rule correctly
    +        QDate utcDate;
    +        QTime utcTime;
    +        msecsToTime(msecs, &utcDate, &utcTime);
    +        int year, month, day;
    +        utcDate.getDate(&year, &month, &day);
    +        // 2037 is not a leap year, so make sure date isn't Feb 29
    +        if (month == 2 && day == 29)
    +            --day;
    +        QDate fakeDate(2037, month, day);
    +        qint64 fakeMsecs = QDateTime(fakeDate, utcTime, Qt::UTC).toMSecsSinceEpoch();
    +        bool res = qt_localtime(fakeMsecs, localDate, localTime, daylightStatus);
    +        *localDate = localDate->addDays(fakeDate.daysTo(utcDate));
    +        return res;
    +    } else {
    +        // Falls inside time_t suported range so can use localtime
    +        return qt_localtime(msecs, localDate, localTime, daylightStatus);
    +    }
    +}
    +
    +// Convert a LocalTime expressed in local msecs encoding and the corresponding
    +// DST status into a UTC epoch msecs. Optionally populate the returned
    +// values from mktime for the adjusted local date and time.
    +static qint64 localMSecsToEpochMSecs(qint64 localMsecs,
    +                                     QDateTimePrivate::DaylightStatus *daylightStatus,
    +                                     QDate *localDate = 0, QTime *localTime = 0,
    +                                     QString *abbreviation = 0)
    +{
    +    QDate dt;
    +    QTime tm;
    +    msecsToTime(localMsecs, &dt, &tm);
    +
    +    const qint64 msecsMax = qint64(TIME_T_MAX) * 1000;
    +
    +    if (localMsecs <= qint64(MSECS_PER_DAY)) {
    +
    +        // Docs state any LocalTime before 1970-01-01 will *not* have any DST applied
    +
    +        // First, if localMsecs is within +/- 1 day of minimum time_t try mktime in case it does
    +        // fall after minimum and needs proper DST conversion
    +        if (localMsecs >= -qint64(MSECS_PER_DAY)) {
    +            bool valid;
    +            qint64 utcMsecs = qt_mktime(&dt, &tm, daylightStatus, abbreviation, &valid);
    +            if (valid && utcMsecs >= 0) {
    +                // mktime worked and falls in valid range, so use it
    +                if (localDate)
    +                    *localDate = dt;
    +                if (localTime)
    +                    *localTime = tm;
    +                return utcMsecs;
    +            }
    +        } else {
    +            // If we don't call mktime then need to call tzset to get offset
    +            qTzSet();
    +        }
    +        // Time is clearly before 1970-01-01 so just use standard offset to convert
    +        qint64 utcMsecs = localMsecs + qt_timezone() * 1000;
    +        if (localDate || localTime)
    +            msecsToTime(localMsecs, localDate, localTime);
    +        if (daylightStatus)
    +            *daylightStatus = QDateTimePrivate::StandardTime;
    +        if (abbreviation)
    +            *abbreviation = qt_tzname(QDateTimePrivate::StandardTime);
    +        return utcMsecs;
    +
    +    } else if (localMsecs >= msecsMax - MSECS_PER_DAY) {
    +
    +        // Docs state any LocalTime after 2037-12-31 *will* have any DST applied
    +        // but this may fall outside the supported time_t range, so need to fake it.
    +
    +        // First, if localMsecs is within +/- 1 day of maximum time_t try mktime in case it does
    +        // fall before maximum and can use proper DST conversion
    +        if (localMsecs <= msecsMax + MSECS_PER_DAY) {
    +            bool valid;
    +            qint64 utcMsecs = qt_mktime(&dt, &tm, daylightStatus, abbreviation, &valid);
    +            if (valid && utcMsecs <= msecsMax) {
    +                // mktime worked and falls in valid range, so use it
    +                if (localDate)
    +                    *localDate = dt;
    +                if (localTime)
    +                    *localTime = tm;
    +                return utcMsecs;
    +            }
    +        }
    +        // Use existing method to fake the conversion, but this is deeply flawed as it may
    +        // apply the conversion from the wrong day number, e.g. if rule is last Sunday of month
    +        // TODO Use QTimeZone when available to apply the future rule correctly
    +        int year, month, day;
    +        dt.getDate(&year, &month, &day);
    +        // 2037 is not a leap year, so make sure date isn't Feb 29
    +        if (month == 2 && day == 29)
    +            --day;
    +        QDate fakeDate(2037, month, day);
    +        qint64 fakeDiff = fakeDate.daysTo(dt);
    +        qint64 utcMsecs = qt_mktime(&fakeDate, &tm, daylightStatus, abbreviation);
    +        if (localDate)
    +            *localDate = fakeDate.addDays(fakeDiff);
    +        if (localTime)
    +            *localTime = tm;
    +        QDate utcDate;
    +        QTime utcTime;
    +        msecsToTime(utcMsecs, &utcDate, &utcTime);
    +        utcDate = utcDate.addDays(fakeDiff);
    +        utcMsecs = timeToMSecs(utcDate, utcTime);
    +        return utcMsecs;
    +
    +    } else {
    +
    +        // Clearly falls inside 1970-2037 suported range so can use mktime
    +        qint64 utcMsecs = qt_mktime(&dt, &tm, daylightStatus, abbreviation);
    +        if (localDate)
    +            *localDate = dt;
    +        if (localTime)
    +            *localTime = tm;
    +        return utcMsecs;
    +
    +    }
    +}
    +
    +static inline bool specCanBeSmall(Qt::TimeSpec spec)
    +{
    +    return spec == Qt::LocalTime || spec == Qt::UTC;
    +}
    +
    +static inline bool msecsCanBeSmall(qint64 msecs)
    +{
    +    if (!QDateTimeData::CanBeSmall)
    +        return false;
    +
    +    ShortData sd;
    +    sd.msecs = qintptr(msecs);
    +    return sd.msecs == msecs;
    +}
    +
    +static Q_DECL_CONSTEXPR inline
    +QDateTimePrivate::StatusFlags mergeSpec(QDateTimePrivate::StatusFlags status, Qt::TimeSpec spec)
    +{
    +    return QDateTimePrivate::StatusFlags((status & ~QDateTimePrivate::TimeSpecMask) |
    +                                         (int(spec) << QDateTimePrivate::TimeSpecShift));
    +}
    +
    +static Q_DECL_CONSTEXPR inline Qt::TimeSpec extractSpec(QDateTimePrivate::StatusFlags status)
    +{
    +    return Qt::TimeSpec((status & QDateTimePrivate::TimeSpecMask) >> QDateTimePrivate::TimeSpecShift);
    +}
    +
    +// Set the Daylight Status if LocalTime set via msecs
    +static Q_DECL_RELAXED_CONSTEXPR inline QDateTimePrivate::StatusFlags
    +mergeDaylightStatus(QDateTimePrivate::StatusFlags sf, QDateTimePrivate::DaylightStatus status)
    +{
    +    sf &= ~QDateTimePrivate::DaylightMask;
    +    if (status == QDateTimePrivate::DaylightTime) {
    +        sf |= QDateTimePrivate::SetToDaylightTime;
    +    } else if (status == QDateTimePrivate::StandardTime) {
    +        sf |= QDateTimePrivate::SetToStandardTime;
    +    }
    +    return sf;
    +}
    +
    +// Get the DST Status if LocalTime set via msecs
    +static Q_DECL_RELAXED_CONSTEXPR inline
    +QDateTimePrivate::DaylightStatus extractDaylightStatus(QDateTimePrivate::StatusFlags status)
    +{
    +    if (status & QDateTimePrivate::SetToDaylightTime)
    +        return QDateTimePrivate::DaylightTime;
    +    if (status & QDateTimePrivate::SetToStandardTime)
    +        return QDateTimePrivate::StandardTime;
    +    return QDateTimePrivate::UnknownDaylightTime;
    +}
    +
    +static inline qint64 getMSecs(const QDateTimeData &d)
    +{
    +    if (d.isShort()) {
    +        // same as, but producing better code
    +        //return d.data.msecs;
    +        return qintptr(d.d) >> 8;
    +    }
    +    return d->m_msecs;
    +}
    +
    +static inline QDateTimePrivate::StatusFlags getStatus(const QDateTimeData &d)
    +{
    +    if (d.isShort()) {
    +        // same as, but producing better code
    +        //return StatusFlag(d.data.status);
    +        return QDateTimePrivate::StatusFlag(qintptr(d.d) & 0xFF);
    +    }
    +    return d->m_status;
    +}
    +
    +static inline Qt::TimeSpec getSpec(const QDateTimeData &d)
    +{
    +    return extractSpec(getStatus(d));
    +}
    +
    +#if QT_CONFIG(timezone)
    +void QDateTimePrivate::setUtcOffsetByTZ(qint64 atMSecsSinceEpoch)
    +{
    +    m_offsetFromUtc = m_timeZone.d->offsetFromUtc(atMSecsSinceEpoch);
    +}
    +#endif
    +
    +// Refresh the LocalTime validity and offset
    +static void refreshDateTime(QDateTimeData &d)
    +{
    +    auto status = getStatus(d);
    +    const auto spec = extractSpec(status);
    +    const qint64 msecs = getMSecs(d);
    +    qint64 epochMSecs = 0;
    +    int offsetFromUtc = 0;
    +    QDate testDate;
    +    QTime testTime;
    +    Q_ASSERT(spec == Qt::TimeZone || spec == Qt::LocalTime);
    +
    +#if QT_CONFIG(timezone)
    +    // If not valid time zone then is invalid
    +    if (spec == Qt::TimeZone) {
    +        if (!d->m_timeZone.isValid()) {
    +            status &= ~QDateTimePrivate::ValidDateTime;
    +        } else {
    +            epochMSecs = QDateTimePrivate::zoneMSecsToEpochMSecs(msecs, d->m_timeZone, extractDaylightStatus(status), &testDate, &testTime);
    +            d->setUtcOffsetByTZ(epochMSecs);
    +        }
    +    }
    +#endif // timezone
    +
    +    // If not valid date and time then is invalid
    +    if (!(status & QDateTimePrivate::ValidDate) || !(status & QDateTimePrivate::ValidTime)) {
    +        status &= ~QDateTimePrivate::ValidDateTime;
    +        if (status & QDateTimePrivate::ShortData) {
    +            d.data.status = status;
    +        } else {
    +            d->m_status = status;
    +            d->m_offsetFromUtc = 0;
    +        }
    +        return;
    +    }
    +
    +    // We have a valid date and time and a Qt::LocalTime or Qt::TimeZone that needs calculating
    +    // LocalTime and TimeZone might fall into a "missing" DST transition hour
    +    // Calling toEpochMSecs will adjust the returned date/time if it does
    +    if (spec == Qt::LocalTime) {
    +        auto dstStatus = extractDaylightStatus(status);
    +        epochMSecs = localMSecsToEpochMSecs(msecs, &dstStatus, &testDate, &testTime);
    +    }
    +    if (timeToMSecs(testDate, testTime) == msecs) {
    +        status |= QDateTimePrivate::ValidDateTime;
    +        // Cache the offset to use in offsetFromUtc()
    +        offsetFromUtc = (msecs - epochMSecs) / 1000;
    +    } else {
    +        status &= ~QDateTimePrivate::ValidDateTime;
    +    }
    +
    +    if (status & QDateTimePrivate::ShortData) {
    +        d.data.status = status;
    +    } else {
    +        d->m_status = status;
    +        d->m_offsetFromUtc = offsetFromUtc;
    +    }
    +}
    +
    +// Check the UTC / offsetFromUTC validity
    +static void checkValidDateTime(QDateTimeData &d)
    +{
    +    auto status = getStatus(d);
    +    auto spec = extractSpec(status);
    +    switch (spec) {
    +    case Qt::OffsetFromUTC:
    +    case Qt::UTC:
    +        // for these, a valid date and a valid time imply a valid QDateTime
    +        if ((status & QDateTimePrivate::ValidDate) && (status & QDateTimePrivate::ValidTime))
    +            status |= QDateTimePrivate::ValidDateTime;
    +        else
    +            status &= ~QDateTimePrivate::ValidDateTime;
    +        if (status & QDateTimePrivate::ShortData)
    +            d.data.status = status;
    +        else
    +            d->m_status = status;
    +        break;
    +    case Qt::TimeZone:
    +    case Qt::LocalTime:
    +        // for these, we need to check whether the timezone is valid and whether
    +        // the time is valid in that timezone. Expensive, but no other option.
    +        refreshDateTime(d);
    +        break;
    +    }
    +}
    +
    +static void setTimeSpec(QDateTimeData &d, Qt::TimeSpec spec, int offsetSeconds)
    +{
    +    auto status = getStatus(d);
    +    status &= ~(QDateTimePrivate::ValidDateTime | QDateTimePrivate::DaylightMask |
    +                QDateTimePrivate::TimeSpecMask);
    +
    +    switch (spec) {
    +    case Qt::OffsetFromUTC:
    +        if (offsetSeconds == 0)
    +            spec = Qt::UTC;
    +        break;
    +    case Qt::TimeZone:
    +        // Use system time zone instead
    +        spec = Qt::LocalTime;
    +        Q_FALLTHROUGH();
    +    case Qt::UTC:
    +    case Qt::LocalTime:
    +        offsetSeconds = 0;
    +        break;
    +    }
    +
    +    status = mergeSpec(status, spec);
    +    if (d.isShort() && offsetSeconds == 0) {
    +        d.data.status = status;
    +    } else {
    +        d.detach();
    +        d->m_status = status & ~QDateTimePrivate::ShortData;
    +        d->m_offsetFromUtc = offsetSeconds;
    +#if QT_CONFIG(timezone)
    +        d->m_timeZone = QTimeZone();
    +#endif // timezone
    +    }
    +}
    +
    +static void setDateTime(QDateTimeData &d, const QDate &date, const QTime &time)
    +{
    +    // If the date is valid and the time is not we set time to 00:00:00
    +    QTime useTime = time;
    +    if (!useTime.isValid() && date.isValid())
    +        useTime = QTime::fromMSecsSinceStartOfDay(0);
    +
    +    QDateTimePrivate::StatusFlags newStatus = 0;
    +
    +    // Set date value and status
    +    qint64 days = 0;
    +    if (date.isValid()) {
    +        days = date.toJulianDay() - JULIAN_DAY_FOR_EPOCH;
    +        newStatus = QDateTimePrivate::ValidDate;
    +    }
    +
    +    // Set time value and status
    +    int ds = 0;
    +    if (useTime.isValid()) {
    +        ds = useTime.msecsSinceStartOfDay();
    +        newStatus |= QDateTimePrivate::ValidTime;
    +    }
    +
    +    // Set msecs serial value
    +    qint64 msecs = (days * MSECS_PER_DAY) + ds;
    +    if (d.isShort()) {
    +        // let's see if we can keep this short
    +        if (msecsCanBeSmall(msecs)) {
    +            // yes, we can
    +            d.data.msecs = qintptr(msecs);
    +            d.data.status &= ~(QDateTimePrivate::ValidityMask | QDateTimePrivate::DaylightMask);
    +            d.data.status |= newStatus;
    +        } else {
    +            // nope...
    +            d.detach();
    +        }
    +    }
    +    if (!d.isShort()) {
    +        d.detach();
    +        d->m_msecs = msecs;
    +        d->m_status &= ~(QDateTimePrivate::ValidityMask | QDateTimePrivate::DaylightMask);
    +        d->m_status |= newStatus;
    +    }
    +
    +    // Set if date and time are valid
    +    checkValidDateTime(d);
    +}
    +
    +static QPair getDateTime(const QDateTimeData &d)
    +{
    +    QPair result;
    +    qint64 msecs = getMSecs(d);
    +    auto status = getStatus(d);
    +    msecsToTime(msecs, &result.first, &result.second);
    +
    +    if (!status.testFlag(QDateTimePrivate::ValidDate))
    +        result.first = QDate();
    +
    +    if (!status.testFlag(QDateTimePrivate::ValidTime))
    +        result.second = QTime();
    +
    +    return result;
    +}
    +
    +/*****************************************************************************
    +  QDateTime::Data member functions
    + *****************************************************************************/
    +
    +inline QDateTime::Data::Data()
    +{
    +    // default-constructed data has a special exception:
    +    // it can be small even if CanBeSmall == false
    +    // (optimization so we don't allocate memory in the default constructor)
    +    quintptr value = quintptr(mergeSpec(QDateTimePrivate::ShortData, Qt::LocalTime));
    +    d = reinterpret_cast(value);
    +}
    +
    +inline QDateTime::Data::Data(Qt::TimeSpec spec)
    +{
    +    if (CanBeSmall && Q_LIKELY(specCanBeSmall(spec))) {
    +        d = reinterpret_cast(quintptr(mergeSpec(QDateTimePrivate::ShortData, spec)));
    +    } else {
    +        // the structure is too small, we need to detach
    +        d = new QDateTimePrivate;
    +        d->ref.ref();
    +        d->m_status = mergeSpec(0, spec);
    +    }
    +}
    +
    +inline QDateTime::Data::Data(const Data &other)
    +    : d(other.d)
    +{
    +    if (!isShort()) {
    +        // check if we could shrink
    +        if (specCanBeSmall(extractSpec(d->m_status)) && msecsCanBeSmall(d->m_msecs)) {
    +            ShortData sd;
    +            sd.msecs = qintptr(d->m_msecs);
    +            sd.status = d->m_status | QDateTimePrivate::ShortData;
    +            data = sd;
    +        } else {
    +            // no, have to keep it big
    +            d->ref.ref();
    +        }
    +    }
    +}
    +
    +inline QDateTime::Data::Data(Data &&other)
    +    : d(other.d)
    +{
    +    // reset the other to a short state
    +    Data dummy;
    +    Q_ASSERT(dummy.isShort());
    +    other.d = dummy.d;
    +}
    +
    +inline QDateTime::Data &QDateTime::Data::operator=(const Data &other)
    +{
    +    if (d == other.d)
    +        return *this;
    +
    +    auto x = d;
    +    d = other.d;
    +    if (!other.isShort()) {
    +        // check if we could shrink
    +        if (specCanBeSmall(extractSpec(other.d->m_status)) && msecsCanBeSmall(other.d->m_msecs)) {
    +            ShortData sd;
    +            sd.msecs = qintptr(other.d->m_msecs);
    +            sd.status = other.d->m_status | QDateTimePrivate::ShortData;
    +            data = sd;
    +        } else {
    +            // no, have to keep it big
    +            other.d->ref.ref();
    +        }
    +    }
    +
    +    if (!(quintptr(x) & QDateTimePrivate::ShortData) && !x->ref.deref())
    +        delete x;
    +    return *this;
    +}
    +
    +inline QDateTime::Data::~Data()
    +{
    +    if (!isShort() && !d->ref.deref())
    +        delete d;
    +}
    +
    +inline bool QDateTime::Data::isShort() const
    +{
    +    bool b = quintptr(d) & QDateTimePrivate::ShortData;
    +
    +    // sanity check:
    +    Q_ASSERT(b || (d->m_status & QDateTimePrivate::ShortData) == 0);
    +
    +    // even if CanBeSmall = false, we have short data for a default-constructed
    +    // QDateTime object. But it's unlikely.
    +    if (CanBeSmall)
    +        return Q_LIKELY(b);
    +    return Q_UNLIKELY(b);
    +}
    +
    +inline void QDateTime::Data::detach()
    +{
    +    QDateTimePrivate *x;
    +    bool wasShort = isShort();
    +    if (wasShort) {
    +        // force enlarging
    +        x = new QDateTimePrivate;
    +        x->m_status = QDateTimePrivate::StatusFlag(data.status & ~QDateTimePrivate::ShortData);
    +        x->m_msecs = data.msecs;
    +    } else {
    +        if (d->ref.load() == 1)
    +            return;
    +
    +        x = new QDateTimePrivate(*d);
    +    }
    +
    +    x->ref.store(1);
    +    if (!wasShort && !d->ref.deref())
    +        delete d;
    +    d = x;
    +}
    +
    +inline const QDateTimePrivate *QDateTime::Data::operator->() const
    +{
    +    Q_ASSERT(!isShort());
    +    return d;
    +}
    +
    +inline QDateTimePrivate *QDateTime::Data::operator->()
    +{
    +    // should we attempt to detach here?
    +    Q_ASSERT(!isShort());
    +    Q_ASSERT(d->ref.load() == 1);
    +    return d;
    +}
    +
    +/*****************************************************************************
    +  QDateTimePrivate member functions
    + *****************************************************************************/
    +
    +Q_NEVER_INLINE
    +QDateTime::Data QDateTimePrivate::create(const QDate &toDate, const QTime &toTime, Qt::TimeSpec toSpec,
    +                                         int offsetSeconds)
    +{
    +    QDateTime::Data result(toSpec);
    +    setTimeSpec(result, toSpec, offsetSeconds);
    +    setDateTime(result, toDate, toTime);
    +    return result;
    +}
    +
    +#if QT_CONFIG(timezone)
    +inline QDateTime::Data QDateTimePrivate::create(const QDate &toDate, const QTime &toTime,
    +                                                const QTimeZone &toTimeZone)
    +{
    +    QDateTime::Data result(Qt::TimeZone);
    +    Q_ASSERT(!result.isShort());
    +
    +    result.d->m_status = mergeSpec(result.d->m_status, Qt::TimeZone);
    +    result.d->m_timeZone = toTimeZone;
    +    setDateTime(result, toDate, toTime);
    +    return result;
    +}
    +
    +// Convert a TimeZone time expressed in zone msecs encoding into a UTC epoch msecs
    +// DST transitions are disambiguated by hint.
    +inline qint64 QDateTimePrivate::zoneMSecsToEpochMSecs(qint64 zoneMSecs, const QTimeZone &zone,
    +                                                      DaylightStatus hint,
    +                                                      QDate *zoneDate, QTime *zoneTime)
    +{
    +    // Get the effective data from QTimeZone
    +    QTimeZonePrivate::Data data = zone.d->dataForLocalTime(zoneMSecs, int(hint));
    +    // Docs state any time before 1970-01-01 will *not* have any DST applied
    +    // but all affected times afterwards will have DST applied.
    +    if (data.atMSecsSinceEpoch < 0) {
    +        msecsToTime(zoneMSecs, zoneDate, zoneTime);
    +        return zoneMSecs - data.standardTimeOffset * 1000;
    +    } else {
    +        msecsToTime(data.atMSecsSinceEpoch + data.offsetFromUtc * 1000, zoneDate, zoneTime);
    +        return data.atMSecsSinceEpoch;
    +    }
    +}
    +#endif // timezone
    +
    +/*****************************************************************************
    +  QDateTime member functions
    + *****************************************************************************/
    +
    +/*!
    +    \class QDateTime
    +    \inmodule QtCore
    +    \ingroup shared
    +    \reentrant
    +    \brief The QDateTime class provides date and time functions.
    +
    +
    +    A QDateTime object encodes a calendar date and a clock time (a
    +    "datetime"). It combines features of the QDate and QTime classes.
    +    It can read the current datetime from the system clock. It
    +    provides functions for comparing datetimes and for manipulating a
    +    datetime by adding a number of seconds, days, months, or years.
    +
    +    A QDateTime object is typically created either by giving a date
    +    and time explicitly in the constructor, or by using the static
    +    function currentDateTime() that returns a QDateTime object set
    +    to the system clock's time. The date and time can be changed with
    +    setDate() and setTime(). A datetime can also be set using the
    +    setTime_t() function that takes a POSIX-standard "number of
    +    seconds since 00:00:00 on January 1, 1970" value. The fromString()
    +    function returns a QDateTime, given a string and a date format
    +    used to interpret the date within the string.
    +
    +    The date() and time() functions provide access to the date and
    +    time parts of the datetime. The same information is provided in
    +    textual format by the toString() function.
    +
    +    QDateTime provides a full set of operators to compare two
    +    QDateTime objects, where smaller means earlier and larger means
    +    later.
    +
    +    You can increment (or decrement) a datetime by a given number of
    +    milliseconds using addMSecs(), seconds using addSecs(), or days
    +    using addDays(). Similarly, you can use addMonths() and addYears().
    +    The daysTo() function returns the number of days between two datetimes,
    +    secsTo() returns the number of seconds between two datetimes, and
    +    msecsTo() returns the number of milliseconds between two datetimes.
    +
    +    QDateTime can store datetimes as \l{Qt::LocalTime}{local time} or
    +    as \l{Qt::UTC}{UTC}. QDateTime::currentDateTime() returns a
    +    QDateTime expressed as local time; use toUTC() to convert it to
    +    UTC. You can also use timeSpec() to find out if a QDateTime
    +    object stores a UTC time or a local time. Operations such as
    +    addSecs() and secsTo() are aware of daylight-saving time (DST).
    +
    +    \note QDateTime does not account for leap seconds.
    +
    +    \section1 Remarks
    +
    +    \section2 No Year 0
    +
    +    There is no year 0. Dates in that year are considered invalid. The
    +    year -1 is the year "1 before Christ" or "1 before current era."
    +    The day before 1 January 1 CE is 31 December 1 BCE.
    +
    +    \section2 Range of Valid Dates
    +
    +    The range of valid values able to be stored in QDateTime is dependent on
    +    the internal storage implementation. QDateTime is currently stored in a
    +    qint64 as a serial msecs value encoding the date and time.  This restricts
    +    the date range to about +/- 292 million years, compared to the QDate range
    +    of +/- 2 billion years.  Care must be taken when creating a QDateTime with
    +    extreme values that you do not overflow the storage.  The exact range of
    +    supported values varies depending on the Qt::TimeSpec and time zone.
    +
    +    \section2 Use of System Timezone
    +
    +    QDateTime uses the system's time zone information to determine the
    +    offset of local time from UTC. If the system is not configured
    +    correctly or not up-to-date, QDateTime will give wrong results as
    +    well.
    +
    +    \section2 Daylight-Saving Time (DST)
    +
    +    QDateTime takes into account the system's time zone information
    +    when dealing with DST. On modern Unix systems, this means it
    +    applies the correct historical DST data whenever possible. On
    +    Windows, where the system doesn't support historical DST data,
    +    historical accuracy is not maintained with respect to DST.
    +
    +    The range of valid dates taking DST into account is 1970-01-01 to
    +    the present, and rules are in place for handling DST correctly
    +    until 2037-12-31, but these could change. For dates falling
    +    outside that range, QDateTime makes a \e{best guess} using the
    +    rules for year 1970 or 2037, but we can't guarantee accuracy. This
    +    means QDateTime doesn't take into account changes in a locale's
    +    time zone before 1970, even if the system's time zone database
    +    supports that information.
    +
    +    QDateTime takes into consideration the Standard Time to Daylight-Saving Time
    +    transition.  For example if the transition is at 2am and the clock goes
    +    forward to 3am, then there is a "missing" hour from 02:00:00 to 02:59:59.999
    +    which QDateTime considers to be invalid.  Any date maths performed
    +    will take this missing hour into account and return a valid result.
    +
    +    \section2 Offset From UTC
    +
    +    A Qt::TimeSpec of Qt::OffsetFromUTC is also supported. This allows you
    +    to define a QDateTime relative to UTC at a fixed offset of a given number
    +    of seconds from UTC.  For example, an offset of +3600 seconds is one hour
    +    ahead of UTC and is usually written in ISO standard notation as
    +    "UTC+01:00".  Daylight-Saving Time never applies with this TimeSpec.
    +
    +    There is no explicit size restriction to the offset seconds, but there is
    +    an implicit limit imposed when using the toString() and fromString()
    +    methods which use a format of [+|-]hh:mm, effectively limiting the range
    +    to +/- 99 hours and 59 minutes and whole minutes only.  Note that currently
    +    no time zone lies outside the range of +/- 14 hours.
    +
    +    \section2 Time Zone Support
    +
    +    A Qt::TimeSpec of Qt::TimeZone is also supported in conjunction with the
    +    QTimeZone class.  This allows you to define a datetime in a named time zone
    +    adhering to a consistent set of daylight-saving transition rules.  For
    +    example a time zone of "Europe/Berlin" will apply the daylight-saving
    +    rules as used in Germany since 1970.  Note that the transition rules
    +    applied depend on the platform support.  See the QTimeZone documentation
    +    for more details.
    +
    +    \sa QDate, QTime, QDateTimeEdit, QTimeZone
    +*/
    +
    +/*!
    +    Constructs a null datetime (i.e. null date and null time). A null
    +    datetime is invalid, since the date is invalid.
    +
    +    \sa isValid()
    +*/
    +QDateTime::QDateTime() noexcept(Data::CanBeSmall)
    +{
    +}
    +
    +
    +/*!
    +    Constructs a datetime with the given \a date, a valid
    +    time(00:00:00.000), and sets the timeSpec() to Qt::LocalTime.
    +*/
    +
    +QDateTime::QDateTime(const QDate &date)
    +    : d(QDateTimePrivate::create(date, QTime(0, 0), Qt::LocalTime, 0))
    +{
    +}
    +
    +/*!
    +    Constructs a datetime with the given \a date and \a time, using
    +    the time specification defined by \a spec.
    +
    +    If \a date is valid and \a time is not, the time will be set to midnight.
    +
    +    If \a spec is Qt::OffsetFromUTC then it will be set to Qt::UTC, i.e. an
    +    offset of 0 seconds. To create a Qt::OffsetFromUTC datetime use the
    +    correct constructor.
    +
    +    If \a spec is Qt::TimeZone then the spec will be set to Qt::LocalTime,
    +    i.e. the current system time zone.  To create a Qt::TimeZone datetime
    +    use the correct constructor.
    +*/
    +
    +QDateTime::QDateTime(const QDate &date, const QTime &time, Qt::TimeSpec spec)
    +    : d(QDateTimePrivate::create(date, time, spec, 0))
    +{
    +}
    +
    +/*!
    +    \since 5.2
    +
    +    Constructs a datetime with the given \a date and \a time, using
    +    the time specification defined by \a spec and \a offsetSeconds seconds.
    +
    +    If \a date is valid and \a time is not, the time will be set to midnight.
    +
    +    If the \a spec is not Qt::OffsetFromUTC then \a offsetSeconds will be ignored.
    +
    +    If the \a spec is Qt::OffsetFromUTC and \a offsetSeconds is 0 then the
    +    timeSpec() will be set to Qt::UTC, i.e. an offset of 0 seconds.
    +
    +    If \a spec is Qt::TimeZone then the spec will be set to Qt::LocalTime,
    +    i.e. the current system time zone.  To create a Qt::TimeZone datetime
    +    use the correct constructor.
    +*/
    +
    +QDateTime::QDateTime(const QDate &date, const QTime &time, Qt::TimeSpec spec, int offsetSeconds)
    +         : d(QDateTimePrivate::create(date, time, spec, offsetSeconds))
    +{
    +}
    +
    +#if QT_CONFIG(timezone)
    +/*!
    +    \since 5.2
    +
    +    Constructs a datetime with the given \a date and \a time, using
    +    the Time Zone specified by \a timeZone.
    +
    +    If \a date is valid and \a time is not, the time will be set to 00:00:00.
    +
    +    If \a timeZone is invalid then the datetime will be invalid.
    +*/
    +
    +QDateTime::QDateTime(const QDate &date, const QTime &time, const QTimeZone &timeZone)
    +    : d(QDateTimePrivate::create(date, time, timeZone))
    +{
    +}
    +#endif // timezone
    +
    +/*!
    +    Constructs a copy of the \a other datetime.
    +*/
    +QDateTime::QDateTime(const QDateTime &other) noexcept
    +    : d(other.d)
    +{
    +}
    +
    +/*!
    +    \since 5.8
    +    Moves the content of the temporary \a other datetime to this object and
    +    leaves \a other in an unspecified (but proper) state.
    +*/
    +QDateTime::QDateTime(QDateTime &&other) noexcept
    +    : d(std::move(other.d))
    +{
    +}
    +
    +/*!
    +    Destroys the datetime.
    +*/
    +QDateTime::~QDateTime()
    +{
    +}
    +
    +/*!
    +    Makes a copy of the \a other datetime and returns a reference to the
    +    copy.
    +*/
    +
    +QDateTime &QDateTime::operator=(const QDateTime &other) noexcept
    +{
    +    d = other.d;
    +    return *this;
    +}
    +/*!
    +    \fn void QDateTime::swap(QDateTime &other)
    +    \since 5.0
    +
    +    Swaps this datetime with \a other. This operation is very fast
    +    and never fails.
    +*/
    +
    +/*!
    +    Returns \c true if both the date and the time are null; otherwise
    +    returns \c false. A null datetime is invalid.
    +
    +    \sa QDate::isNull(), QTime::isNull(), isValid()
    +*/
    +
    +bool QDateTime::isNull() const
    +{
    +    auto status = getStatus(d);
    +    return !status.testFlag(QDateTimePrivate::ValidDate) &&
    +            !status.testFlag(QDateTimePrivate::ValidTime);
    +}
    +
    +/*!
    +    Returns \c true if both the date and the time are valid and they are valid in
    +    the current Qt::TimeSpec, otherwise returns \c false.
    +
    +    If the timeSpec() is Qt::LocalTime or Qt::TimeZone then the date and time are
    +    checked to see if they fall in the Standard Time to Daylight-Saving Time transition
    +    hour, i.e. if the transition is at 2am and the clock goes forward to 3am
    +    then the time from 02:00:00 to 02:59:59.999 is considered to be invalid.
    +
    +    \sa QDate::isValid(), QTime::isValid()
    +*/
    +
    +bool QDateTime::isValid() const
    +{
    +    auto status = getStatus(d);
    +    return status & QDateTimePrivate::ValidDateTime;
    +}
    +
    +/*!
    +    Returns the date part of the datetime.
    +
    +    \sa setDate(), time(), timeSpec()
    +*/
    +
    +QDate QDateTime::date() const
    +{
    +    auto status = getStatus(d);
    +    if (!status.testFlag(QDateTimePrivate::ValidDate))
    +        return QDate();
    +    QDate dt;
    +    msecsToTime(getMSecs(d), &dt, 0);
    +    return dt;
    +}
    +
    +/*!
    +    Returns the time part of the datetime.
    +
    +    \sa setTime(), date(), timeSpec()
    +*/
    +
    +QTime QDateTime::time() const
    +{
    +    auto status = getStatus(d);
    +    if (!status.testFlag(QDateTimePrivate::ValidTime))
    +        return QTime();
    +    QTime tm;
    +    msecsToTime(getMSecs(d), 0, &tm);
    +    return tm;
    +}
    +
    +/*!
    +    Returns the time specification of the datetime.
    +
    +    \sa setTimeSpec(), date(), time(), Qt::TimeSpec
    +*/
    +
    +Qt::TimeSpec QDateTime::timeSpec() const
    +{
    +    return getSpec(d);
    +}
    +
    +#if QT_CONFIG(timezone)
    +/*!
    +    \since 5.2
    +
    +    Returns the time zone of the datetime.
    +
    +    If the timeSpec() is Qt::LocalTime then an instance of the current system
    +    time zone will be returned. Note however that if you copy this time zone
    +    the instance will not remain in sync if the system time zone changes.
    +
    +    \sa setTimeZone(), Qt::TimeSpec
    +*/
    +
    +QTimeZone QDateTime::timeZone() const
    +{
    +    switch (getSpec(d)) {
    +    case Qt::UTC:
    +        return QTimeZone::utc();
    +    case Qt::OffsetFromUTC:
    +        return QTimeZone(d->m_offsetFromUtc);
    +    case Qt::TimeZone:
    +        Q_ASSERT(d->m_timeZone.isValid());
    +        return d->m_timeZone;
    +    case Qt::LocalTime:
    +        return QTimeZone::systemTimeZone();
    +    }
    +    return QTimeZone();
    +}
    +#endif // timezone
    +
    +/*!
    +    \since 5.2
    +
    +    Returns the current Offset From UTC in seconds.
    +
    +    If the timeSpec() is Qt::OffsetFromUTC this will be the value originally set.
    +
    +    If the timeSpec() is Qt::TimeZone this will be the offset effective in the
    +    Time Zone including any Daylight-Saving Offset.
    +
    +    If the timeSpec() is Qt::LocalTime this will be the difference between the
    +    Local Time and UTC including any Daylight-Saving Offset.
    +
    +    If the timeSpec() is Qt::UTC this will be 0.
    +
    +    \sa setOffsetFromUtc()
    +*/
    +
    +int QDateTime::offsetFromUtc() const
    +{
    +    if (!d.isShort())
    +        return d->m_offsetFromUtc;
    +    if (!isValid())
    +        return 0;
    +
    +    auto spec = getSpec(d);
    +    if (spec == Qt::LocalTime) {
    +        // we didn't cache the value, so we need to calculate it now...
    +        qint64 msecs = getMSecs(d);
    +        return (msecs - toMSecsSinceEpoch()) / 1000;
    +    }
    +
    +    Q_ASSERT(spec == Qt::UTC);
    +    return 0;
    +}
    +
    +/*!
    +    \since 5.2
    +
    +    Returns the Time Zone Abbreviation for the datetime.
    +
    +    If the timeSpec() is Qt::UTC this will be "UTC".
    +
    +    If the timeSpec() is Qt::OffsetFromUTC this will be in the format
    +    "UTC[+-]00:00".
    +
    +    If the timeSpec() is Qt::LocalTime then the host system is queried for the
    +    correct abbreviation.
    +
    +    Note that abbreviations may or may not be localized.
    +
    +    Note too that the abbreviation is not guaranteed to be a unique value,
    +    i.e. different time zones may have the same abbreviation.
    +
    +    \sa timeSpec()
    +*/
    +
    +QString QDateTime::timeZoneAbbreviation() const
    +{
    +    switch (getSpec(d)) {
    +    case Qt::UTC:
    +        return QLatin1String("UTC");
    +    case Qt::OffsetFromUTC:
    +        return QLatin1String("UTC") + toOffsetString(Qt::ISODate, d->m_offsetFromUtc);
    +    case Qt::TimeZone:
    +#if !QT_CONFIG(timezone)
    +        break;
    +#else
    +        return d->m_timeZone.d->abbreviation(toMSecsSinceEpoch());
    +#endif // timezone
    +    case Qt::LocalTime:  {
    +        QString abbrev;
    +        auto status = extractDaylightStatus(getStatus(d));
    +        localMSecsToEpochMSecs(getMSecs(d), &status, 0, 0, &abbrev);
    +        return abbrev;
    +        }
    +    }
    +    return QString();
    +}
    +
    +/*!
    +    \since 5.2
    +
    +    Returns if this datetime falls in Daylight-Saving Time.
    +
    +    If the Qt::TimeSpec is not Qt::LocalTime or Qt::TimeZone then will always
    +    return false.
    +
    +    \sa timeSpec()
    +*/
    +
    +bool QDateTime::isDaylightTime() const
    +{
    +    switch (getSpec(d)) {
    +    case Qt::UTC:
    +    case Qt::OffsetFromUTC:
    +        return false;
    +    case Qt::TimeZone:
    +#if !QT_CONFIG(timezone)
    +        break;
    +#else
    +        return d->m_timeZone.d->isDaylightTime(toMSecsSinceEpoch());
    +#endif // timezone
    +    case Qt::LocalTime: {
    +        auto status = extractDaylightStatus(getStatus(d));
    +        if (status == QDateTimePrivate::UnknownDaylightTime)
    +            localMSecsToEpochMSecs(getMSecs(d), &status);
    +        return (status == QDateTimePrivate::DaylightTime);
    +        }
    +    }
    +    return false;
    +}
    +
    +/*!
    +    Sets the date part of this datetime to \a date. If no time is set yet, it
    +    is set to midnight. If \a date is invalid, this QDateTime becomes invalid.
    +
    +    \sa date(), setTime(), setTimeSpec()
    +*/
    +
    +void QDateTime::setDate(const QDate &date)
    +{
    +    setDateTime(d, date, time());
    +}
    +
    +/*!
    +    Sets the time part of this datetime to \a time. If \a time is not valid,
    +    this function sets it to midnight. Therefore, it's possible to clear any
    +    set time in a QDateTime by setting it to a default QTime:
    +
    +    \code
    +        QDateTime dt = QDateTime::currentDateTime();
    +        dt.setTime(QTime());
    +    \endcode
    +
    +    \sa time(), setDate(), setTimeSpec()
    +*/
    +
    +void QDateTime::setTime(const QTime &time)
    +{
    +    setDateTime(d, date(), time);
    +}
    +
    +/*!
    +    Sets the time specification used in this datetime to \a spec.
    +    The datetime will refer to a different point in time.
    +
    +    If \a spec is Qt::OffsetFromUTC then the timeSpec() will be set
    +    to Qt::UTC, i.e. an effective offset of 0.
    +
    +    If \a spec is Qt::TimeZone then the spec will be set to Qt::LocalTime,
    +    i.e. the current system time zone.
    +
    +    Example:
    +    \snippet code/src_corelib_tools_qdatetime.cpp 19
    +
    +    \sa timeSpec(), setDate(), setTime(), setTimeZone(), Qt::TimeSpec
    +*/
    +
    +void QDateTime::setTimeSpec(Qt::TimeSpec spec)
    +{
    +    QT_PREPEND_NAMESPACE(setTimeSpec(d, spec, 0));
    +    checkValidDateTime(d);
    +}
    +
    +/*!
    +    \since 5.2
    +
    +    Sets the timeSpec() to Qt::OffsetFromUTC and the offset to \a offsetSeconds.
    +    The datetime will refer to a different point in time.
    +
    +    The maximum and minimum offset is 14 positive or negative hours.  If
    +    \a offsetSeconds is larger or smaller than that, then the result is
    +    undefined.
    +
    +    If \a offsetSeconds is 0 then the timeSpec() will be set to Qt::UTC.
    +
    +    \sa isValid(), offsetFromUtc()
    +*/
    +
    +void QDateTime::setOffsetFromUtc(int offsetSeconds)
    +{
    +    QT_PREPEND_NAMESPACE(setTimeSpec(d, Qt::OffsetFromUTC, offsetSeconds));
    +    checkValidDateTime(d);
    +}
    +
    +#if QT_CONFIG(timezone)
    +/*!
    +    \since 5.2
    +
    +    Sets the time zone used in this datetime to \a toZone.
    +    The datetime will refer to a different point in time.
    +
    +    If \a toZone is invalid then the datetime will be invalid.
    +
    +    \sa timeZone(), Qt::TimeSpec
    +*/
    +
    +void QDateTime::setTimeZone(const QTimeZone &toZone)
    +{
    +    d.detach();         // always detach
    +    d->m_status = mergeSpec(d->m_status, Qt::TimeZone);
    +    d->m_offsetFromUtc = 0;
    +    d->m_timeZone = toZone;
    +    refreshDateTime(d);
    +}
    +#endif // timezone
    +
    +/*!
    +    \since 4.7
    +
    +    Returns the datetime as the number of milliseconds that have passed
    +    since 1970-01-01T00:00:00.000, Coordinated Universal Time (Qt::UTC).
    +
    +    On systems that do not support time zones, this function will
    +    behave as if local time were Qt::UTC.
    +
    +    The behavior for this function is undefined if the datetime stored in
    +    this object is not valid. However, for all valid dates, this function
    +    returns a unique value.
    +
    +    \sa toSecsSinceEpoch(), setMSecsSinceEpoch()
    +*/
    +qint64 QDateTime::toMSecsSinceEpoch() const
    +{
    +    switch (getSpec(d)) {
    +    case Qt::UTC:
    +        return getMSecs(d);
    +
    +    case Qt::OffsetFromUTC:
    +        return d->m_msecs - (d->m_offsetFromUtc * 1000);
    +
    +    case Qt::LocalTime: {
    +        // recalculate the local timezone
    +        auto status = extractDaylightStatus(getStatus(d));
    +        return localMSecsToEpochMSecs(getMSecs(d), &status);
    +    }
    +
    +    case Qt::TimeZone:
    +#if !QT_CONFIG(timezone)
    +        return 0;
    +#else
    +        return QDateTimePrivate::zoneMSecsToEpochMSecs(d->m_msecs, d->m_timeZone,
    +                                                       extractDaylightStatus(getStatus(d)));
    +#endif
    +    }
    +    Q_UNREACHABLE();
    +    return 0;
    +}
    +
    +/*!
    +    \since 5.8
    +
    +    Returns the datetime as the number of seconds that have passed since
    +    1970-01-01T00:00:00.000, Coordinated Universal Time (Qt::UTC).
    +
    +    On systems that do not support time zones, this function will
    +    behave as if local time were Qt::UTC.
    +
    +    The behavior for this function is undefined if the datetime stored in
    +    this object is not valid. However, for all valid dates, this function
    +    returns a unique value.
    +
    +    \sa toMSecsSinceEpoch(), setSecsSinceEpoch()
    +*/
    +qint64 QDateTime::toSecsSinceEpoch() const
    +{
    +    return toMSecsSinceEpoch() / 1000;
    +}
    +
    +#if QT_DEPRECATED_SINCE(5, 8)
    +/*!
    +    \deprecated
    +
    +    Returns the datetime as the number of seconds that have passed
    +    since 1970-01-01T00:00:00, Coordinated Universal Time (Qt::UTC).
    +
    +    On systems that do not support time zones, this function will
    +    behave as if local time were Qt::UTC.
    +
    +    \note This function returns a 32-bit unsigned integer and is deprecated.
    +
    +    If the date is outside the range 1970-01-01T00:00:00 to
    +    2106-02-07T06:28:14, this function returns -1 cast to an unsigned integer
    +    (i.e., 0xFFFFFFFF).
    +
    +    To get an extended range, use toMSecsSinceEpoch() or toSecsSinceEpoch().
    +
    +    \sa toSecsSinceEpoch(), toMSecsSinceEpoch(), setTime_t()
    +*/
    +
    +uint QDateTime::toTime_t() const
    +{
    +    if (!isValid())
    +        return uint(-1);
    +    qint64 retval = toMSecsSinceEpoch() / 1000;
    +    if (quint64(retval) >= Q_UINT64_C(0xFFFFFFFF))
    +        return uint(-1);
    +    return uint(retval);
    +}
    +#endif
    +
    +/*!
    +    \since 4.7
    +
    +    Sets the date and time given the number of milliseconds \a msecs that have
    +    passed since 1970-01-01T00:00:00.000, Coordinated Universal Time
    +    (Qt::UTC). On systems that do not support time zones this function
    +    will behave as if local time were Qt::UTC.
    +
    +    Note that passing the minimum of \c qint64
    +    (\c{std::numeric_limits::min()}) to \a msecs will result in
    +    undefined behavior.
    +
    +    \sa toMSecsSinceEpoch(), setSecsSinceEpoch()
    +*/
    +void QDateTime::setMSecsSinceEpoch(qint64 msecs)
    +{
    +    const auto spec = getSpec(d);
    +    auto status = getStatus(d);
    +
    +    status &= ~QDateTimePrivate::ValidityMask;
    +    switch (spec) {
    +    case Qt::UTC:
    +        status = status
    +                    | QDateTimePrivate::ValidDate
    +                    | QDateTimePrivate::ValidTime
    +                    | QDateTimePrivate::ValidDateTime;
    +        break;
    +    case Qt::OffsetFromUTC:
    +        msecs = msecs + (d->m_offsetFromUtc * 1000);
    +        status = status
    +                    | QDateTimePrivate::ValidDate
    +                    | QDateTimePrivate::ValidTime
    +                    | QDateTimePrivate::ValidDateTime;
    +        break;
    +    case Qt::TimeZone:
    +        Q_ASSERT(!d.isShort());
    +#if QT_CONFIG(timezone)
    +        // Docs state any LocalTime before 1970-01-01 will *not* have any DST applied
    +        // but all affected times afterwards will have DST applied.
    +        d.detach();
    +        if (msecs >= 0) {
    +            status = mergeDaylightStatus(status,
    +                                         d->m_timeZone.d->isDaylightTime(msecs)
    +                                         ? QDateTimePrivate::DaylightTime
    +                                         : QDateTimePrivate::StandardTime);
    +            d->m_offsetFromUtc = d->m_timeZone.d->offsetFromUtc(msecs);
    +        } else {
    +            status = mergeDaylightStatus(status, QDateTimePrivate::StandardTime);
    +            d->m_offsetFromUtc = d->m_timeZone.d->standardTimeOffset(msecs);
    +        }
    +        msecs = msecs + (d->m_offsetFromUtc * 1000);
    +        status = status
    +                    | QDateTimePrivate::ValidDate
    +                    | QDateTimePrivate::ValidTime
    +                    | QDateTimePrivate::ValidDateTime;
    +#endif // timezone
    +        break;
    +    case Qt::LocalTime: {
    +        QDate dt;
    +        QTime tm;
    +        QDateTimePrivate::DaylightStatus dstStatus;
    +        epochMSecsToLocalTime(msecs, &dt, &tm, &dstStatus);
    +        setDateTime(d, dt, tm);
    +        msecs = getMSecs(d);
    +        status = mergeDaylightStatus(getStatus(d), dstStatus);
    +        break;
    +        }
    +    }
    +
    +    if (msecsCanBeSmall(msecs) && d.isShort()) {
    +        // we can keep short
    +        d.data.msecs = qintptr(msecs);
    +        d.data.status = status;
    +    } else {
    +        d.detach();
    +        d->m_status = status & ~QDateTimePrivate::ShortData;
    +        d->m_msecs = msecs;
    +    }
    +
    +    if (spec == Qt::LocalTime || spec == Qt::TimeZone)
    +        refreshDateTime(d);
    +}
    +
    +/*!
    +    \since 5.8
    +
    +    Sets the date and time given the number of seconds \a secs that have
    +    passed since 1970-01-01T00:00:00.000, Coordinated Universal Time
    +    (Qt::UTC). On systems that do not support time zones this function
    +    will behave as if local time were Qt::UTC.
    +
    +    \sa toSecsSinceEpoch(), setMSecsSinceEpoch()
    +*/
    +void QDateTime::setSecsSinceEpoch(qint64 secs)
    +{
    +    setMSecsSinceEpoch(secs * 1000);
    +}
    +
    +#if QT_DEPRECATED_SINCE(5, 8)
    +/*!
    +    \fn void QDateTime::setTime_t(uint seconds)
    +    \deprecated
    +
    +    Sets the date and time given the number of \a seconds that have
    +    passed since 1970-01-01T00:00:00, Coordinated Universal Time
    +    (Qt::UTC). On systems that do not support time zones this function
    +    will behave as if local time were Qt::UTC.
    +
    +    \note This function is deprecated. For new code, use setSecsSinceEpoch().
    +
    +    \sa toTime_t()
    +*/
    +
    +void QDateTime::setTime_t(uint secsSince1Jan1970UTC)
    +{
    +    setMSecsSinceEpoch((qint64)secsSince1Jan1970UTC * 1000);
    +}
    +#endif
    +
    +#if QT_CONFIG(datestring)
    +/*!
    +    \fn QString QDateTime::toString(Qt::DateFormat format) const
    +
    +    \overload
    +
    +    Returns the datetime as a string in the \a format given.
    +
    +    If the \a format is Qt::TextDate, the string is formatted in
    +    the default way. QDate::shortDayName(), QDate::shortMonthName(),
    +    and QTime::toString() are used to generate the string, so the
    +    day and month names will be localized names using the system locale,
    +    i.e. QLocale::system(). An example of this formatting is
    +    "Wed May 20 03:40:13 1998".
    +
    +    If the \a format is Qt::ISODate, the string format corresponds
    +    to the ISO 8601 extended specification for representations of
    +    dates and times, taking the form yyyy-MM-ddTHH:mm:ss[Z|[+|-]HH:mm],
    +    depending on the timeSpec() of the QDateTime. If the timeSpec()
    +    is Qt::UTC, Z will be appended to the string; if the timeSpec() is
    +    Qt::OffsetFromUTC, the offset in hours and minutes from UTC will
    +    be appended to the string. To include milliseconds in the ISO 8601
    +    date, use the \a format Qt::ISODateWithMs, which corresponds to
    +    yyyy-MM-ddTHH:mm:ss.zzz[Z|[+|-]HH:mm].
    +
    +    If the \a format is Qt::SystemLocaleShortDate or
    +    Qt::SystemLocaleLongDate, the string format depends on the locale
    +    settings of the system. Identical to calling
    +    QLocale::system().toString(datetime, QLocale::ShortFormat) or
    +    QLocale::system().toString(datetime, QLocale::LongFormat).
    +
    +    If the \a format is Qt::DefaultLocaleShortDate or
    +    Qt::DefaultLocaleLongDate, the string format depends on the
    +    default application locale. This is the locale set with
    +    QLocale::setDefault(), or the system locale if no default locale
    +    has been set. Identical to calling QLocale().toString(datetime,
    +    QLocale::ShortFormat) or QLocale().toString(datetime,
    +    QLocale::LongFormat).
    +
    +    If the \a format is Qt::RFC2822Date, the string is formatted
    +    following \l{RFC 2822}.
    +
    +    If the datetime is invalid, an empty string will be returned.
    +
    +    \warning The Qt::ISODate format is only valid for years in the
    +    range 0 to 9999. This restriction may apply to locale-aware
    +    formats as well, depending on the locale settings.
    +
    +    \sa fromString(), QDate::toString(), QTime::toString(),
    +    QLocale::toString()
    +*/
    +
    +QString QDateTime::toString(Qt::DateFormat format) const
    +{
    +    QString buf;
    +    if (!isValid())
    +        return buf;
    +
    +    switch (format) {
    +    case Qt::SystemLocaleDate:
    +    case Qt::SystemLocaleShortDate:
    +        return QLocale::system().toString(*this, QLocale::ShortFormat);
    +    case Qt::SystemLocaleLongDate:
    +        return QLocale::system().toString(*this, QLocale::LongFormat);
    +    case Qt::LocaleDate:
    +    case Qt::DefaultLocaleShortDate:
    +        return QLocale().toString(*this, QLocale::ShortFormat);
    +    case Qt::DefaultLocaleLongDate:
    +        return QLocale().toString(*this, QLocale::LongFormat);
    +    case Qt::RFC2822Date: {
    +        buf = QLocale::c().toString(*this, QStringViewLiteral("dd MMM yyyy hh:mm:ss "));
    +        buf += toOffsetString(Qt::TextDate, offsetFromUtc());
    +        return buf;
    +    }
    +    default:
    +#if QT_CONFIG(textdate)
    +    case Qt::TextDate: {
    +        const QPair p = getDateTime(d);
    +        buf = p.first.toString(Qt::TextDate);
    +        // Insert time between date's day and year:
    +        buf.insert(buf.lastIndexOf(QLatin1Char(' ')),
    +                   QLatin1Char(' ') + p.second.toString(Qt::TextDate));
    +        // Append zone/offset indicator, as appropriate:
    +        switch (timeSpec()) {
    +        case Qt::LocalTime:
    +            break;
    +# if QT_CONFIG(timezone)
    +        case Qt::TimeZone:
    +            buf += QLatin1Char(' ') + d->m_timeZone.abbreviation(*this);
    +            break;
    +# endif
    +        default:
    +            buf += QLatin1String(" GMT");
    +            if (getSpec(d) == Qt::OffsetFromUTC)
    +                buf += toOffsetString(Qt::TextDate, offsetFromUtc());
    +        }
    +        return buf;
    +    }
    +#endif
    +    case Qt::ISODate:
    +    case Qt::ISODateWithMs: {
    +        const QPair p = getDateTime(d);
    +        const QDate &dt = p.first;
    +        const QTime &tm = p.second;
    +        buf = dt.toString(Qt::ISODate);
    +        if (buf.isEmpty())
    +            return QString();   // failed to convert
    +        buf += QLatin1Char('T');
    +        buf += tm.toString(format);
    +        switch (getSpec(d)) {
    +        case Qt::UTC:
    +            buf += QLatin1Char('Z');
    +            break;
    +        case Qt::OffsetFromUTC:
    +#if QT_CONFIG(timezone)
    +        case Qt::TimeZone:
    +#endif
    +            buf += toOffsetString(Qt::ISODate, offsetFromUtc());
    +            break;
    +        default:
    +            break;
    +        }
    +        return buf;
    +    }
    +    }
    +}
    +
    +/*!
    +    \fn QString QDateTime::toString(const QString &format) const
    +    \fn QString QDateTime::toString(QStringView format) const
    +
    +    Returns the datetime as a string. The \a format parameter
    +    determines the format of the result string.
    +
    +    These expressions may be used for the date:
    +
    +    \table
    +    \header \li Expression \li Output
    +    \row \li d \li the day as number without a leading zero (1 to 31)
    +    \row \li dd \li the day as number with a leading zero (01 to 31)
    +    \row \li ddd
    +            \li the abbreviated localized day name (e.g. 'Mon' to 'Sun').
    +            Uses the system locale to localize the name, i.e. QLocale::system().
    +    \row \li dddd
    +            \li the long localized day name (e.g. 'Monday' to 'Sunday').
    +            Uses the system locale to localize the name, i.e. QLocale::system().
    +    \row \li M \li the month as number without a leading zero (1-12)
    +    \row \li MM \li the month as number with a leading zero (01-12)
    +    \row \li MMM
    +            \li the abbreviated localized month name (e.g. 'Jan' to 'Dec').
    +            Uses the system locale to localize the name, i.e. QLocale::system().
    +    \row \li MMMM
    +            \li the long localized month name (e.g. 'January' to 'December').
    +            Uses the system locale to localize the name, i.e. QLocale::system().
    +    \row \li yy \li the year as two digit number (00-99)
    +    \row \li yyyy \li the year as four digit number
    +    \endtable
    +
    +    These expressions may be used for the time:
    +
    +    \table
    +    \header \li Expression \li Output
    +    \row \li h
    +         \li the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
    +    \row \li hh
    +         \li the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
    +    \row \li H
    +         \li the hour without a leading zero (0 to 23, even with AM/PM display)
    +    \row \li HH
    +         \li the hour with a leading zero (00 to 23, even with AM/PM display)
    +    \row \li m \li the minute without a leading zero (0 to 59)
    +    \row \li mm \li the minute with a leading zero (00 to 59)
    +    \row \li s \li the whole second without a leading zero (0 to 59)
    +    \row \li ss \li the whole second with a leading zero where applicable (00 to 59)
    +    \row \li z \li the fractional part of the second, to go after a decimal
    +                point, without trailing zeroes (0 to 999).  Thus "\c{s.z}"
    +                reports the seconds to full available (millisecond) precision
    +                without trailing zeroes.
    +    \row \li zzz \li the fractional part of the second, to millisecond
    +                precision, including trailing zeroes where applicable (000 to 999).
    +    \row \li AP or A
    +         \li use AM/PM display. \e A/AP will be replaced by either "AM" or "PM".
    +    \row \li ap or a
    +         \li use am/pm display. \e a/ap will be replaced by either "am" or "pm".
    +    \row \li t \li the timezone (for example "CEST")
    +    \endtable
    +
    +    Any sequence of characters enclosed in single quotes will be included
    +    verbatim in the output string (stripped of the quotes), even if it contains
    +    formatting characters. Two consecutive single quotes ("''") are replaced by
    +    a single quote in the output. All other characters in the format string are
    +    included verbatim in the output string.
    +
    +    Formats without separators (e.g. "ddMM") are supported but must be used with
    +    care, as the resulting strings aren't always reliably readable (e.g. if "dM"
    +    produces "212" it could mean either the 2nd of December or the 21st of
    +    February).
    +
    +    Example format strings (assumed that the QDateTime is 21 May 2001
    +    14:13:09.120):
    +
    +    \table
    +    \header \li Format       \li Result
    +    \row \li dd.MM.yyyy      \li 21.05.2001
    +    \row \li ddd MMMM d yy   \li Tue May 21 01
    +    \row \li hh:mm:ss.zzz    \li 14:13:09.120
    +    \row \li hh:mm:ss.z      \li 14:13:09.12
    +    \row \li h:m:s ap        \li 2:13:9 pm
    +    \endtable
    +
    +    If the datetime is invalid, an empty string will be returned.
    +
    +    \sa fromString(), QDate::toString(), QTime::toString(), QLocale::toString()
    +*/
    +QString QDateTime::toString(QStringView format) const
    +{
    +    return QLocale::system().toString(*this, format); // QLocale::c() ### Qt6
    +}
    +
    +#if QT_STRINGVIEW_LEVEL < 2
    +QString QDateTime::toString(const QString &format) const
    +{
    +    return toString(qToStringViewIgnoringNull(format));
    +}
    +#endif
    +
    +#endif // datestring
    +
    +static inline void massageAdjustedDateTime(const QDateTimeData &d, QDate *date, QTime *time)
    +{
    +    /*
    +      If we have just adjusted to a day with a DST transition, our given time
    +      may lie in the transition hour (either missing or duplicated).  For any
    +      other time, telling mktime (deep in the bowels of localMSecsToEpochMSecs)
    +      we don't know its DST-ness will produce no adjustment (just a decision as
    +      to its DST-ness); but for a time in spring's missing hour it'll adjust the
    +      time while picking a DST-ness.  (Handling of autumn is trickier, as either
    +      DST-ness is valid, without adjusting the time.  We might want to propagate
    +      the daylight status in that case, but it's hard to do so without breaking
    +      (far more common) other cases; and it makes little difference, as the two
    +      answers do then differ only in DST-ness.)
    +    */
    +    auto spec = getSpec(d);
    +    if (spec == Qt::LocalTime) {
    +        QDateTimePrivate::DaylightStatus status = QDateTimePrivate::UnknownDaylightTime;
    +        localMSecsToEpochMSecs(timeToMSecs(*date, *time), &status, date, time);
    +#if QT_CONFIG(timezone)
    +    } else if (spec == Qt::TimeZone) {
    +        QDateTimePrivate::zoneMSecsToEpochMSecs(timeToMSecs(*date, *time),
    +                                                d->m_timeZone,
    +                                                QDateTimePrivate::UnknownDaylightTime,
    +                                                date, time);
    +#endif // timezone
    +    }
    +}
    +
    +/*!
    +    Returns a QDateTime object containing a datetime \a ndays days
    +    later than the datetime of this object (or earlier if \a ndays is
    +    negative).
    +
    +    If the timeSpec() is Qt::LocalTime and the resulting
    +    date and time fall in the Standard Time to Daylight-Saving Time transition
    +    hour then the result will be adjusted accordingly, i.e. if the transition
    +    is at 2am and the clock goes forward to 3am and the result falls between
    +    2am and 3am then the result will be adjusted to fall after 3am.
    +
    +    \sa daysTo(), addMonths(), addYears(), addSecs()
    +*/
    +
    +QDateTime QDateTime::addDays(qint64 ndays) const
    +{
    +    QDateTime dt(*this);
    +    QPair p = getDateTime(d);
    +    QDate &date = p.first;
    +    QTime &time = p.second;
    +    date = date.addDays(ndays);
    +    massageAdjustedDateTime(dt.d, &date, &time);
    +    setDateTime(dt.d, date, time);
    +    return dt;
    +}
    +
    +/*!
    +    Returns a QDateTime object containing a datetime \a nmonths months
    +    later than the datetime of this object (or earlier if \a nmonths
    +    is negative).
    +
    +    If the timeSpec() is Qt::LocalTime and the resulting
    +    date and time fall in the Standard Time to Daylight-Saving Time transition
    +    hour then the result will be adjusted accordingly, i.e. if the transition
    +    is at 2am and the clock goes forward to 3am and the result falls between
    +    2am and 3am then the result will be adjusted to fall after 3am.
    +
    +    \sa daysTo(), addDays(), addYears(), addSecs()
    +*/
    +
    +QDateTime QDateTime::addMonths(int nmonths) const
    +{
    +    QDateTime dt(*this);
    +    QPair p = getDateTime(d);
    +    QDate &date = p.first;
    +    QTime &time = p.second;
    +    date = date.addMonths(nmonths);
    +    massageAdjustedDateTime(dt.d, &date, &time);
    +    setDateTime(dt.d, date, time);
    +    return dt;
    +}
    +
    +/*!
    +    Returns a QDateTime object containing a datetime \a nyears years
    +    later than the datetime of this object (or earlier if \a nyears is
    +    negative).
    +
    +    If the timeSpec() is Qt::LocalTime and the resulting
    +    date and time fall in the Standard Time to Daylight-Saving Time transition
    +    hour then the result will be adjusted accordingly, i.e. if the transition
    +    is at 2am and the clock goes forward to 3am and the result falls between
    +    2am and 3am then the result will be adjusted to fall after 3am.
    +
    +    \sa daysTo(), addDays(), addMonths(), addSecs()
    +*/
    +
    +QDateTime QDateTime::addYears(int nyears) const
    +{
    +    QDateTime dt(*this);
    +    QPair p = getDateTime(d);
    +    QDate &date = p.first;
    +    QTime &time = p.second;
    +    date = date.addYears(nyears);
    +    massageAdjustedDateTime(dt.d, &date, &time);
    +    setDateTime(dt.d, date, time);
    +    return dt;
    +}
    +
    +/*!
    +    Returns a QDateTime object containing a datetime \a s seconds
    +    later than the datetime of this object (or earlier if \a s is
    +    negative).
    +
    +    If this datetime is invalid, an invalid datetime will be returned.
    +
    +    \sa addMSecs(), secsTo(), addDays(), addMonths(), addYears()
    +*/
    +
    +QDateTime QDateTime::addSecs(qint64 s) const
    +{
    +    return addMSecs(s * 1000);
    +}
    +
    +/*!
    +    Returns a QDateTime object containing a datetime \a msecs miliseconds
    +    later than the datetime of this object (or earlier if \a msecs is
    +    negative).
    +
    +    If this datetime is invalid, an invalid datetime will be returned.
    +
    +    \sa addSecs(), msecsTo(), addDays(), addMonths(), addYears()
    +*/
    +QDateTime QDateTime::addMSecs(qint64 msecs) const
    +{
    +    if (!isValid())
    +        return QDateTime();
    +
    +    QDateTime dt(*this);
    +    auto spec = getSpec(d);
    +    if (spec == Qt::LocalTime || spec == Qt::TimeZone) {
    +        // Convert to real UTC first in case crosses DST transition
    +        dt.setMSecsSinceEpoch(toMSecsSinceEpoch() + msecs);
    +    } else {
    +        // No need to convert, just add on
    +        if (d.isShort()) {
    +            // need to check if we need to enlarge first
    +            msecs += dt.d.data.msecs;
    +            if (msecsCanBeSmall(msecs)) {
    +                dt.d.data.msecs = qintptr(msecs);
    +            } else {
    +                dt.d.detach();
    +                dt.d->m_msecs = msecs;
    +            }
    +        } else {
    +            dt.d.detach();
    +            dt.d->m_msecs += msecs;
    +        }
    +    }
    +    return dt;
    +}
    +
    +/*!
    +    Returns the number of days from this datetime to the \a other
    +    datetime. The number of days is counted as the number of times
    +    midnight is reached between this datetime to the \a other
    +    datetime. This means that a 10 minute difference from 23:55 to
    +    0:05 the next day counts as one day.
    +
    +    If the \a other datetime is earlier than this datetime,
    +    the value returned is negative.
    +
    +    Example:
    +    \snippet code/src_corelib_tools_qdatetime.cpp 15
    +
    +    \sa addDays(), secsTo(), msecsTo()
    +*/
    +
    +qint64 QDateTime::daysTo(const QDateTime &other) const
    +{
    +    return date().daysTo(other.date());
    +}
    +
    +/*!
    +    Returns the number of seconds from this datetime to the \a other
    +    datetime. If the \a other datetime is earlier than this datetime,
    +    the value returned is negative.
    +
    +    Before performing the comparison, the two datetimes are converted
    +    to Qt::UTC to ensure that the result is correct if daylight-saving
    +    (DST) applies to one of the two datetimes but not the other.
    +
    +    Returns 0 if either datetime is invalid.
    +
    +    Example:
    +    \snippet code/src_corelib_tools_qdatetime.cpp 11
    +
    +    \sa addSecs(), daysTo(), QTime::secsTo()
    +*/
    +
    +qint64 QDateTime::secsTo(const QDateTime &other) const
    +{
    +    return (msecsTo(other) / 1000);
    +}
    +
    +/*!
    +    Returns the number of milliseconds from this datetime to the \a other
    +    datetime. If the \a other datetime is earlier than this datetime,
    +    the value returned is negative.
    +
    +    Before performing the comparison, the two datetimes are converted
    +    to Qt::UTC to ensure that the result is correct if daylight-saving
    +    (DST) applies to one of the two datetimes and but not the other.
    +
    +    Returns 0 if either datetime is invalid.
    +
    +    \sa addMSecs(), daysTo(), QTime::msecsTo()
    +*/
    +
    +qint64 QDateTime::msecsTo(const QDateTime &other) const
    +{
    +    if (!isValid() || !other.isValid())
    +        return 0;
    +
    +    return other.toMSecsSinceEpoch() - toMSecsSinceEpoch();
    +}
    +
    +/*!
    +    \fn QDateTime QDateTime::toTimeSpec(Qt::TimeSpec spec) const
    +
    +    Returns a copy of this datetime converted to the given time
    +    \a spec.
    +
    +    If \a spec is Qt::OffsetFromUTC then it is set to Qt::UTC.  To set to a
    +    spec of Qt::OffsetFromUTC use toOffsetFromUtc().
    +
    +    If \a spec is Qt::TimeZone then it is set to Qt::LocalTime,
    +    i.e. the local Time Zone.
    +
    +    Example:
    +    \snippet code/src_corelib_tools_qdatetime.cpp 16
    +
    +    \sa timeSpec(), toTimeZone(), toUTC(), toLocalTime()
    +*/
    +
    +QDateTime QDateTime::toTimeSpec(Qt::TimeSpec spec) const
    +{
    +    if (getSpec(d) == spec && (spec == Qt::UTC || spec == Qt::LocalTime))
    +        return *this;
    +
    +    if (!isValid()) {
    +        QDateTime ret = *this;
    +        ret.setTimeSpec(spec);
    +        return ret;
    +    }
    +
    +    return fromMSecsSinceEpoch(toMSecsSinceEpoch(), spec, 0);
    +}
    +
    +/*!
    +    \since 5.2
    +
    +    \fn QDateTime QDateTime::toOffsetFromUtc(int offsetSeconds) const
    +
    +    Returns a copy of this datetime converted to a spec of Qt::OffsetFromUTC
    +    with the given \a offsetSeconds.
    +
    +    If the \a offsetSeconds equals 0 then a UTC datetime will be returned
    +
    +    \sa setOffsetFromUtc(), offsetFromUtc(), toTimeSpec()
    +*/
    +
    +QDateTime QDateTime::toOffsetFromUtc(int offsetSeconds) const
    +{
    +    if (getSpec(d) == Qt::OffsetFromUTC
    +            && d->m_offsetFromUtc == offsetSeconds)
    +        return *this;
    +
    +    if (!isValid()) {
    +        QDateTime ret = *this;
    +        ret.setOffsetFromUtc(offsetSeconds);
    +        return ret;
    +    }
    +
    +    return fromMSecsSinceEpoch(toMSecsSinceEpoch(), Qt::OffsetFromUTC, offsetSeconds);
    +}
    +
    +#if QT_CONFIG(timezone)
    +/*!
    +    \since 5.2
    +
    +    Returns a copy of this datetime converted to the given \a timeZone
    +
    +    \sa timeZone(), toTimeSpec()
    +*/
    +
    +QDateTime QDateTime::toTimeZone(const QTimeZone &timeZone) const
    +{
    +    if (getSpec(d) == Qt::TimeZone && d->m_timeZone == timeZone)
    +        return *this;
    +
    +    if (!isValid()) {
    +        QDateTime ret = *this;
    +        ret.setTimeZone(timeZone);
    +        return ret;
    +    }
    +
    +    return fromMSecsSinceEpoch(toMSecsSinceEpoch(), timeZone);
    +}
    +#endif // timezone
    +
    +/*!
    +    Returns \c true if this datetime is equal to the \a other datetime;
    +    otherwise returns \c false.
    +
    +    \sa operator!=()
    +*/
    +
    +bool QDateTime::operator==(const QDateTime &other) const
    +{
    +    if (getSpec(d) == Qt::LocalTime
    +        && getStatus(d) == getStatus(other.d)) {
    +        return getMSecs(d) == getMSecs(other.d);
    +    }
    +    // Convert to UTC and compare
    +    return (toMSecsSinceEpoch() == other.toMSecsSinceEpoch());
    +}
    +
    +/*!
    +    \fn bool QDateTime::operator!=(const QDateTime &other) const
    +
    +    Returns \c true if this datetime is different from the \a other
    +    datetime; otherwise returns \c false.
    +
    +    Two datetimes are different if either the date, the time, or the
    +    time zone components are different.
    +
    +    \sa operator==()
    +*/
    +
    +/*!
    +    Returns \c true if this datetime is earlier than the \a other
    +    datetime; otherwise returns \c false.
    +*/
    +
    +bool QDateTime::operator<(const QDateTime &other) const
    +{
    +    if (getSpec(d) == Qt::LocalTime
    +        && getStatus(d) == getStatus(other.d)) {
    +        return getMSecs(d) < getMSecs(other.d);
    +    }
    +    // Convert to UTC and compare
    +    return (toMSecsSinceEpoch() < other.toMSecsSinceEpoch());
    +}
    +
    +/*!
    +    \fn bool QDateTime::operator<=(const QDateTime &other) const
    +
    +    Returns \c true if this datetime is earlier than or equal to the
    +    \a other datetime; otherwise returns \c false.
    +*/
    +
    +/*!
    +    \fn bool QDateTime::operator>(const QDateTime &other) const
    +
    +    Returns \c true if this datetime is later than the \a other datetime;
    +    otherwise returns \c false.
    +*/
    +
    +/*!
    +    \fn bool QDateTime::operator>=(const QDateTime &other) const
    +
    +    Returns \c true if this datetime is later than or equal to the
    +    \a other datetime; otherwise returns \c false.
    +*/
    +
    +/*!
    +    \fn QDateTime QDateTime::currentDateTime()
    +    Returns the current datetime, as reported by the system clock, in
    +    the local time zone.
    +
    +    \sa currentDateTimeUtc(), QDate::currentDate(), QTime::currentTime(), toTimeSpec()
    +*/
    +
    +/*!
    +    \fn QDateTime QDateTime::currentDateTimeUtc()
    +    \since 4.7
    +    Returns the current datetime, as reported by the system clock, in
    +    UTC.
    +
    +    \sa currentDateTime(), QDate::currentDate(), QTime::currentTime(), toTimeSpec()
    +*/
    +
    +/*!
    +    \fn qint64 QDateTime::currentMSecsSinceEpoch()
    +    \since 4.7
    +
    +    Returns the number of milliseconds since 1970-01-01T00:00:00 Universal
    +    Coordinated Time. This number is like the POSIX time_t variable, but
    +    expressed in milliseconds instead.
    +
    +    \sa currentDateTime(), currentDateTimeUtc(), toTime_t(), toTimeSpec()
    +*/
    +
    +/*!
    +    \fn qint64 QDateTime::currentSecsSinceEpoch()
    +    \since 5.8
    +
    +    Returns the number of seconds since 1970-01-01T00:00:00 Universal
    +    Coordinated Time.
    +
    +    \sa currentMSecsSinceEpoch()
    +*/
    +
    +#if defined(Q_OS_WIN)
    +static inline uint msecsFromDecomposed(int hour, int minute, int sec, int msec = 0)
    +{
    +    return MSECS_PER_HOUR * hour + MSECS_PER_MIN * minute + 1000 * sec + msec;
    +}
    +
    +QDate QDate::currentDate()
    +{
    +    QDate d;
    +    SYSTEMTIME st;
    +    memset(&st, 0, sizeof(SYSTEMTIME));
    +    GetLocalTime(&st);
    +    d.jd = julianDayFromDate(st.wYear, st.wMonth, st.wDay);
    +    return d;
    +}
    +
    +QTime QTime::currentTime()
    +{
    +    QTime ct;
    +    SYSTEMTIME st;
    +    memset(&st, 0, sizeof(SYSTEMTIME));
    +    GetLocalTime(&st);
    +    ct.setHMS(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
    +    return ct;
    +}
    +
    +QDateTime QDateTime::currentDateTime()
    +{
    +    QDate d;
    +    QTime t;
    +    SYSTEMTIME st;
    +    memset(&st, 0, sizeof(SYSTEMTIME));
    +    GetLocalTime(&st);
    +    d.jd = julianDayFromDate(st.wYear, st.wMonth, st.wDay);
    +    t.mds = msecsFromDecomposed(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
    +    return QDateTime(d, t);
    +}
    +
    +QDateTime QDateTime::currentDateTimeUtc()
    +{
    +    QDate d;
    +    QTime t;
    +    SYSTEMTIME st;
    +    memset(&st, 0, sizeof(SYSTEMTIME));
    +    GetSystemTime(&st);
    +    d.jd = julianDayFromDate(st.wYear, st.wMonth, st.wDay);
    +    t.mds = msecsFromDecomposed(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
    +    return QDateTime(d, t, Qt::UTC);
    +}
    +
    +qint64 QDateTime::currentMSecsSinceEpoch() noexcept
    +{
    +    SYSTEMTIME st;
    +    memset(&st, 0, sizeof(SYSTEMTIME));
    +    GetSystemTime(&st);
    +
    +    return msecsFromDecomposed(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds) +
    +            qint64(julianDayFromDate(st.wYear, st.wMonth, st.wDay)
    +                   - julianDayFromDate(1970, 1, 1)) * Q_INT64_C(86400000);
    +}
    +
    +qint64 QDateTime::currentSecsSinceEpoch() noexcept
    +{
    +    SYSTEMTIME st;
    +    memset(&st, 0, sizeof(SYSTEMTIME));
    +    GetSystemTime(&st);
    +
    +    return st.wHour * SECS_PER_HOUR + st.wMinute * SECS_PER_MIN + st.wSecond +
    +            qint64(julianDayFromDate(st.wYear, st.wMonth, st.wDay)
    +                   - julianDayFromDate(1970, 1, 1)) * Q_INT64_C(86400);
    +}
    +
    +#elif defined(Q_OS_UNIX)
    +QDate QDate::currentDate()
    +{
    +    return QDateTime::currentDateTime().date();
    +}
    +
    +QTime QTime::currentTime()
    +{
    +    return QDateTime::currentDateTime().time();
    +}
    +
    +QDateTime QDateTime::currentDateTime()
    +{
    +    return fromMSecsSinceEpoch(currentMSecsSinceEpoch(), Qt::LocalTime);
    +}
    +
    +QDateTime QDateTime::currentDateTimeUtc()
    +{
    +    return fromMSecsSinceEpoch(currentMSecsSinceEpoch(), Qt::UTC);
    +}
    +
    +qint64 QDateTime::currentMSecsSinceEpoch() noexcept
    +{
    +    // posix compliant system
    +    // we have milliseconds
    +    struct timeval tv;
    +    gettimeofday(&tv, 0);
    +    return qint64(tv.tv_sec) * Q_INT64_C(1000) + tv.tv_usec / 1000;
    +}
    +
    +qint64 QDateTime::currentSecsSinceEpoch() noexcept
    +{
    +    struct timeval tv;
    +    gettimeofday(&tv, 0);
    +    return qint64(tv.tv_sec);
    +}
    +#else
    +#error "What system is this?"
    +#endif
    +
    +#if QT_DEPRECATED_SINCE(5, 8)
    +/*!
    +  \since 4.2
    +  \deprecated
    +
    +  Returns a datetime whose date and time are the number of \a seconds
    +  that have passed since 1970-01-01T00:00:00, Coordinated Universal
    +  Time (Qt::UTC) and converted to Qt::LocalTime.  On systems that do not
    +  support time zones, the time will be set as if local time were Qt::UTC.
    +
    +  \note This function is deprecated. Please use fromSecsSinceEpoch() in new
    +  code.
    +
    +  \sa toTime_t(), setTime_t()
    +*/
    +QDateTime QDateTime::fromTime_t(uint seconds)
    +{
    +    return fromMSecsSinceEpoch((qint64)seconds * 1000, Qt::LocalTime);
    +}
    +
    +/*!
    +  \since 5.2
    +  \deprecated
    +
    +  Returns a datetime whose date and time are the number of \a seconds
    +  that have passed since 1970-01-01T00:00:00, Coordinated Universal
    +  Time (Qt::UTC) and converted to the given \a spec.
    +
    +  If the \a spec is not Qt::OffsetFromUTC then the \a offsetSeconds will be
    +  ignored.  If the \a spec is Qt::OffsetFromUTC and the \a offsetSeconds is 0
    +  then the spec will be set to Qt::UTC, i.e. an offset of 0 seconds.
    +
    +  \note This function is deprecated. Please use fromSecsSinceEpoch() in new
    +  code.
    +
    +  \sa toTime_t(), setTime_t()
    +*/
    +QDateTime QDateTime::fromTime_t(uint seconds, Qt::TimeSpec spec, int offsetSeconds)
    +{
    +    return fromMSecsSinceEpoch((qint64)seconds * 1000, spec, offsetSeconds);
    +}
    +
    +#if QT_CONFIG(timezone)
    +/*!
    +    \since 5.2
    +    \deprecated
    +
    +    Returns a datetime whose date and time are the number of \a seconds
    +    that have passed since 1970-01-01T00:00:00, Coordinated Universal
    +    Time (Qt::UTC) and with the given \a timeZone.
    +
    +    \note This function is deprecated. Please use fromSecsSinceEpoch() in new
    +    code.
    +
    +    \sa toTime_t(), setTime_t()
    +*/
    +QDateTime QDateTime::fromTime_t(uint seconds, const QTimeZone &timeZone)
    +{
    +    return fromMSecsSinceEpoch((qint64)seconds * 1000, timeZone);
    +}
    +#endif
    +#endif // QT_DEPRECATED_SINCE(5, 8)
    +
    +/*!
    +  \since 4.7
    +
    +  Returns a datetime whose date and time are the number of milliseconds, \a msecs,
    +  that have passed since 1970-01-01T00:00:00.000, Coordinated Universal
    +  Time (Qt::UTC), and converted to Qt::LocalTime.  On systems that do not
    +  support time zones, the time will be set as if local time were Qt::UTC.
    +
    +  Note that there are possible values for \a msecs that lie outside the valid
    +  range of QDateTime, both negative and positive. The behavior of this
    +  function is undefined for those values.
    +
    +  \sa toMSecsSinceEpoch(), setMSecsSinceEpoch()
    +*/
    +QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs)
    +{
    +    return fromMSecsSinceEpoch(msecs, Qt::LocalTime);
    +}
    +
    +/*!
    +  \since 5.2
    +
    +  Returns a datetime whose date and time are the number of milliseconds \a msecs
    +  that have passed since 1970-01-01T00:00:00.000, Coordinated Universal
    +  Time (Qt::UTC) and converted to the given \a spec.
    +
    +  Note that there are possible values for \a msecs that lie outside the valid
    +  range of QDateTime, both negative and positive. The behavior of this
    +  function is undefined for those values.
    +
    +  If the \a spec is not Qt::OffsetFromUTC then the \a offsetSeconds will be
    +  ignored.  If the \a spec is Qt::OffsetFromUTC and the \a offsetSeconds is 0
    +  then the spec will be set to Qt::UTC, i.e. an offset of 0 seconds.
    +
    +  If \a spec is Qt::TimeZone then the spec will be set to Qt::LocalTime,
    +  i.e. the current system time zone.
    +
    +  \sa toMSecsSinceEpoch(), setMSecsSinceEpoch()
    +*/
    +QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs, Qt::TimeSpec spec, int offsetSeconds)
    +{
    +    QDateTime dt;
    +    QT_PREPEND_NAMESPACE(setTimeSpec(dt.d, spec, offsetSeconds));
    +    dt.setMSecsSinceEpoch(msecs);
    +    return dt;
    +}
    +
    +/*!
    +  \since 5.8
    +
    +  Returns a datetime whose date and time are the number of seconds \a secs
    +  that have passed since 1970-01-01T00:00:00.000, Coordinated Universal
    +  Time (Qt::UTC) and converted to the given \a spec.
    +
    +  Note that there are possible values for \a secs that lie outside the valid
    +  range of QDateTime, both negative and positive. The behavior of this
    +  function is undefined for those values.
    +
    +  If the \a spec is not Qt::OffsetFromUTC then the \a offsetSeconds will be
    +  ignored.  If the \a spec is Qt::OffsetFromUTC and the \a offsetSeconds is 0
    +  then the spec will be set to Qt::UTC, i.e. an offset of 0 seconds.
    +
    +  If \a spec is Qt::TimeZone then the spec will be set to Qt::LocalTime,
    +  i.e. the current system time zone.
    +
    +  \sa toSecsSinceEpoch(), setSecsSinceEpoch()
    +*/
    +QDateTime QDateTime::fromSecsSinceEpoch(qint64 secs, Qt::TimeSpec spec, int offsetSeconds)
    +{
    +    return fromMSecsSinceEpoch(secs * 1000, spec, offsetSeconds);
    +}
    +
    +#if QT_CONFIG(timezone)
    +/*!
    +    \since 5.2
    +
    +    Returns a datetime whose date and time are the number of milliseconds \a msecs
    +    that have passed since 1970-01-01T00:00:00.000, Coordinated Universal
    +    Time (Qt::UTC) and with the given \a timeZone.
    +
    +    \sa fromSecsSinceEpoch()
    +*/
    +QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs, const QTimeZone &timeZone)
    +{
    +    QDateTime dt;
    +    dt.setTimeZone(timeZone);
    +    dt.setMSecsSinceEpoch(msecs);
    +    return dt;
    +}
    +
    +/*!
    +    \since 5.8
    +
    +    Returns a datetime whose date and time are the number of seconds \a secs
    +    that have passed since 1970-01-01T00:00:00.000, Coordinated Universal
    +    Time (Qt::UTC) and with the given \a timeZone.
    +
    +    \sa fromMSecsSinceEpoch()
    +*/
    +QDateTime QDateTime::fromSecsSinceEpoch(qint64 secs, const QTimeZone &timeZone)
    +{
    +    return fromMSecsSinceEpoch(secs * 1000, timeZone);
    +}
    +#endif
    +
    +#if QT_DEPRECATED_SINCE(5, 2)
    +/*!
    +    \since 4.4
    +    \internal
    +    \obsolete
    +
    +    This method was added in 4.4 but never documented as public. It was replaced
    +    in 5.2 with public method setOffsetFromUtc() for consistency with QTimeZone.
    +
    +    This method should never be made public.
    +
    +    \sa setOffsetFromUtc()
    + */
    +void QDateTime::setUtcOffset(int seconds)
    +{
    +    setOffsetFromUtc(seconds);
    +}
    +
    +/*!
    +    \since 4.4
    +    \internal
    +    \obsolete
    +
    +    This method was added in 4.4 but never documented as public. It was replaced
    +    in 5.1 with public method offsetFromUTC() for consistency with QTimeZone.
    +
    +    This method should never be made public.
    +
    +    \sa offsetFromUTC()
    +*/
    +int QDateTime::utcOffset() const
    +{
    +    return offsetFromUtc();
    +}
    +#endif // QT_DEPRECATED_SINCE
    +
    +#if QT_CONFIG(datestring)
    +
    +/*!
    +    Returns the QDateTime represented by the \a string, using the
    +    \a format given, or an invalid datetime if this is not possible.
    +
    +    Note for Qt::TextDate: It is recommended that you use the
    +    English short month names (e.g. "Jan"). Although localized month
    +    names can also be used, they depend on the user's locale settings.
    +
    +    \sa toString(), QLocale::toDateTime()
    +*/
    +QDateTime QDateTime::fromString(const QString &string, Qt::DateFormat format)
    +{
    +    if (string.isEmpty())
    +        return QDateTime();
    +
    +    switch (format) {
    +    case Qt::SystemLocaleDate:
    +    case Qt::SystemLocaleShortDate:
    +        return QLocale::system().toDateTime(string, QLocale::ShortFormat);
    +    case Qt::SystemLocaleLongDate:
    +        return QLocale::system().toDateTime(string, QLocale::LongFormat);
    +    case Qt::LocaleDate:
    +    case Qt::DefaultLocaleShortDate:
    +        return QLocale().toDateTime(string, QLocale::ShortFormat);
    +    case Qt::DefaultLocaleLongDate:
    +        return QLocale().toDateTime(string, QLocale::LongFormat);
    +    case Qt::RFC2822Date: {
    +        const ParsedRfcDateTime rfc = rfcDateImpl(string);
    +
    +        if (!rfc.date.isValid() || !rfc.time.isValid())
    +            return QDateTime();
    +
    +        QDateTime dateTime(rfc.date, rfc.time, Qt::UTC);
    +        dateTime.setOffsetFromUtc(rfc.utcOffset);
    +        return dateTime;
    +    }
    +    case Qt::ISODate:
    +    case Qt::ISODateWithMs: {
    +        const int size = string.size();
    +        if (size < 10)
    +            return QDateTime();
    +
    +        QDate date = QDate::fromString(string.left(10), Qt::ISODate);
    +        if (!date.isValid())
    +            return QDateTime();
    +        if (size == 10)
    +            return QDateTime(date);
    +
    +        Qt::TimeSpec spec = Qt::LocalTime;
    +        QStringRef isoString(&string);
    +        isoString = isoString.mid(10); // trim "yyyy-MM-dd"
    +
    +        // Must be left with T and at least one digit for the hour:
    +        if (isoString.size() < 2
    +            || !(isoString.startsWith(QLatin1Char('T'))
    +                 // FIXME: QSql relies on QVariant::toDateTime() accepting a space here:
    +                 || isoString.startsWith(QLatin1Char(' ')))) {
    +            return QDateTime();
    +        }
    +        isoString = isoString.mid(1); // trim 'T' (or space)
    +
    +        int offset = 0;
    +        // Check end of string for Time Zone definition, either Z for UTC or [+-]HH:mm for Offset
    +        if (isoString.endsWith(QLatin1Char('Z'))) {
    +            spec = Qt::UTC;
    +            isoString.chop(1); // trim 'Z'
    +        } else {
    +            // the loop below is faster but functionally equal to:
    +            // const int signIndex = isoString.indexOf(QRegExp(QStringLiteral("[+-]")));
    +            int signIndex = isoString.size() - 1;
    +            Q_ASSERT(signIndex >= 0);
    +            bool found = false;
    +            {
    +                const QChar plus = QLatin1Char('+');
    +                const QChar minus = QLatin1Char('-');
    +                do {
    +                    QChar character(isoString.at(signIndex));
    +                    found = character == plus || character == minus;
    +                } while (!found && --signIndex >= 0);
    +            }
    +
    +            if (found) {
    +                bool ok;
    +                offset = fromOffsetString(isoString.mid(signIndex), &ok);
    +                if (!ok)
    +                    return QDateTime();
    +                isoString = isoString.left(signIndex);
    +                spec = Qt::OffsetFromUTC;
    +            }
    +        }
    +
    +        // Might be end of day (24:00, including variants), which QTime considers invalid.
    +        // ISO 8601 (section 4.2.3) says that 24:00 is equivalent to 00:00 the next day.
    +        bool isMidnight24 = false;
    +        QTime time = fromIsoTimeString(isoString, format, &isMidnight24);
    +        if (!time.isValid())
    +            return QDateTime();
    +        if (isMidnight24)
    +            date = date.addDays(1);
    +        return QDateTime(date, time, spec, offset);
    +    }
    +#if QT_CONFIG(textdate)
    +    case Qt::TextDate: {
    +        QVector parts = string.splitRef(QLatin1Char(' '), QString::SkipEmptyParts);
    +
    +        if ((parts.count() < 5) || (parts.count() > 6))
    +            return QDateTime();
    +
    +        // Accept "Sun Dec 1 13:02:00 1974" and "Sun 1. Dec 13:02:00 1974"
    +        int month = 0;
    +        int day = 0;
    +        bool ok = false;
    +
    +        // First try month then day
    +        month = fromShortMonthName(parts.at(1));
    +        if (month)
    +            day = parts.at(2).toInt();
    +
    +        // If failed try day then month
    +        if (!month || !day) {
    +            month = fromShortMonthName(parts.at(2));
    +            if (month) {
    +                QStringRef dayStr = parts.at(1);
    +                if (dayStr.endsWith(QLatin1Char('.'))) {
    +                    dayStr = dayStr.left(dayStr.size() - 1);
    +                    day = dayStr.toInt();
    +                }
    +            }
    +        }
    +
    +        // If both failed, give up
    +        if (!month || !day)
    +            return QDateTime();
    +
    +        // Year can be before or after time, "Sun Dec 1 1974 13:02:00" or "Sun Dec 1 13:02:00 1974"
    +        // Guess which by looking for ':' in the time
    +        int year = 0;
    +        int yearPart = 0;
    +        int timePart = 0;
    +        if (parts.at(3).contains(QLatin1Char(':'))) {
    +            yearPart = 4;
    +            timePart = 3;
    +        } else if (parts.at(4).contains(QLatin1Char(':'))) {
    +            yearPart = 3;
    +            timePart = 4;
    +        } else {
    +            return QDateTime();
    +        }
    +
    +        year = parts.at(yearPart).toInt(&ok);
    +        if (!ok)
    +            return QDateTime();
    +
    +        QDate date(year, month, day);
    +        if (!date.isValid())
    +            return QDateTime();
    +
    +        QVector timeParts = parts.at(timePart).split(QLatin1Char(':'));
    +        if (timeParts.count() < 2 || timeParts.count() > 3)
    +            return QDateTime();
    +
    +        int hour = timeParts.at(0).toInt(&ok);
    +        if (!ok)
    +            return QDateTime();
    +
    +        int minute = timeParts.at(1).toInt(&ok);
    +        if (!ok)
    +            return QDateTime();
    +
    +        int second = 0;
    +        int millisecond = 0;
    +        if (timeParts.count() > 2) {
    +            const QVector secondParts = timeParts.at(2).split(QLatin1Char('.'));
    +            if (secondParts.size() > 2) {
    +                return QDateTime();
    +            }
    +
    +            second = secondParts.first().toInt(&ok);
    +            if (!ok) {
    +                return QDateTime();
    +            }
    +
    +            if (secondParts.size() > 1) {
    +                millisecond = secondParts.last().toInt(&ok);
    +                if (!ok) {
    +                    return QDateTime();
    +                }
    +            }
    +        }
    +
    +        QTime time(hour, minute, second, millisecond);
    +        if (!time.isValid())
    +            return QDateTime();
    +
    +        if (parts.count() == 5)
    +            return QDateTime(date, time, Qt::LocalTime);
    +
    +        QStringRef tz = parts.at(5);
    +        if (!tz.startsWith(QLatin1String("GMT"), Qt::CaseInsensitive))
    +            return QDateTime();
    +        tz = tz.mid(3);
    +        if (!tz.isEmpty()) {
    +            int offset = fromOffsetString(tz, &ok);
    +            if (!ok)
    +                return QDateTime();
    +            return QDateTime(date, time, Qt::OffsetFromUTC, offset);
    +        } else {
    +            return QDateTime(date, time, Qt::UTC);
    +        }
    +    }
    +#endif // textdate
    +    }
    +
    +    return QDateTime();
    +}
    +
    +/*!
    +    Returns the QDateTime represented by the \a string, using the \a
    +    format given, or an invalid datetime if the string cannot be parsed.
    +
    +    These expressions may be used for the date part of the format string:
    +
    +    \table
    +    \header \li Expression \li Output
    +    \row \li d \li the day as number without a leading zero (1 to 31)
    +    \row \li dd \li the day as number with a leading zero (01 to 31)
    +    \row \li ddd
    +            \li the abbreviated localized day name (e.g. 'Mon' to 'Sun').
    +            Uses QDate::shortDayName().
    +    \row \li dddd
    +            \li the long localized day name (e.g. 'Monday' to 'Sunday').
    +            Uses QDate::longDayName().
    +    \row \li M \li the month as number without a leading zero (1-12)
    +    \row \li MM \li the month as number with a leading zero (01-12)
    +    \row \li MMM
    +            \li the abbreviated localized month name (e.g. 'Jan' to 'Dec').
    +            Uses QDate::shortMonthName().
    +    \row \li MMMM
    +            \li the long localized month name (e.g. 'January' to 'December').
    +            Uses QDate::longMonthName().
    +    \row \li yy \li the year as two digit number (00-99)
    +    \row \li yyyy \li the year as four digit number
    +    \endtable
    +
    +    \note Unlike the other version of this function, day and month names must
    +    be given in the user's local language. It is only possible to use the English
    +    names if the user's language is English.
    +
    +    These expressions may be used for the time part of the format string:
    +
    +    \table
    +    \header \li Expression \li Output
    +    \row \li h
    +            \li the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
    +    \row \li hh
    +            \li the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
    +    \row \li H
    +            \li the hour without a leading zero (0 to 23, even with AM/PM display)
    +    \row \li HH
    +            \li the hour with a leading zero (00 to 23, even with AM/PM display)
    +    \row \li m \li the minute without a leading zero (0 to 59)
    +    \row \li mm \li the minute with a leading zero (00 to 59)
    +    \row \li s \li the whole second without a leading zero (0 to 59)
    +    \row \li ss \li the whole second with a leading zero where applicable (00 to 59)
    +    \row \li z \li the fractional part of the second, to go after a decimal
    +                point, without trailing zeroes (0 to 999).  Thus "\c{s.z}"
    +                reports the seconds to full available (millisecond) precision
    +                without trailing zeroes.
    +    \row \li zzz \li the fractional part of the second, to millisecond
    +                precision, including trailing zeroes where applicable (000 to 999).
    +    \row \li AP or A
    +         \li interpret as an AM/PM time. \e AP must be either "AM" or "PM".
    +    \row \li ap or a
    +         \li Interpret as an AM/PM time. \e ap must be either "am" or "pm".
    +    \endtable
    +
    +    All other input characters will be treated as text. Any sequence
    +    of characters that are enclosed in single quotes will also be
    +    treated as text and not be used as an expression.
    +
    +    \snippet code/src_corelib_tools_qdatetime.cpp 12
    +
    +    If the format is not satisfied, an invalid QDateTime is returned.
    +    The expressions that don't have leading zeroes (d, M, h, m, s, z) will be
    +    greedy. This means that they will use two digits even if this will
    +    put them outside the range and/or leave too few digits for other
    +    sections.
    +
    +    \snippet code/src_corelib_tools_qdatetime.cpp 13
    +
    +    This could have meant 1 January 00:30.00 but the M will grab
    +    two digits.
    +
    +    Incorrectly specified fields of the \a string will cause an invalid
    +    QDateTime to be returned. For example, consider the following code,
    +    where the two digit year 12 is read as 1912 (see the table below for all
    +    field defaults); the resulting datetime is invalid because 23 April 1912
    +    was a Tuesday, not a Monday:
    +
    +    \snippet code/src_corelib_tools_qdatetime.cpp 20
    +
    +    The correct code is:
    +
    +    \snippet code/src_corelib_tools_qdatetime.cpp 21
    +
    +    For any field that is not represented in the format, the following
    +    defaults are used:
    +
    +    \table
    +    \header \li Field  \li Default value
    +    \row    \li Year   \li 1900
    +    \row    \li Month  \li 1 (January)
    +    \row    \li Day    \li 1
    +    \row    \li Hour   \li 0
    +    \row    \li Minute \li 0
    +    \row    \li Second \li 0
    +    \endtable
    +
    +    For example:
    +
    +    \snippet code/src_corelib_tools_qdatetime.cpp 14
    +
    +    \sa toString(), QDate::fromString(), QTime::fromString(),
    +    QLocale::toDateTime()
    +*/
    +
    +QDateTime QDateTime::fromString(const QString &string, const QString &format)
    +{
    +#if QT_CONFIG(datetimeparser)
    +    QTime time;
    +    QDate date;
    +
    +    QDateTimeParser dt(QVariant::DateTime, QDateTimeParser::FromString);
    +    // dt.setDefaultLocale(QLocale::c()); ### Qt 6
    +    if (dt.parseFormat(format) && dt.fromString(string, &date, &time))
    +        return QDateTime(date, time);
    +#else
    +    Q_UNUSED(string);
    +    Q_UNUSED(format);
    +#endif
    +    return QDateTime();
    +}
    +
    +#endif // datestring
    +/*!
    +    \fn QDateTime QDateTime::toLocalTime() const
    +
    +    Returns a datetime containing the date and time information in
    +    this datetime, but specified using the Qt::LocalTime definition.
    +
    +    Example:
    +
    +    \snippet code/src_corelib_tools_qdatetime.cpp 17
    +
    +    \sa toTimeSpec()
    +*/
    +
    +/*!
    +    \fn QDateTime QDateTime::toUTC() const
    +
    +    Returns a datetime containing the date and time information in
    +    this datetime, but specified using the Qt::UTC definition.
    +
    +    Example:
    +
    +    \snippet code/src_corelib_tools_qdatetime.cpp 18
    +
    +    \sa toTimeSpec()
    +*/
    +
    +/*****************************************************************************
    +  Date/time stream functions
    + *****************************************************************************/
    +
    +#ifndef QT_NO_DATASTREAM
    +/*!
    +    \relates QDate
    +
    +    Writes the \a date to stream \a out.
    +
    +    \sa {Serializing Qt Data Types}
    +*/
    +
    +QDataStream &operator<<(QDataStream &out, const QDate &date)
    +{
    +    if (out.version() < QDataStream::Qt_5_0)
    +        return out << quint32(date.jd);
    +    else
    +        return out << qint64(date.jd);
    +}
    +
    +/*!
    +    \relates QDate
    +
    +    Reads a date from stream \a in into the \a date.
    +
    +    \sa {Serializing Qt Data Types}
    +*/
    +
    +QDataStream &operator>>(QDataStream &in, QDate &date)
    +{
    +    if (in.version() < QDataStream::Qt_5_0) {
    +        quint32 jd;
    +        in >> jd;
    +        // Older versions consider 0 an invalid jd.
    +        date.jd = (jd != 0 ? jd : QDate::nullJd());
    +    } else {
    +        qint64 jd;
    +        in >> jd;
    +        date.jd = jd;
    +    }
    +
    +    return in;
    +}
    +
    +/*!
    +    \relates QTime
    +
    +    Writes \a time to stream \a out.
    +
    +    \sa {Serializing Qt Data Types}
    +*/
    +
    +QDataStream &operator<<(QDataStream &out, const QTime &time)
    +{
    +    if (out.version() >= QDataStream::Qt_4_0) {
    +        return out << quint32(time.mds);
    +    } else {
    +        // Qt3 had no support for reading -1, QTime() was valid and serialized as 0
    +        return out << quint32(time.isNull() ? 0 : time.mds);
    +    }
    +}
    +
    +/*!
    +    \relates QTime
    +
    +    Reads a time from stream \a in into the given \a time.
    +
    +    \sa {Serializing Qt Data Types}
    +*/
    +
    +QDataStream &operator>>(QDataStream &in, QTime &time)
    +{
    +    quint32 ds;
    +    in >> ds;
    +    if (in.version() >= QDataStream::Qt_4_0) {
    +        time.mds = int(ds);
    +    } else {
    +        // Qt3 would write 0 for a null time
    +        time.mds = (ds == 0) ? QTime::NullTime : int(ds);
    +    }
    +    return in;
    +}
    +
    +/*!
    +    \relates QDateTime
    +
    +    Writes \a dateTime to the \a out stream.
    +
    +    \sa {Serializing Qt Data Types}
    +*/
    +QDataStream &operator<<(QDataStream &out, const QDateTime &dateTime)
    +{
    +    QPair dateAndTime;
    +
    +    if (out.version() >= QDataStream::Qt_5_2) {
    +
    +        // In 5.2 we switched to using Qt::TimeSpec and added offset support
    +        dateAndTime = getDateTime(dateTime.d);
    +        out << dateAndTime << qint8(dateTime.timeSpec());
    +        if (dateTime.timeSpec() == Qt::OffsetFromUTC)
    +            out << qint32(dateTime.offsetFromUtc());
    +#if QT_CONFIG(timezone)
    +        else if (dateTime.timeSpec() == Qt::TimeZone)
    +            out << dateTime.timeZone();
    +#endif // timezone
    +
    +    } else if (out.version() == QDataStream::Qt_5_0) {
    +
    +        // In Qt 5.0 we incorrectly serialised all datetimes as UTC.
    +        // This approach is wrong and should not be used again; it breaks
    +        // the guarantee that a deserialised local datetime is the same time
    +        // of day, regardless of which timezone it was serialised in.
    +        dateAndTime = getDateTime((dateTime.isValid() ? dateTime.toUTC() : dateTime).d);
    +        out << dateAndTime << qint8(dateTime.timeSpec());
    +
    +    } else if (out.version() >= QDataStream::Qt_4_0) {
    +
    +        // From 4.0 to 5.1 (except 5.0) we used QDateTimePrivate::Spec
    +        dateAndTime = getDateTime(dateTime.d);
    +        out << dateAndTime;
    +        switch (dateTime.timeSpec()) {
    +        case Qt::UTC:
    +            out << (qint8)QDateTimePrivate::UTC;
    +            break;
    +        case Qt::OffsetFromUTC:
    +            out << (qint8)QDateTimePrivate::OffsetFromUTC;
    +            break;
    +        case Qt::TimeZone:
    +            out << (qint8)QDateTimePrivate::TimeZone;
    +            break;
    +        case Qt::LocalTime:
    +            out << (qint8)QDateTimePrivate::LocalUnknown;
    +            break;
    +        }
    +
    +    } else { // version < QDataStream::Qt_4_0
    +
    +        // Before 4.0 there was no TimeSpec, only Qt::LocalTime was supported
    +        dateAndTime = getDateTime(dateTime.d);
    +        out << dateAndTime;
    +
    +    }
    +
    +    return out;
    +}
    +
    +/*!
    +    \relates QDateTime
    +
    +    Reads a datetime from the stream \a in into \a dateTime.
    +
    +    \sa {Serializing Qt Data Types}
    +*/
    +
    +QDataStream &operator>>(QDataStream &in, QDateTime &dateTime)
    +{
    +    QDate dt;
    +    QTime tm;
    +    qint8 ts = 0;
    +    Qt::TimeSpec spec = Qt::LocalTime;
    +    qint32 offset = 0;
    +#if QT_CONFIG(timezone)
    +    QTimeZone tz;
    +#endif // timezone
    +
    +    if (in.version() >= QDataStream::Qt_5_2) {
    +
    +        // In 5.2 we switched to using Qt::TimeSpec and added offset support
    +        in >> dt >> tm >> ts;
    +        spec = static_cast(ts);
    +        if (spec == Qt::OffsetFromUTC) {
    +            in >> offset;
    +            dateTime = QDateTime(dt, tm, spec, offset);
    +#if QT_CONFIG(timezone)
    +        } else if (spec == Qt::TimeZone) {
    +            in >> tz;
    +            dateTime = QDateTime(dt, tm, tz);
    +#endif // timezone
    +        } else {
    +            dateTime = QDateTime(dt, tm, spec);
    +        }
    +
    +    } else if (in.version() == QDataStream::Qt_5_0) {
    +
    +        // In Qt 5.0 we incorrectly serialised all datetimes as UTC
    +        in >> dt >> tm >> ts;
    +        spec = static_cast(ts);
    +        dateTime = QDateTime(dt, tm, Qt::UTC);
    +        dateTime = dateTime.toTimeSpec(spec);
    +
    +    } else if (in.version() >= QDataStream::Qt_4_0) {
    +
    +        // From 4.0 to 5.1 (except 5.0) we used QDateTimePrivate::Spec
    +        in >> dt >> tm >> ts;
    +        switch ((QDateTimePrivate::Spec)ts) {
    +        case QDateTimePrivate::UTC:
    +            spec = Qt::UTC;
    +            break;
    +        case QDateTimePrivate::OffsetFromUTC:
    +            spec = Qt::OffsetFromUTC;
    +            break;
    +        case QDateTimePrivate::TimeZone:
    +            spec = Qt::TimeZone;
    +#if QT_CONFIG(timezone)
    +            // FIXME: need to use a different constructor !
    +#endif
    +            break;
    +        case QDateTimePrivate::LocalUnknown:
    +        case QDateTimePrivate::LocalStandard:
    +        case QDateTimePrivate::LocalDST:
    +            spec = Qt::LocalTime;
    +            break;
    +        }
    +        dateTime = QDateTime(dt, tm, spec, offset);
    +
    +    } else { // version < QDataStream::Qt_4_0
    +
    +        // Before 4.0 there was no TimeSpec, only Qt::LocalTime was supported
    +        in >> dt >> tm;
    +        dateTime = QDateTime(dt, tm, spec, offset);
    +
    +    }
    +
    +    return in;
    +}
    +#endif // QT_NO_DATASTREAM
    +
    +/*****************************************************************************
    +  Date / Time Debug Streams
    +*****************************************************************************/
    +
    +#if !defined(QT_NO_DEBUG_STREAM) && QT_CONFIG(datestring)
    +QDebug operator<<(QDebug dbg, const QDate &date)
    +{
    +    QDebugStateSaver saver(dbg);
    +    dbg.nospace() << "QDate(";
    +    if (date.isValid())
    +        dbg.nospace() << date.toString(Qt::ISODate);
    +    else
    +        dbg.nospace() << "Invalid";
    +    dbg.nospace() << ')';
    +    return dbg;
    +}
    +
    +QDebug operator<<(QDebug dbg, const QTime &time)
    +{
    +    QDebugStateSaver saver(dbg);
    +    dbg.nospace() << "QTime(";
    +    if (time.isValid())
    +        dbg.nospace() << time.toString(QStringViewLiteral("HH:mm:ss.zzz"));
    +    else
    +        dbg.nospace() << "Invalid";
    +    dbg.nospace() << ')';
    +    return dbg;
    +}
    +
    +QDebug operator<<(QDebug dbg, const QDateTime &date)
    +{
    +    QDebugStateSaver saver(dbg);
    +    dbg.nospace() << "QDateTime(";
    +    if (date.isValid()) {
    +        const Qt::TimeSpec ts = date.timeSpec();
    +        dbg.noquote() << date.toString(QStringViewLiteral("yyyy-MM-dd HH:mm:ss.zzz t"))
    +                      << ' ' << ts;
    +        switch (ts) {
    +        case Qt::UTC:
    +            break;
    +        case Qt::OffsetFromUTC:
    +            dbg.space() << date.offsetFromUtc() << 's';
    +            break;
    +        case Qt::TimeZone:
    +#if QT_CONFIG(timezone)
    +            dbg.space() << date.timeZone().id();
    +#endif // timezone
    +            break;
    +        case Qt::LocalTime:
    +            break;
    +        }
    +    } else {
    +        dbg.nospace() << "Invalid";
    +    }
    +    return dbg.nospace() << ')';
    +}
    +#endif // debug_stream && datestring
    +
    +/*! \fn uint qHash(const QDateTime &key, uint seed = 0)
    +    \relates QHash
    +    \since 5.0
    +
    +    Returns the hash value for the \a key, using \a seed to seed the calculation.
    +*/
    +uint qHash(const QDateTime &key, uint seed)
    +{
    +    // Use to toMSecsSinceEpoch instead of individual qHash functions for
    +    // QDate/QTime/spec/offset because QDateTime::operator== converts both arguments
    +    // to the same timezone. If we don't, qHash would return different hashes for
    +    // two QDateTimes that are equivalent once converted to the same timezone.
    +    return qHash(key.toMSecsSinceEpoch(), seed);
    +}
    +
    +/*! \fn uint qHash(const QDate &key, uint seed = 0)
    +    \relates QHash
    +    \since 5.0
    +
    +    Returns the hash value for the \a key, using \a seed to seed the calculation.
    +*/
    +uint qHash(const QDate &key, uint seed) noexcept
    +{
    +    return qHash(key.toJulianDay(), seed);
    +}
    +
    +/*! \fn uint qHash(const QTime &key, uint seed = 0)
    +    \relates QHash
    +    \since 5.0
    +
    +    Returns the hash value for the \a key, using \a seed to seed the calculation.
    +*/
    +uint qHash(const QTime &key, uint seed) noexcept
    +{
    +    return qHash(key.msecsSinceStartOfDay(), seed);
    +}
    +
    +QT_END_NAMESPACE
    diff --git a/src/corelib/time/qdatetime.h b/src/corelib/time/qdatetime.h
    new file mode 100644
    index 0000000000..3e3b953b52
    --- /dev/null
    +++ b/src/corelib/time/qdatetime.h
    @@ -0,0 +1,426 @@
    +/****************************************************************************
    +**
    +** Copyright (C) 2019 The Qt Company Ltd.
    +** Copyright (C) 2016 Intel Corporation.
    +** Contact: https://www.qt.io/licensing/
    +**
    +** This file is part of the QtCore module of the Qt Toolkit.
    +**
    +** $QT_BEGIN_LICENSE:LGPL$
    +** Commercial License Usage
    +** Licensees holding valid commercial Qt licenses may use this file in
    +** accordance with the commercial license agreement provided with the
    +** Software or, alternatively, in accordance with the terms contained in
    +** a written agreement between you and The Qt Company. For licensing terms
    +** and conditions see https://www.qt.io/terms-conditions. For further
    +** information use the contact form at https://www.qt.io/contact-us.
    +**
    +** GNU Lesser General Public License Usage
    +** Alternatively, this file may be used under the terms of the GNU Lesser
    +** General Public License version 3 as published by the Free Software
    +** Foundation and appearing in the file LICENSE.LGPL3 included in the
    +** packaging of this file. Please review the following information to
    +** ensure the GNU Lesser General Public License version 3 requirements
    +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
    +**
    +** GNU General Public License Usage
    +** Alternatively, this file may be used under the terms of the GNU
    +** General Public License version 2.0 or (at your option) the GNU General
    +** Public license version 3 or any later version approved by the KDE Free
    +** Qt Foundation. The licenses are as published by the Free Software
    +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
    +** included in the packaging of this file. Please review the following
    +** information to ensure the GNU General Public License requirements will
    +** be met: https://www.gnu.org/licenses/gpl-2.0.html and
    +** https://www.gnu.org/licenses/gpl-3.0.html.
    +**
    +** $QT_END_LICENSE$
    +**
    +****************************************************************************/
    +
    +#ifndef QDATETIME_H
    +#define QDATETIME_H
    +
    +#include 
    +#include 
    +#include 
    +
    +#include 
    +
    +#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
    +Q_FORWARD_DECLARE_CF_TYPE(CFDate);
    +Q_FORWARD_DECLARE_OBJC_CLASS(NSDate);
    +#endif
    +
    +QT_BEGIN_NAMESPACE
    +
    +class QTimeZone;
    +class QDateTime;
    +
    +class Q_CORE_EXPORT QDate
    +{
    +public:
    +    enum MonthNameType { // ### Qt 6: remove, along with methods using it
    +        DateFormat = 0,
    +        StandaloneFormat
    +    };
    +private:
    +    explicit Q_DECL_CONSTEXPR QDate(qint64 julianDay) : jd(julianDay) {}
    +public:
    +    Q_DECL_CONSTEXPR QDate() : jd(nullJd()) {}
    +    QDate(int y, int m, int d);
    +
    +    Q_DECL_CONSTEXPR bool isNull() const { return !isValid(); }
    +    Q_DECL_CONSTEXPR bool isValid() const { return jd >= minJd() && jd <= maxJd(); }
    +
    +    int year() const;
    +    int month() const;
    +    int day() const;
    +    int dayOfWeek() const;
    +    int dayOfYear() const;
    +    int daysInMonth() const;
    +    int daysInYear() const;
    +    int weekNumber(int *yearNum = nullptr) const;
    +
    +    QDateTime startOfDay(Qt::TimeSpec spec = Qt::LocalTime, int offsetSeconds = 0) const;
    +    QDateTime endOfDay(Qt::TimeSpec spec = Qt::LocalTime, int offsetSeconds = 0) const;
    +#if QT_CONFIG(timezone)
    +    QDateTime startOfDay(const QTimeZone &zone) const;
    +    QDateTime endOfDay(const QTimeZone &zone) const;
    +#endif
    +
    +#if QT_DEPRECATED_SINCE(5, 10) && QT_CONFIG(textdate)
    +    QT_DEPRECATED_X("Use QLocale::monthName or QLocale::standaloneMonthName")
    +        static QString shortMonthName(int month, MonthNameType type = DateFormat);
    +    QT_DEPRECATED_X("Use QLocale::dayName or QLocale::standaloneDayName")
    +        static QString shortDayName(int weekday, MonthNameType type = DateFormat);
    +    QT_DEPRECATED_X("Use QLocale::monthName or QLocale::standaloneMonthName")
    +        static QString longMonthName(int month, MonthNameType type = DateFormat);
    +    QT_DEPRECATED_X("Use QLocale::dayName or QLocale::standaloneDayName")
    +        static QString longDayName(int weekday, MonthNameType type = DateFormat);
    +#endif // textdate && deprecated
    +#if QT_CONFIG(datestring)
    +    QString toString(Qt::DateFormat f = Qt::TextDate) const;
    +#if QT_STRINGVIEW_LEVEL < 2
    +    QString toString(const QString &format) const;
    +#endif
    +    QString toString(QStringView format) const;
    +#endif
    +#if QT_DEPRECATED_SINCE(5,0)
    +    QT_DEPRECATED_X("Use setDate() instead") inline bool setYMD(int y, int m, int d)
    +    { if (uint(y) <= 99) y += 1900; return setDate(y, m, d); }
    +#endif
    +
    +    bool setDate(int year, int month, int day);
    +
    +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    +    void getDate(int *year, int *month, int *day); // ### Qt 6: remove
    +#endif // < Qt 6
    +    void getDate(int *year, int *month, int *day) const;
    +
    +    Q_REQUIRED_RESULT QDate addDays(qint64 days) const;
    +    Q_REQUIRED_RESULT QDate addMonths(int months) const;
    +    Q_REQUIRED_RESULT QDate addYears(int years) const;
    +    qint64 daysTo(const QDate &) const;
    +
    +    Q_DECL_CONSTEXPR bool operator==(const QDate &other) const { return jd == other.jd; }
    +    Q_DECL_CONSTEXPR bool operator!=(const QDate &other) const { return jd != other.jd; }
    +    Q_DECL_CONSTEXPR bool operator< (const QDate &other) const { return jd <  other.jd; }
    +    Q_DECL_CONSTEXPR bool operator<=(const QDate &other) const { return jd <= other.jd; }
    +    Q_DECL_CONSTEXPR bool operator> (const QDate &other) const { return jd >  other.jd; }
    +    Q_DECL_CONSTEXPR bool operator>=(const QDate &other) const { return jd >= other.jd; }
    +
    +    static QDate currentDate();
    +#if QT_CONFIG(datestring)
    +    static QDate fromString(const QString &s, Qt::DateFormat f = Qt::TextDate);
    +    static QDate fromString(const QString &s, const QString &format);
    +#endif
    +    static bool isValid(int y, int m, int d);
    +    static bool isLeapYear(int year);
    +
    +    static Q_DECL_CONSTEXPR inline QDate fromJulianDay(qint64 jd_)
    +    { return jd_ >= minJd() && jd_ <= maxJd() ? QDate(jd_) : QDate() ; }
    +    Q_DECL_CONSTEXPR inline qint64 toJulianDay() const { return jd; }
    +
    +private:
    +    // using extra parentheses around min to avoid expanding it if it is a macro
    +    static Q_DECL_CONSTEXPR inline qint64 nullJd() { return (std::numeric_limits::min)(); }
    +    static Q_DECL_CONSTEXPR inline qint64 minJd() { return Q_INT64_C(-784350574879); }
    +    static Q_DECL_CONSTEXPR inline qint64 maxJd() { return Q_INT64_C( 784354017364); }
    +
    +    qint64 jd;
    +
    +    friend class QDateTime;
    +    friend class QDateTimePrivate;
    +#ifndef QT_NO_DATASTREAM
    +    friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QDate &);
    +    friend Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QDate &);
    +#endif
    +};
    +Q_DECLARE_TYPEINFO(QDate, Q_MOVABLE_TYPE);
    +
    +class Q_CORE_EXPORT QTime
    +{
    +    explicit Q_DECL_CONSTEXPR QTime(int ms) : mds(ms)
    +    {}
    +public:
    +    Q_DECL_CONSTEXPR QTime(): mds(NullTime)
    +    {}
    +    QTime(int h, int m, int s = 0, int ms = 0);
    +
    +    Q_DECL_CONSTEXPR bool isNull() const { return mds == NullTime; }
    +    bool isValid() const;
    +
    +    int hour() const;
    +    int minute() const;
    +    int second() const;
    +    int msec() const;
    +#if QT_CONFIG(datestring)
    +    QString toString(Qt::DateFormat f = Qt::TextDate) const;
    +#if QT_STRINGVIEW_LEVEL < 2
    +    QString toString(const QString &format) const;
    +#endif
    +    QString toString(QStringView format) const;
    +#endif
    +    bool setHMS(int h, int m, int s, int ms = 0);
    +
    +    Q_REQUIRED_RESULT QTime addSecs(int secs) const;
    +    int secsTo(const QTime &) const;
    +    Q_REQUIRED_RESULT QTime addMSecs(int ms) const;
    +    int msecsTo(const QTime &) const;
    +
    +    Q_DECL_CONSTEXPR bool operator==(const QTime &other) const { return mds == other.mds; }
    +    Q_DECL_CONSTEXPR bool operator!=(const QTime &other) const { return mds != other.mds; }
    +    Q_DECL_CONSTEXPR bool operator< (const QTime &other) const { return mds <  other.mds; }
    +    Q_DECL_CONSTEXPR bool operator<=(const QTime &other) const { return mds <= other.mds; }
    +    Q_DECL_CONSTEXPR bool operator> (const QTime &other) const { return mds >  other.mds; }
    +    Q_DECL_CONSTEXPR bool operator>=(const QTime &other) const { return mds >= other.mds; }
    +
    +    static Q_DECL_CONSTEXPR inline QTime fromMSecsSinceStartOfDay(int msecs) { return QTime(msecs); }
    +    Q_DECL_CONSTEXPR inline int msecsSinceStartOfDay() const { return mds == NullTime ? 0 : mds; }
    +
    +    static QTime currentTime();
    +#if QT_CONFIG(datestring)
    +    static QTime fromString(const QString &s, Qt::DateFormat f = Qt::TextDate);
    +    static QTime fromString(const QString &s, const QString &format);
    +#endif
    +    static bool isValid(int h, int m, int s, int ms = 0);
    +
    +#if QT_DEPRECATED_SINCE(5, 14) // ### Qt 6: remove
    +    QT_DEPRECATED_X("Use QElapsedTimer instead") void start();
    +    QT_DEPRECATED_X("Use QElapsedTimer instead") int restart();
    +    QT_DEPRECATED_X("Use QElapsedTimer instead") int elapsed() const;
    +#endif
    +private:
    +    enum TimeFlag { NullTime = -1 };
    +    Q_DECL_CONSTEXPR inline int ds() const { return mds == -1 ? 0 : mds; }
    +    int mds;
    +
    +    friend class QDateTime;
    +    friend class QDateTimePrivate;
    +#ifndef QT_NO_DATASTREAM
    +    friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QTime &);
    +    friend Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QTime &);
    +#endif
    +};
    +Q_DECLARE_TYPEINFO(QTime, Q_MOVABLE_TYPE);
    +
    +class QDateTimePrivate;
    +
    +class Q_CORE_EXPORT QDateTime
    +{
    +    // ### Qt 6: revisit the optimization
    +    struct ShortData {
    +#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
    +        quintptr status : 8;
    +#endif
    +        // note: this is only 24 bits on 32-bit systems...
    +        qintptr msecs : sizeof(void *) * 8 - 8;
    +
    +#if Q_BYTE_ORDER == Q_BIG_ENDIAN
    +        quintptr status : 8;
    +#endif
    +    };
    +
    +    union Data {
    +        enum {
    +            // To be of any use, we need at least 60 years around 1970, which
    +            // is 1,893,456,000,000 ms. That requires 41 bits to store, plus
    +            // the sign bit. With the status byte, the minimum size is 50 bits.
    +            CanBeSmall = sizeof(ShortData) * 8 > 50
    +        };
    +
    +        Data();
    +        Data(Qt::TimeSpec);
    +        Data(const Data &other);
    +        Data(Data &&other);
    +        Data &operator=(const Data &other);
    +        ~Data();
    +
    +        bool isShort() const;
    +        void detach();
    +
    +        const QDateTimePrivate *operator->() const;
    +        QDateTimePrivate *operator->();
    +
    +        QDateTimePrivate *d;
    +        ShortData data;
    +    };
    +
    +public:
    +    QDateTime() noexcept(Data::CanBeSmall);
    +    explicit QDateTime(const QDate &);
    +    QDateTime(const QDate &, const QTime &, Qt::TimeSpec spec = Qt::LocalTime);
    +    // ### Qt 6: Merge with above with default offsetSeconds = 0
    +    QDateTime(const QDate &date, const QTime &time, Qt::TimeSpec spec, int offsetSeconds);
    +#if QT_CONFIG(timezone)
    +    QDateTime(const QDate &date, const QTime &time, const QTimeZone &timeZone);
    +#endif // timezone
    +    QDateTime(const QDateTime &other) noexcept;
    +    QDateTime(QDateTime &&other) noexcept;
    +    ~QDateTime();
    +
    +    QDateTime &operator=(QDateTime &&other) noexcept { swap(other); return *this; }
    +    QDateTime &operator=(const QDateTime &other) noexcept;
    +
    +    void swap(QDateTime &other) noexcept { qSwap(d.d, other.d.d); }
    +
    +    bool isNull() const;
    +    bool isValid() const;
    +
    +    QDate date() const;
    +    QTime time() const;
    +    Qt::TimeSpec timeSpec() const;
    +    int offsetFromUtc() const;
    +#if QT_CONFIG(timezone)
    +    QTimeZone timeZone() const;
    +#endif // timezone
    +    QString timeZoneAbbreviation() const;
    +    bool isDaylightTime() const;
    +
    +    qint64 toMSecsSinceEpoch() const;
    +    qint64 toSecsSinceEpoch() const;
    +
    +    void setDate(const QDate &date);
    +    void setTime(const QTime &time);
    +    void setTimeSpec(Qt::TimeSpec spec);
    +    void setOffsetFromUtc(int offsetSeconds);
    +#if QT_CONFIG(timezone)
    +    void setTimeZone(const QTimeZone &toZone);
    +#endif // timezone
    +    void setMSecsSinceEpoch(qint64 msecs);
    +    void setSecsSinceEpoch(qint64 secs);
    +
    +#if QT_CONFIG(datestring)
    +    QString toString(Qt::DateFormat f = Qt::TextDate) const;
    +#if QT_STRINGVIEW_LEVEL < 2
    +    QString toString(const QString &format) const;
    +#endif
    +    QString toString(QStringView format) const;
    +#endif
    +    Q_REQUIRED_RESULT QDateTime addDays(qint64 days) const;
    +    Q_REQUIRED_RESULT QDateTime addMonths(int months) const;
    +    Q_REQUIRED_RESULT QDateTime addYears(int years) const;
    +    Q_REQUIRED_RESULT QDateTime addSecs(qint64 secs) const;
    +    Q_REQUIRED_RESULT QDateTime addMSecs(qint64 msecs) const;
    +
    +    QDateTime toTimeSpec(Qt::TimeSpec spec) const;
    +    inline QDateTime toLocalTime() const { return toTimeSpec(Qt::LocalTime); }
    +    inline QDateTime toUTC() const { return toTimeSpec(Qt::UTC); }
    +    QDateTime toOffsetFromUtc(int offsetSeconds) const;
    +#if QT_CONFIG(timezone)
    +    QDateTime toTimeZone(const QTimeZone &toZone) const;
    +#endif // timezone
    +
    +    qint64 daysTo(const QDateTime &) const;
    +    qint64 secsTo(const QDateTime &) const;
    +    qint64 msecsTo(const QDateTime &) const;
    +
    +    bool operator==(const QDateTime &other) const;
    +    inline bool operator!=(const QDateTime &other) const { return !(*this == other); }
    +    bool operator<(const QDateTime &other) const;
    +    inline bool operator<=(const QDateTime &other) const { return !(other < *this); }
    +    inline bool operator>(const QDateTime &other) const { return other < *this; }
    +    inline bool operator>=(const QDateTime &other) const { return !(*this < other); }
    +
    +#if QT_DEPRECATED_SINCE(5, 2) // ### Qt 6: remove
    +    QT_DEPRECATED_X("Use setOffsetFromUtc() instead") void setUtcOffset(int seconds);
    +    QT_DEPRECATED_X("Use offsetFromUtc() instead") int utcOffset() const;
    +#endif // QT_DEPRECATED_SINCE
    +
    +    static QDateTime currentDateTime();
    +    static QDateTime currentDateTimeUtc();
    +#if QT_CONFIG(datestring)
    +    static QDateTime fromString(const QString &s, Qt::DateFormat f = Qt::TextDate);
    +    static QDateTime fromString(const QString &s, const QString &format);
    +#endif
    +
    +#if QT_DEPRECATED_SINCE(5, 8)
    +    uint toTime_t() const;
    +    void setTime_t(uint secsSince1Jan1970UTC);
    +    static QDateTime fromTime_t(uint secsSince1Jan1970UTC);
    +    static QDateTime fromTime_t(uint secsSince1Jan1970UTC, Qt::TimeSpec spec,
    +                                int offsetFromUtc = 0);
    +    static QDateTime fromTime_t(uint secsSince1Jan1970UTC, const QTimeZone &timeZone);
    +#endif
    +
    +    static QDateTime fromMSecsSinceEpoch(qint64 msecs);
    +    // ### Qt 6: Merge with above with default spec = Qt::LocalTime
    +    static QDateTime fromMSecsSinceEpoch(qint64 msecs, Qt::TimeSpec spec, int offsetFromUtc = 0);
    +    static QDateTime fromSecsSinceEpoch(qint64 secs, Qt::TimeSpec spe = Qt::LocalTime, int offsetFromUtc = 0);
    +
    +#if QT_CONFIG(timezone)
    +    static QDateTime fromMSecsSinceEpoch(qint64 msecs, const QTimeZone &timeZone);
    +    static QDateTime fromSecsSinceEpoch(qint64 secs, const QTimeZone &timeZone);
    +#endif
    +
    +    static qint64 currentMSecsSinceEpoch() noexcept;
    +    static qint64 currentSecsSinceEpoch() noexcept;
    +
    +#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
    +    static QDateTime fromCFDate(CFDateRef date);
    +    CFDateRef toCFDate() const Q_DECL_CF_RETURNS_RETAINED;
    +    static QDateTime fromNSDate(const NSDate *date);
    +    NSDate *toNSDate() const Q_DECL_NS_RETURNS_AUTORELEASED;
    +#endif
    +
    +private:
    +    friend class QDateTimePrivate;
    +
    +    Data d;
    +
    +#ifndef QT_NO_DATASTREAM
    +    friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QDateTime &);
    +    friend Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QDateTime &);
    +#endif
    +
    +#if !defined(QT_NO_DEBUG_STREAM) && QT_CONFIG(datestring)
    +    friend Q_CORE_EXPORT QDebug operator<<(QDebug, const QDateTime &);
    +#endif
    +};
    +Q_DECLARE_SHARED(QDateTime)
    +
    +#ifndef QT_NO_DATASTREAM
    +Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QDate &);
    +Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QDate &);
    +Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QTime &);
    +Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QTime &);
    +Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QDateTime &);
    +Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QDateTime &);
    +#endif // QT_NO_DATASTREAM
    +
    +#if !defined(QT_NO_DEBUG_STREAM) && QT_CONFIG(datestring)
    +Q_CORE_EXPORT QDebug operator<<(QDebug, const QDate &);
    +Q_CORE_EXPORT QDebug operator<<(QDebug, const QTime &);
    +Q_CORE_EXPORT QDebug operator<<(QDebug, const QDateTime &);
    +#endif
    +
    +// QDateTime is not noexcept for now -- to be revised once
    +// timezone and calendaring support is added
    +Q_CORE_EXPORT uint qHash(const QDateTime &key, uint seed = 0);
    +Q_CORE_EXPORT uint qHash(const QDate &key, uint seed = 0) noexcept;
    +Q_CORE_EXPORT uint qHash(const QTime &key, uint seed = 0) noexcept;
    +
    +QT_END_NAMESPACE
    +
    +#endif // QDATETIME_H
    diff --git a/src/corelib/time/qdatetime_p.h b/src/corelib/time/qdatetime_p.h
    new file mode 100644
    index 0000000000..6018f8f7b0
    --- /dev/null
    +++ b/src/corelib/time/qdatetime_p.h
    @@ -0,0 +1,151 @@
    +/****************************************************************************
    +**
    +** Copyright (C) 2016 The Qt Company Ltd.
    +** Copyright (C) 2016 Intel Corporation.
    +** Contact: https://www.qt.io/licensing/
    +**
    +** This file is part of the QtCore module of the Qt Toolkit.
    +**
    +** $QT_BEGIN_LICENSE:LGPL$
    +** Commercial License Usage
    +** Licensees holding valid commercial Qt licenses may use this file in
    +** accordance with the commercial license agreement provided with the
    +** Software or, alternatively, in accordance with the terms contained in
    +** a written agreement between you and The Qt Company. For licensing terms
    +** and conditions see https://www.qt.io/terms-conditions. For further
    +** information use the contact form at https://www.qt.io/contact-us.
    +**
    +** GNU Lesser General Public License Usage
    +** Alternatively, this file may be used under the terms of the GNU Lesser
    +** General Public License version 3 as published by the Free Software
    +** Foundation and appearing in the file LICENSE.LGPL3 included in the
    +** packaging of this file. Please review the following information to
    +** ensure the GNU Lesser General Public License version 3 requirements
    +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
    +**
    +** GNU General Public License Usage
    +** Alternatively, this file may be used under the terms of the GNU
    +** General Public License version 2.0 or (at your option) the GNU General
    +** Public license version 3 or any later version approved by the KDE Free
    +** Qt Foundation. The licenses are as published by the Free Software
    +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
    +** included in the packaging of this file. Please review the following
    +** information to ensure the GNU General Public License requirements will
    +** be met: https://www.gnu.org/licenses/gpl-2.0.html and
    +** https://www.gnu.org/licenses/gpl-3.0.html.
    +**
    +** $QT_END_LICENSE$
    +**
    +****************************************************************************/
    +
    +#ifndef QDATETIME_P_H
    +#define QDATETIME_P_H
    +
    +//
    +//  W A R N I N G
    +//  -------------
    +//
    +// This file is not part of the Qt API.  It exists purely as an
    +// implementation detail.  This header file may change from version to
    +// version without notice, or even be removed.
    +//
    +// We mean it.
    +//
    +
    +#include 
    +#include "qplatformdefs.h"
    +#include "QtCore/qatomic.h"
    +#include "QtCore/qdatetime.h"
    +#include "QtCore/qpair.h"
    +
    +#if QT_CONFIG(timezone)
    +#include "qtimezone.h"
    +#endif
    +
    +QT_BEGIN_NAMESPACE
    +
    +class QDateTimePrivate
    +{
    +public:
    +    // forward the declarations from QDateTime (this makes them public)
    +    typedef QDateTime::ShortData QDateTimeShortData;
    +    typedef QDateTime::Data QDateTimeData;
    +
    +    // Never change or delete this enum, it is required for backwards compatible
    +    // serialization of QDateTime before 5.2, so is essentially public API
    +    enum Spec {
    +        LocalUnknown = -1,
    +        LocalStandard = 0,
    +        LocalDST = 1,
    +        UTC = 2,
    +        OffsetFromUTC = 3,
    +        TimeZone = 4
    +    };
    +
    +    // Daylight Time Status
    +    enum DaylightStatus {
    +        UnknownDaylightTime = -1,
    +        StandardTime = 0,
    +        DaylightTime = 1
    +    };
    +
    +    // Status of date/time
    +    enum StatusFlag {
    +        ShortData           = 0x01,
    +
    +        ValidDate           = 0x02,
    +        ValidTime           = 0x04,
    +        ValidDateTime       = 0x08,
    +
    +        TimeSpecMask        = 0x30,
    +
    +        SetToStandardTime   = 0x40,
    +        SetToDaylightTime   = 0x80
    +    };
    +    Q_DECLARE_FLAGS(StatusFlags, StatusFlag)
    +
    +    enum {
    +        TimeSpecShift = 4,
    +        ValidityMask        = ValidDate | ValidTime | ValidDateTime,
    +        DaylightMask        = SetToStandardTime | SetToDaylightTime
    +    };
    +
    +    QDateTimePrivate() : m_msecs(0),
    +                         m_status(StatusFlag(Qt::LocalTime << TimeSpecShift)),
    +                         m_offsetFromUtc(0),
    +                         ref(0)
    +    {
    +    }
    +
    +    static QDateTime::Data create(const QDate &toDate, const QTime &toTime, Qt::TimeSpec toSpec,
    +                                  int offsetSeconds);
    +
    +#if QT_CONFIG(timezone)
    +    static QDateTime::Data create(const QDate &toDate, const QTime &toTime, const QTimeZone & timeZone);
    +#endif // timezone
    +
    +    qint64 m_msecs;
    +    StatusFlags m_status;
    +    int m_offsetFromUtc;
    +    mutable QAtomicInt ref;
    +#if QT_CONFIG(timezone)
    +    QTimeZone m_timeZone;
    +#endif // timezone
    +
    +#if QT_CONFIG(timezone)
    +    static qint64 zoneMSecsToEpochMSecs(qint64 msecs, const QTimeZone &zone,
    +                                        DaylightStatus hint = UnknownDaylightTime,
    +                                        QDate *localDate = nullptr, QTime *localTime = nullptr);
    +
    +    // Inlined for its one caller in qdatetime.cpp
    +    inline void setUtcOffsetByTZ(qint64 atMSecsSinceEpoch);
    +#endif // timezone
    +
    +    // ### Qt 5.14: expose publicly in QDateTime
    +    // The first and last years of which QDateTime can represent some part:
    +    enum class YearRange : qint32 { First = -292275056,  Last = +292278994 };
    +};
    +
    +QT_END_NAMESPACE
    +
    +#endif // QDATETIME_P_H
    diff --git a/src/corelib/time/qdatetimeparser.cpp b/src/corelib/time/qdatetimeparser.cpp
    new file mode 100644
    index 0000000000..728b066db1
    --- /dev/null
    +++ b/src/corelib/time/qdatetimeparser.cpp
    @@ -0,0 +1,2047 @@
    +/****************************************************************************
    +**
    +** Copyright (C) 2016 The Qt Company Ltd.
    +** Contact: https://www.qt.io/licensing/
    +**
    +** This file is part of the QtCore module of the Qt Toolkit.
    +**
    +** $QT_BEGIN_LICENSE:LGPL$
    +** Commercial License Usage
    +** Licensees holding valid commercial Qt licenses may use this file in
    +** accordance with the commercial license agreement provided with the
    +** Software or, alternatively, in accordance with the terms contained in
    +** a written agreement between you and The Qt Company. For licensing terms
    +** and conditions see https://www.qt.io/terms-conditions. For further
    +** information use the contact form at https://www.qt.io/contact-us.
    +**
    +** GNU Lesser General Public License Usage
    +** Alternatively, this file may be used under the terms of the GNU Lesser
    +** General Public License version 3 as published by the Free Software
    +** Foundation and appearing in the file LICENSE.LGPL3 included in the
    +** packaging of this file. Please review the following information to
    +** ensure the GNU Lesser General Public License version 3 requirements
    +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
    +**
    +** GNU General Public License Usage
    +** Alternatively, this file may be used under the terms of the GNU
    +** General Public License version 2.0 or (at your option) the GNU General
    +** Public license version 3 or any later version approved by the KDE Free
    +** Qt Foundation. The licenses are as published by the Free Software
    +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
    +** included in the packaging of this file. Please review the following
    +** information to ensure the GNU General Public License requirements will
    +** be met: https://www.gnu.org/licenses/gpl-2.0.html and
    +** https://www.gnu.org/licenses/gpl-3.0.html.
    +**
    +** $QT_END_LICENSE$
    +**
    +****************************************************************************/
    +
    +#include "qplatformdefs.h"
    +#include "private/qdatetimeparser_p.h"
    +
    +#include "qdatastream.h"
    +#include "qset.h"
    +#include "qlocale.h"
    +#include "qdatetime.h"
    +#if QT_CONFIG(timezone)
    +#include "qtimezone.h"
    +#endif
    +#include "qdebug.h"
    +
    +//#define QDATETIMEPARSER_DEBUG
    +#if defined (QDATETIMEPARSER_DEBUG) && !defined(QT_NO_DEBUG_STREAM)
    +#  define QDTPDEBUG qDebug()
    +#  define QDTPDEBUGN qDebug
    +#else
    +#  define QDTPDEBUG if (false) qDebug()
    +#  define QDTPDEBUGN if (false) qDebug
    +#endif
    +
    +QT_BEGIN_NAMESPACE
    +
    +QDateTimeParser::~QDateTimeParser()
    +{
    +}
    +
    +/*!
    +  \internal
    +  Gets the digit from a datetime. E.g.
    +
    +  QDateTime var(QDate(2004, 02, 02));
    +  int digit = getDigit(var, Year);
    +  // digit = 2004
    +*/
    +
    +int QDateTimeParser::getDigit(const QDateTime &t, int index) const
    +{
    +    if (index < 0 || index >= sectionNodes.size()) {
    +#if QT_CONFIG(datestring)
    +        qWarning("QDateTimeParser::getDigit() Internal error (%ls %d)",
    +                 qUtf16Printable(t.toString()), index);
    +#else
    +        qWarning("QDateTimeParser::getDigit() Internal error (%d)", index);
    +#endif
    +        return -1;
    +    }
    +    const SectionNode &node = sectionNodes.at(index);
    +    switch (node.type) {
    +    case TimeZoneSection: return t.offsetFromUtc();
    +    case Hour24Section: case Hour12Section: return t.time().hour();
    +    case MinuteSection: return t.time().minute();
    +    case SecondSection: return t.time().second();
    +    case MSecSection: return t.time().msec();
    +    case YearSection2Digits:
    +    case YearSection: return t.date().year();
    +    case MonthSection: return t.date().month();
    +    case DaySection: return t.date().day();
    +    case DayOfWeekSectionShort:
    +    case DayOfWeekSectionLong: return t.date().day();
    +    case AmPmSection: return t.time().hour() > 11 ? 1 : 0;
    +
    +    default: break;
    +    }
    +
    +#if QT_CONFIG(datestring)
    +    qWarning("QDateTimeParser::getDigit() Internal error 2 (%ls %d)",
    +             qUtf16Printable(t.toString()), index);
    +#else
    +    qWarning("QDateTimeParser::getDigit() Internal error 2 (%d)", index);
    +#endif
    +    return -1;
    +}
    +
    +/*!
    +  \internal
    +  Sets a digit in a datetime. E.g.
    +
    +  QDateTime var(QDate(2004, 02, 02));
    +  int digit = getDigit(var, Year);
    +  // digit = 2004
    +  setDigit(&var, Year, 2005);
    +  digit = getDigit(var, Year);
    +  // digit = 2005
    +*/
    +
    +bool QDateTimeParser::setDigit(QDateTime &v, int index, int newVal) const
    +{
    +    if (index < 0 || index >= sectionNodes.size()) {
    +#if QT_CONFIG(datestring)
    +        qWarning("QDateTimeParser::setDigit() Internal error (%ls %d %d)",
    +                 qUtf16Printable(v.toString()), index, newVal);
    +#else
    +        qWarning("QDateTimeParser::setDigit() Internal error (%d %d)", index, newVal);
    +#endif
    +        return false;
    +    }
    +    const SectionNode &node = sectionNodes.at(index);
    +
    +    const QDate date = v.date();
    +    const QTime time = v.time();
    +    int year = date.year();
    +    int month = date.month();
    +    int day = date.day();
    +    int hour = time.hour();
    +    int minute = time.minute();
    +    int second = time.second();
    +    int msec = time.msec();
    +    Qt::TimeSpec tspec = v.timeSpec();
    +    // Only offset from UTC is amenable to setting an int value:
    +    int offset = tspec == Qt::OffsetFromUTC ? v.offsetFromUtc() : 0;
    +
    +    switch (node.type) {
    +    case Hour24Section: case Hour12Section: hour = newVal; break;
    +    case MinuteSection: minute = newVal; break;
    +    case SecondSection: second = newVal; break;
    +    case MSecSection: msec = newVal; break;
    +    case YearSection2Digits:
    +    case YearSection: year = newVal; break;
    +    case MonthSection: month = newVal; break;
    +    case DaySection:
    +    case DayOfWeekSectionShort:
    +    case DayOfWeekSectionLong:
    +        if (newVal > 31) {
    +            // have to keep legacy behavior. setting the
    +            // date to 32 should return false. Setting it
    +            // to 31 for february should return true
    +            return false;
    +        }
    +        day = newVal;
    +        break;
    +    case TimeZoneSection:
    +        if (newVal < absoluteMin(index) || newVal > absoluteMax(index))
    +            return false;
    +        tspec = Qt::OffsetFromUTC;
    +        offset = newVal;
    +        break;
    +    case AmPmSection: hour = (newVal == 0 ? hour % 12 : (hour % 12) + 12); break;
    +    default:
    +        qWarning("QDateTimeParser::setDigit() Internal error (%ls)",
    +                 qUtf16Printable(node.name()));
    +        break;
    +    }
    +
    +    if (!(node.type & DaySectionMask)) {
    +        if (day < cachedDay)
    +            day = cachedDay;
    +        const int max = QDate(year, month, 1).daysInMonth();
    +        if (day > max) {
    +            day = max;
    +        }
    +    }
    +
    +    const QDate newDate(year, month, day);
    +    const QTime newTime(hour, minute, second, msec);
    +    if (!newDate.isValid() || !newTime.isValid())
    +        return false;
    +
    +    // Preserve zone:
    +    v =
    +#if QT_CONFIG(timezone)
    +         tspec == Qt::TimeZone ? QDateTime(newDate, newTime, v.timeZone()) :
    +#endif
    +         QDateTime(newDate, newTime, tspec, offset);
    +    return true;
    +}
    +
    +
    +
    +/*!
    +  \internal
    +
    +  Returns the absolute maximum for a section
    +*/
    +
    +int QDateTimeParser::absoluteMax(int s, const QDateTime &cur) const
    +{
    +    const SectionNode &sn = sectionNode(s);
    +    switch (sn.type) {
    +#if QT_CONFIG(timezone)
    +    case TimeZoneSection: return QTimeZone::MaxUtcOffsetSecs;
    +#endif
    +    case Hour24Section:
    +    case Hour12Section: return 23; // this is special-cased in
    +                                   // parseSection. We want it to be
    +                                   // 23 for the stepBy case.
    +    case MinuteSection:
    +    case SecondSection: return 59;
    +    case MSecSection: return 999;
    +    case YearSection2Digits:
    +    case YearSection: return 9999; // sectionMaxSize will prevent
    +                                   // people from typing in a larger
    +                                   // number in count == 2 sections.
    +                                   // stepBy() will work on real years anyway
    +    case MonthSection: return 12;
    +    case DaySection:
    +    case DayOfWeekSectionShort:
    +    case DayOfWeekSectionLong: return cur.isValid() ? cur.date().daysInMonth() : 31;
    +    case AmPmSection: return 1;
    +    default: break;
    +    }
    +    qWarning("QDateTimeParser::absoluteMax() Internal error (%ls)",
    +             qUtf16Printable(sn.name()));
    +    return -1;
    +}
    +
    +/*!
    +  \internal
    +
    +  Returns the absolute minimum for a section
    +*/
    +
    +int QDateTimeParser::absoluteMin(int s) const
    +{
    +    const SectionNode &sn = sectionNode(s);
    +    switch (sn.type) {
    +#if QT_CONFIG(timezone)
    +    case TimeZoneSection: return QTimeZone::MinUtcOffsetSecs;
    +#endif
    +    case Hour24Section:
    +    case Hour12Section:
    +    case MinuteSection:
    +    case SecondSection:
    +    case MSecSection:
    +    case YearSection2Digits:
    +    case YearSection: return 0;
    +    case MonthSection:
    +    case DaySection:
    +    case DayOfWeekSectionShort:
    +    case DayOfWeekSectionLong: return 1;
    +    case AmPmSection: return 0;
    +    default: break;
    +    }
    +    qWarning("QDateTimeParser::absoluteMin() Internal error (%ls, %0x)",
    +             qUtf16Printable(sn.name()), sn.type);
    +    return -1;
    +}
    +
    +/*!
    +  \internal
    +
    +  Returns the sectionNode for the Section \a s.
    +*/
    +
    +const QDateTimeParser::SectionNode &QDateTimeParser::sectionNode(int sectionIndex) const
    +{
    +    if (sectionIndex < 0) {
    +        switch (sectionIndex) {
    +        case FirstSectionIndex:
    +            return first;
    +        case LastSectionIndex:
    +            return last;
    +        case NoSectionIndex:
    +            return none;
    +        }
    +    } else if (sectionIndex < sectionNodes.size()) {
    +        return sectionNodes.at(sectionIndex);
    +    }
    +
    +    qWarning("QDateTimeParser::sectionNode() Internal error (%d)",
    +             sectionIndex);
    +    return none;
    +}
    +
    +QDateTimeParser::Section QDateTimeParser::sectionType(int sectionIndex) const
    +{
    +    return sectionNode(sectionIndex).type;
    +}
    +
    +
    +/*!
    +  \internal
    +
    +  Returns the starting position for section \a s.
    +*/
    +
    +int QDateTimeParser::sectionPos(int sectionIndex) const
    +{
    +    return sectionPos(sectionNode(sectionIndex));
    +}
    +
    +int QDateTimeParser::sectionPos(const SectionNode &sn) const
    +{
    +    switch (sn.type) {
    +    case FirstSection: return 0;
    +    case LastSection: return displayText().size() - 1;
    +    default: break;
    +    }
    +    if (sn.pos == -1) {
    +        qWarning("QDateTimeParser::sectionPos Internal error (%ls)", qUtf16Printable(sn.name()));
    +        return -1;
    +    }
    +    return sn.pos;
    +}
    +
    +
    +/*!
    +  \internal
    +
    +  helper function for parseFormat. removes quotes that are
    +  not escaped and removes the escaping on those that are escaped
    +
    +*/
    +
    +static QString unquote(const QStringRef &str)
    +{
    +    const QChar quote(QLatin1Char('\''));
    +    const QChar slash(QLatin1Char('\\'));
    +    const QChar zero(QLatin1Char('0'));
    +    QString ret;
    +    QChar status(zero);
    +    const int max = str.size();
    +    for (int i=0; iappend(lastQuote >= from ? unquote(separator) : separator.toString());
    +}
    +
    +
    +bool QDateTimeParser::parseFormat(const QString &newFormat)
    +{
    +    const QLatin1Char quote('\'');
    +    const QLatin1Char slash('\\');
    +    const QLatin1Char zero('0');
    +    if (newFormat == displayFormat && !newFormat.isEmpty()) {
    +        return true;
    +    }
    +
    +    QDTPDEBUGN("parseFormat: %s", newFormat.toLatin1().constData());
    +
    +    QVector newSectionNodes;
    +    Sections newDisplay = 0;
    +    QStringList newSeparators;
    +    int i, index = 0;
    +    int add = 0;
    +    QChar status(zero);
    +    const int max = newFormat.size();
    +    int lastQuote = -1;
    +    for (i = 0; i 0 && newFormat.at(i - 1) != slash) {
    +                status = zero;
    +            }
    +        } else if (status != quote) {
    +            const char sect = newFormat.at(i).toLatin1();
    +            switch (sect) {
    +            case 'H':
    +            case 'h':
    +                if (parserType != QVariant::Date) {
    +                    const Section hour = (sect == 'h') ? Hour12Section : Hour24Section;
    +                    const SectionNode sn = { hour, i - add, countRepeat(newFormat, i, 2), 0 };
    +                    newSectionNodes.append(sn);
    +                    appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
    +                    i += sn.count - 1;
    +                    index = i + 1;
    +                    newDisplay |= hour;
    +                }
    +                break;
    +            case 'm':
    +                if (parserType != QVariant::Date) {
    +                    const SectionNode sn = { MinuteSection, i - add, countRepeat(newFormat, i, 2), 0 };
    +                    newSectionNodes.append(sn);
    +                    appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
    +                    i += sn.count - 1;
    +                    index = i + 1;
    +                    newDisplay |= MinuteSection;
    +                }
    +                break;
    +            case 's':
    +                if (parserType != QVariant::Date) {
    +                    const SectionNode sn = { SecondSection, i - add, countRepeat(newFormat, i, 2), 0 };
    +                    newSectionNodes.append(sn);
    +                    appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
    +                    i += sn.count - 1;
    +                    index = i + 1;
    +                    newDisplay |= SecondSection;
    +                }
    +                break;
    +
    +            case 'z':
    +                if (parserType != QVariant::Date) {
    +                    const SectionNode sn = { MSecSection, i - add, countRepeat(newFormat, i, 3) < 3 ? 1 : 3, 0 };
    +                    newSectionNodes.append(sn);
    +                    appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
    +                    i += sn.count - 1;
    +                    index = i + 1;
    +                    newDisplay |= MSecSection;
    +                }
    +                break;
    +            case 'A':
    +            case 'a':
    +                if (parserType != QVariant::Date) {
    +                    const bool cap = (sect == 'A');
    +                    const SectionNode sn = { AmPmSection, i - add, (cap ? 1 : 0), 0 };
    +                    newSectionNodes.append(sn);
    +                    appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
    +                    newDisplay |= AmPmSection;
    +                    if (i + 1 < newFormat.size()
    +                        && newFormat.at(i+1) == (cap ? QLatin1Char('P') : QLatin1Char('p'))) {
    +                        ++i;
    +                    }
    +                    index = i + 1;
    +                }
    +                break;
    +            case 'y':
    +                if (parserType != QVariant::Time) {
    +                    const int repeat = countRepeat(newFormat, i, 4);
    +                    if (repeat >= 2) {
    +                        const SectionNode sn = { repeat == 4 ? YearSection : YearSection2Digits,
    +                                                 i - add, repeat == 4 ? 4 : 2, 0 };
    +                        newSectionNodes.append(sn);
    +                        appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
    +                        i += sn.count - 1;
    +                        index = i + 1;
    +                        newDisplay |= sn.type;
    +                    }
    +                }
    +                break;
    +            case 'M':
    +                if (parserType != QVariant::Time) {
    +                    const SectionNode sn = { MonthSection, i - add, countRepeat(newFormat, i, 4), 0 };
    +                    newSectionNodes.append(sn);
    +                    newSeparators.append(unquote(newFormat.midRef(index, i - index)));
    +                    i += sn.count - 1;
    +                    index = i + 1;
    +                    newDisplay |= MonthSection;
    +                }
    +                break;
    +            case 'd':
    +                if (parserType != QVariant::Time) {
    +                    const int repeat = countRepeat(newFormat, i, 4);
    +                    const Section sectionType = (repeat == 4 ? DayOfWeekSectionLong
    +                        : (repeat == 3 ? DayOfWeekSectionShort : DaySection));
    +                    const SectionNode sn = { sectionType, i - add, repeat, 0 };
    +                    newSectionNodes.append(sn);
    +                    appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
    +                    i += sn.count - 1;
    +                    index = i + 1;
    +                    newDisplay |= sn.type;
    +                }
    +                break;
    +            case 't':
    +                if (parserType != QVariant::Time) {
    +                    const SectionNode sn = { TimeZoneSection, i - add, countRepeat(newFormat, i, 4), 0 };
    +                    newSectionNodes.append(sn);
    +                    appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
    +                    i += sn.count - 1;
    +                    index = i + 1;
    +                    newDisplay |= TimeZoneSection;
    +                }
    +                break;
    +            default:
    +                break;
    +            }
    +        }
    +    }
    +    if (newSectionNodes.isEmpty() && context == DateTimeEdit) {
    +        return false;
    +    }
    +
    +    if ((newDisplay & (AmPmSection|Hour12Section)) == Hour12Section) {
    +        const int count = newSectionNodes.size();
    +        for (int i = 0; i < count; ++i) {
    +            SectionNode &node = newSectionNodes[i];
    +            if (node.type == Hour12Section)
    +                node.type = Hour24Section;
    +        }
    +    }
    +
    +    if (index < max) {
    +        appendSeparator(&newSeparators, newFormat, index, index - max, lastQuote);
    +    } else {
    +        newSeparators.append(QString());
    +    }
    +
    +    displayFormat = newFormat;
    +    separators = newSeparators;
    +    sectionNodes = newSectionNodes;
    +    display = newDisplay;
    +    last.pos = -1;
    +
    +//     for (int i=0; i= sectionNodes.size()) {
    +        qWarning("QDateTimeParser::sectionSize Internal error (%d)", sectionIndex);
    +        return -1;
    +    }
    +
    +    if (sectionIndex == sectionNodes.size() - 1) {
    +        // In some cases there is a difference between displayText() and text.
    +        // e.g. when text is 2000/01/31 and displayText() is "2000/2/31" - text
    +        // is the previous value and displayText() is the new value.
    +        // The size difference is always due to leading zeroes.
    +        int sizeAdjustment = 0;
    +        const int displayTextSize = displayText().size();
    +        if (displayTextSize != text.size()) {
    +            // Any zeroes added before this section will affect our size.
    +            int preceedingZeroesAdded = 0;
    +            if (sectionNodes.size() > 1 && context == DateTimeEdit) {
    +                const auto begin = sectionNodes.cbegin();
    +                const auto end = begin + sectionIndex;
    +                for (auto sectionIt = begin; sectionIt != end; ++sectionIt)
    +                    preceedingZeroesAdded += sectionIt->zeroesAdded;
    +            }
    +            sizeAdjustment = preceedingZeroesAdded;
    +        }
    +
    +        return displayTextSize + sizeAdjustment - sectionPos(sectionIndex) - separators.last().size();
    +    } else {
    +        return sectionPos(sectionIndex + 1) - sectionPos(sectionIndex)
    +            - separators.at(sectionIndex + 1).size();
    +    }
    +}
    +
    +
    +int QDateTimeParser::sectionMaxSize(Section s, int count) const
    +{
    +#if QT_CONFIG(textdate)
    +    int mcount = 12;
    +#endif
    +
    +    switch (s) {
    +    case FirstSection:
    +    case NoSection:
    +    case LastSection: return 0;
    +
    +    case AmPmSection: {
    +        const int lowerMax = qMin(getAmPmText(AmText, LowerCase).size(),
    +                                  getAmPmText(PmText, LowerCase).size());
    +        const int upperMax = qMin(getAmPmText(AmText, UpperCase).size(),
    +                                  getAmPmText(PmText, UpperCase).size());
    +        return qMin(4, qMin(lowerMax, upperMax));
    +    }
    +
    +    case Hour24Section:
    +    case Hour12Section:
    +    case MinuteSection:
    +    case SecondSection:
    +    case DaySection: return 2;
    +    case DayOfWeekSectionShort:
    +    case DayOfWeekSectionLong:
    +#if !QT_CONFIG(textdate)
    +        return 2;
    +#else
    +        mcount = 7;
    +        Q_FALLTHROUGH();
    +#endif
    +    case MonthSection:
    +#if !QT_CONFIG(textdate)
    +        return 2;
    +#else
    +        if (count <= 2)
    +            return 2;
    +
    +        {
    +            int ret = 0;
    +            const QLocale l = locale();
    +            const QLocale::FormatType format = count == 4 ? QLocale::LongFormat : QLocale::ShortFormat;
    +            for (int i=1; i<=mcount; ++i) {
    +                const QString str = (s == MonthSection
    +                                     ? l.monthName(i, format)
    +                                     : l.dayName(i, format));
    +                ret = qMax(str.size(), ret);
    +            }
    +            return ret;
    +        }
    +#endif
    +    case MSecSection: return 3;
    +    case YearSection: return 4;
    +    case YearSection2Digits: return 2;
    +        // Arbitrarily many tokens (each up to 14 bytes) joined with / separators:
    +    case TimeZoneSection: return std::numeric_limits::max();
    +
    +    case CalendarPopupSection:
    +    case Internal:
    +    case TimeSectionMask:
    +    case DateSectionMask:
    +    case HourSectionMask:
    +    case YearSectionMask:
    +    case DayOfWeekSectionMask:
    +    case DaySectionMask:
    +        qWarning("QDateTimeParser::sectionMaxSize: Invalid section %s",
    +                 SectionNode::name(s).toLatin1().constData());
    +
    +    case NoSectionIndex:
    +    case FirstSectionIndex:
    +    case LastSectionIndex:
    +    case CalendarPopupIndex:
    +        // these cases can't happen
    +        break;
    +    }
    +    return -1;
    +}
    +
    +
    +int QDateTimeParser::sectionMaxSize(int index) const
    +{
    +    const SectionNode &sn = sectionNode(index);
    +    return sectionMaxSize(sn.type, sn.count);
    +}
    +
    +/*!
    +  \internal
    +
    +  Returns the text of section \a s. This function operates on the
    +  arg text rather than edit->text().
    +*/
    +
    +
    +QString QDateTimeParser::sectionText(const QString &text, int sectionIndex, int index) const
    +{
    +    const SectionNode &sn = sectionNode(sectionIndex);
    +    switch (sn.type) {
    +    case NoSectionIndex:
    +    case FirstSectionIndex:
    +    case LastSectionIndex:
    +        return QString();
    +    default: break;
    +    }
    +
    +    return text.mid(index, sectionSize(sectionIndex));
    +}
    +
    +QString QDateTimeParser::sectionText(int sectionIndex) const
    +{
    +    const SectionNode &sn = sectionNode(sectionIndex);
    +    return sectionText(displayText(), sectionIndex, sn.pos);
    +}
    +
    +
    +#if QT_CONFIG(datestring)
    +
    +QDateTimeParser::ParsedSection
    +QDateTimeParser::parseSection(const QDateTime ¤tValue, int sectionIndex,
    +                              int offset, QString *text) const
    +{
    +    ParsedSection result; // initially Invalid
    +    const SectionNode &sn = sectionNode(sectionIndex);
    +    if (sn.type & Internal) {
    +        qWarning("QDateTimeParser::parseSection Internal error (%ls %d)",
    +                 qUtf16Printable(sn.name()), sectionIndex);
    +        return result;
    +    }
    +
    +    const int sectionmaxsize = sectionMaxSize(sectionIndex);
    +    QStringRef sectionTextRef = text->midRef(offset, sectionmaxsize);
    +
    +    QDTPDEBUG << "sectionValue for" << sn.name()
    +              << "with text" << *text << "and (at" << offset
    +              << ") st:" << sectionTextRef;
    +
    +    switch (sn.type) {
    +    case AmPmSection: {
    +        QString sectiontext = sectionTextRef.toString();
    +        int used;
    +        const int ampm = findAmPm(sectiontext, sectionIndex, &used);
    +        switch (ampm) {
    +        case AM: // sectiontext == AM
    +        case PM: // sectiontext == PM
    +            result = ParsedSection(Acceptable, ampm, used);
    +            break;
    +        case PossibleAM: // sectiontext => AM
    +        case PossiblePM: // sectiontext => PM
    +            result = ParsedSection(Intermediate, ampm - 2, used);
    +            break;
    +        case PossibleBoth: // sectiontext => AM|PM
    +            result = ParsedSection(Intermediate, 0, used);
    +            break;
    +        case Neither:
    +            QDTPDEBUG << "invalid because findAmPm(" << sectiontext << ") returned -1";
    +            break;
    +        default:
    +            QDTPDEBUGN("This should never happen (findAmPm returned %d)", ampm);
    +            break;
    +        }
    +        if (result.state != Invalid)
    +            text->replace(offset, used, sectiontext.constData(), used);
    +        break; }
    +    case TimeZoneSection:
    +#if QT_CONFIG(timezone)
    +        result = findTimeZone(sectionTextRef, currentValue,
    +                              absoluteMax(sectionIndex),
    +                              absoluteMin(sectionIndex));
    +#endif
    +        break;
    +    case MonthSection:
    +    case DayOfWeekSectionShort:
    +    case DayOfWeekSectionLong:
    +        if (sn.count >= 3) {
    +            QString sectiontext = sectionTextRef.toString();
    +            int num = 0, used = 0;
    +            if (sn.type == MonthSection) {
    +                const QDate minDate = getMinimum().date();
    +                const int min = (currentValue.date().year() == minDate.year())
    +                    ? minDate.month() : 1;
    +                num = findMonth(sectiontext.toLower(), min, sectionIndex, §iontext, &used);
    +            } else {
    +                num = findDay(sectiontext.toLower(), 1, sectionIndex, §iontext, &used);
    +            }
    +
    +            result = ParsedSection(Intermediate, num, used);
    +            if (num != -1) {
    +                text->replace(offset, used, sectiontext.constData(), used);
    +                if (used == sectiontext.size())
    +                    result = ParsedSection(Acceptable, num, used);
    +            }
    +            break;
    +        }
    +        Q_FALLTHROUGH();
    +        // All numeric:
    +    case DaySection:
    +    case YearSection:
    +    case YearSection2Digits:
    +    case Hour12Section:
    +    case Hour24Section:
    +    case MinuteSection:
    +    case SecondSection:
    +    case MSecSection: {
    +        int sectiontextSize = sectionTextRef.size();
    +        if (sectiontextSize == 0) {
    +            result = ParsedSection(Intermediate);
    +        } else {
    +            for (int i = 0; i < sectiontextSize; ++i) {
    +                if (sectionTextRef.at(i).isSpace())
    +                    sectiontextSize = i; // which exits the loop
    +            }
    +
    +            const int absMax = absoluteMax(sectionIndex);
    +            QLocale loc;
    +            bool ok = true;
    +            int last = -1, used = -1;
    +
    +            Q_ASSERT(sectiontextSize <= sectionmaxsize);
    +            QStringRef digitsStr = sectionTextRef.left(sectiontextSize);
    +            for (int digits = sectiontextSize; digits >= 1; --digits) {
    +                digitsStr.truncate(digits);
    +                int tmp = (int)loc.toUInt(digitsStr, &ok);
    +                if (ok && sn.type == Hour12Section) {
    +                    if (tmp > 12) {
    +                        tmp = -1;
    +                        ok = false;
    +                    } else if (tmp == 12) {
    +                        tmp = 0;
    +                    }
    +                }
    +                if (ok && tmp <= absMax) {
    +                    QDTPDEBUG << sectionTextRef.left(digits) << tmp << digits;
    +                    last = tmp;
    +                    used = digits;
    +                    break;
    +                }
    +            }
    +
    +            if (last == -1) {
    +                QChar first(sectionTextRef.at(0));
    +                if (separators.at(sectionIndex + 1).startsWith(first))
    +                    result = ParsedSection(Intermediate, 0, used);
    +                else
    +                    QDTPDEBUG << "invalid because" << sectionTextRef << "can't become a uint" << last << ok;
    +            } else {
    +                const FieldInfo fi = fieldInfo(sectionIndex);
    +                const bool unfilled = used < sectionmaxsize;
    +                if (unfilled && fi & Fraction) { // typing 2 in a zzz field should be .200, not .002
    +                    for (int i = used; i < sectionmaxsize; ++i)
    +                        last *= 10;
    +                }
    +                // Even those *= 10s can't take last above absMax:
    +                Q_ASSERT(last <= absMax);
    +                const int absMin = absoluteMin(sectionIndex);
    +                if (last < absMin) {
    +                    if (unfilled)
    +                        result = ParsedSection(Intermediate, last, used);
    +                    else
    +                        QDTPDEBUG << "invalid because" << last << "is less than absoluteMin" << absMin;
    +                } else if (unfilled && (fi & (FixedWidth|Numeric)) == (FixedWidth|Numeric)) {
    +                    if (skipToNextSection(sectionIndex, currentValue, digitsStr)) {
    +                        const int missingZeroes = sectionmaxsize - digitsStr.size();
    +                        result = ParsedSection(Acceptable, last, sectionmaxsize, missingZeroes);
    +                        text->insert(offset, QString(missingZeroes, QLatin1Char('0')));
    +                        ++(const_cast(this)->sectionNodes[sectionIndex].zeroesAdded);
    +                    } else {
    +                        result = ParsedSection(Intermediate, last, used);;
    +                    }
    +                } else {
    +                    result = ParsedSection(Acceptable, last, used);
    +                }
    +            }
    +        }
    +        break; }
    +    default:
    +        qWarning("QDateTimeParser::parseSection Internal error (%ls %d)",
    +                 qUtf16Printable(sn.name()), sectionIndex);
    +        return result;
    +    }
    +    Q_ASSERT(result.state != Invalid || result.value == -1);
    +
    +    return result;
    +}
    +
    +/*!
    +  \internal
    +
    +  Returns a date consistent with the given data on parts specified by known,
    +  while staying as close to the given data as it can.  Returns an invalid date
    +  when on valid date is consistent with the data.
    +*/
    +
    +static QDate actualDate(QDateTimeParser::Sections known, int year, int year2digits,
    +                        int month, int day, int dayofweek)
    +{
    +    QDate actual(year, month, day);
    +    if (actual.isValid() && year % 100 == year2digits && actual.dayOfWeek() == dayofweek)
    +        return actual; // The obvious candidate is fine :-)
    +
    +    if (dayofweek < 1 || dayofweek > 7) // Invalid: ignore
    +        known &= ~QDateTimeParser::DayOfWeekSectionMask;
    +
    +    // Assuming year > 0 ...
    +    if (year % 100 != year2digits) {
    +        if (known & QDateTimeParser::YearSection2Digits) {
    +            // Over-ride year, even if specified:
    +            year += year2digits - year % 100;
    +            known &= ~QDateTimeParser::YearSection;
    +        } else {
    +            year2digits = year % 100;
    +        }
    +    }
    +    Q_ASSERT(year % 100 == year2digits);
    +
    +    if (month < 1) { // If invalid, clip to nearest valid and ignore in known.
    +        month = 1;
    +        known &= ~QDateTimeParser::MonthSection;
    +    } else if (month > 12) {
    +        month = 12;
    +        known &= ~QDateTimeParser::MonthSection;
    +    }
    +
    +    QDate first(year, month, 1);
    +    int last = known & QDateTimeParser::YearSection && known & QDateTimeParser::MonthSection
    +        ? first.daysInMonth() : 0;
    +    // If we also know day-of-week, tweak last to the last in the month that matches it:
    +    if (last && known & QDateTimeParser::DayOfWeekSectionMask) {
    +        int diff = (dayofweek - first.dayOfWeek() - last) % 7;
    +        Q_ASSERT(diff <= 0); // C++11 specifies (-ve) % (+ve) to be <= 0.
    +        last += diff;
    +    }
    +    if (day < 1) {
    +        if (known & QDateTimeParser::DayOfWeekSectionMask && last) {
    +            day = 1 + dayofweek - first.dayOfWeek();
    +            if (day < 1)
    +                day += 7;
    +        } else {
    +            day = 1;
    +        }
    +        known &= ~QDateTimeParser::DaySection;
    +    } else if (day > 31) {
    +        day = last;
    +        known &= ~QDateTimeParser::DaySection;
    +    } else if (last && day > last && (known & QDateTimeParser::DaySection) == 0) {
    +        day = last;
    +    }
    +
    +    actual = QDate(year, month, day);
    +    if (!actual.isValid() // We can't do better than we have, in this case
    +        || (known & QDateTimeParser::DaySection
    +            && known & QDateTimeParser::MonthSection
    +            && known & QDateTimeParser::YearSection) // ditto
    +        || actual.dayOfWeek() == dayofweek // Good enough, use it.
    +        || (known & QDateTimeParser::DayOfWeekSectionMask) == 0) { // No contradiction, use it.
    +        return actual;
    +    }
    +
    +    /*
    +      Now it gets trickier.
    +
    +      We have some inconsistency in our data; we've been told day of week, but
    +      it doesn't fit with our year, month and day.  At least one of these is
    +      unknown, though: so we can fix day of week by tweaking it.
    +    */
    +
    +    if ((known & QDateTimeParser::DaySection) == 0) {
    +        // Relatively easy to fix.
    +        day += dayofweek - actual.dayOfWeek();
    +        if (day < 1)
    +            day += 7;
    +        else if (day > actual.daysInMonth())
    +            day -= 7;
    +        actual = QDate(year, month, day);
    +        return actual;
    +    }
    +
    +    if ((known & QDateTimeParser::MonthSection) == 0) {
    +        /*
    +          Try possible month-offsets, m, preferring small; at least one (present
    +          month doesn't work) and at most 11 (max month, 12, minus min, 1); try
    +          in both directions, ignoring any offset that takes us out of range.
    +        */
    +        for (int m = 1; m < 12; m++) {
    +            if (m < month) {
    +                actual = QDate(year, month - m, day);
    +                if (actual.dayOfWeek() == dayofweek)
    +                    return actual;
    +            }
    +            if (m + month <= 12) {
    +                actual = QDate(year, month + m, day);
    +                if (actual.dayOfWeek() == dayofweek)
    +                    return actual;
    +            }
    +        }
    +        // Should only get here in corner cases; e.g. day == 31
    +        actual = QDate(year, month, day); // Restore from trial values.
    +    }
    +
    +    if ((known & QDateTimeParser::YearSection) == 0) {
    +        if (known & QDateTimeParser::YearSection2Digits) {
    +            /*
    +              Two-digit year and month are specified; choice of century can only
    +              fix this if diff is in one of {1, 2, 5} or {2, 4, 6}; but not if
    +              diff is in the other.  It's also only reasonable to consider
    +              adjacent century, e.g. if year thinks it's 2012 and two-digit year
    +              is '97, it makes sense to consider 1997.  If either adjacent
    +              century does work, the other won't.
    +            */
    +            actual = QDate(year + 100, month, day);
    +            if (actual.dayOfWeek() == dayofweek)
    +                return actual;
    +            actual = QDate(year - 100, month, day);
    +            if (actual.dayOfWeek() == dayofweek)
    +                return actual;
    +        } else {
    +            // Offset by 7 is usually enough, but rare cases may need more:
    +            for (int y = 1; y < 12; y++) {
    +                actual = QDate(year - y, month, day);
    +                if (actual.dayOfWeek() == dayofweek)
    +                    return actual;
    +                actual = QDate(year + y, month, day);
    +                if (actual.dayOfWeek() == dayofweek)
    +                    return actual;
    +            }
    +        }
    +        actual = QDate(year, month, day); // Restore from trial values.
    +    }
    +
    +    return actual; // It'll just have to do :-(
    +}
    +
    +/*!
    +  \internal
    +*/
    +
    +static QTime actualTime(QDateTimeParser::Sections known,
    +                        int hour, int hour12, int ampm,
    +                        int minute, int second, int msec)
    +{
    +    // If we have no conflict, or don't know enough to diagonose one, use this:
    +    QTime actual(hour, minute, second, msec);
    +    if (hour12 < 0 || hour12 > 12) { // ignore bogus value
    +        known &= ~QDateTimeParser::Hour12Section;
    +        hour12 = hour % 12;
    +    }
    +
    +    if (ampm == -1 || (known & QDateTimeParser::AmPmSection) == 0) {
    +        if ((known & QDateTimeParser::Hour12Section) == 0 || hour % 12 == hour12)
    +            return actual;
    +
    +        if ((known & QDateTimeParser::Hour24Section) == 0)
    +            hour = hour12 + (hour > 12 ? 12 : 0);
    +    } else {
    +        Q_ASSERT(ampm == 0 || ampm == 1);
    +        if (hour - hour12 == ampm * 12)
    +            return actual;
    +
    +        if ((known & QDateTimeParser::Hour24Section) == 0
    +            && known & QDateTimeParser::Hour12Section) {
    +            hour = hour12 + ampm * 12;
    +        }
    +    }
    +    actual = QTime(hour, minute, second, msec);
    +    return actual;
    +}
    +
    +/*!
    +  \internal
    +*/
    +QDateTimeParser::StateNode
    +QDateTimeParser::scanString(const QDateTime &defaultValue,
    +                            bool fixup, QString *input) const
    +{
    +    State state = Acceptable;
    +    bool conflicts = false;
    +    const int sectionNodesCount = sectionNodes.size();
    +    int padding = 0;
    +    int pos = 0;
    +    int year, month, day;
    +    const QDate defaultDate = defaultValue.date();
    +    const QTime defaultTime = defaultValue.time();
    +    defaultDate.getDate(&year, &month, &day);
    +    int year2digits = year % 100;
    +    int hour = defaultTime.hour();
    +    int hour12 = -1;
    +    int minute = defaultTime.minute();
    +    int second = defaultTime.second();
    +    int msec = defaultTime.msec();
    +    int dayofweek = defaultDate.dayOfWeek();
    +    Qt::TimeSpec tspec = defaultValue.timeSpec();
    +    int zoneOffset = 0; // In seconds; local - UTC
    +#if QT_CONFIG(timezone)
    +    QTimeZone timeZone;
    +#endif
    +    switch (tspec) {
    +    case Qt::OffsetFromUTC: // timeZone is ignored
    +        zoneOffset = defaultValue.offsetFromUtc();
    +        break;
    +#if QT_CONFIG(timezone)
    +    case Qt::TimeZone:
    +        timeZone = defaultValue.timeZone();
    +        if (timeZone.isValid())
    +            zoneOffset = timeZone.offsetFromUtc(defaultValue);
    +        // else: is there anything we can do about this ?
    +        break;
    +#endif
    +    default: // zoneOffset and timeZone are ignored
    +        break;
    +    }
    +
    +    int ampm = -1;
    +    Sections isSet = NoSection;
    +
    +    for (int index = 0; index < sectionNodesCount; ++index) {
    +        Q_ASSERT(state != Invalid);
    +        const QString &separator = separators.at(index);
    +        if (input->midRef(pos, separator.size()) != separator) {
    +            QDTPDEBUG << "invalid because" << input->midRef(pos, separator.size())
    +                      << "!=" << separator
    +                      << index << pos << currentSectionIndex;
    +            return StateNode();
    +        }
    +        pos += separator.size();
    +        sectionNodes[index].pos = pos;
    +        int *current = 0;
    +        const SectionNode sn = sectionNodes.at(index);
    +        ParsedSection sect;
    +
    +        {
    +            const QDate date = actualDate(isSet, year, year2digits, month, day, dayofweek);
    +            const QTime time = actualTime(isSet, hour, hour12, ampm, minute, second, msec);
    +            sect = parseSection(
    +#if QT_CONFIG(timezone)
    +                                tspec == Qt::TimeZone ? QDateTime(date, time, timeZone) :
    +#endif
    +                                QDateTime(date, time, tspec, zoneOffset),
    +                                index, pos, input);
    +        }
    +
    +        QDTPDEBUG << "sectionValue" << sn.name() << *input
    +                  << "pos" << pos << "used" << sect.used << stateName(sect.state);
    +
    +        padding += sect.zeroes;
    +        if (fixup && sect.state == Intermediate && sect.used < sn.count) {
    +            const FieldInfo fi = fieldInfo(index);
    +            if ((fi & (Numeric|FixedWidth)) == (Numeric|FixedWidth)) {
    +                const QString newText = QString::fromLatin1("%1").arg(sect.value, sn.count, 10, QLatin1Char('0'));
    +                input->replace(pos, sect.used, newText);
    +                sect.used = sn.count;
    +            }
    +        }
    +
    +        state = qMin(state, sect.state);
    +        // QDateTimeEdit can fix Intermediate and zeroes, but input needing that didn't match format:
    +        if (state == Invalid || (context == FromString && (state == Intermediate || sect.zeroes)))
    +            return StateNode();
    +
    +        switch (sn.type) {
    +        case TimeZoneSection:
    +            current = &zoneOffset;
    +            if (sect.used > 0) {
    +#if QT_CONFIG(timezone) // Synchronize with what findTimeZone() found:
    +                QStringRef zoneName = input->midRef(pos, sect.used);
    +                Q_ASSERT(!zoneName.isEmpty()); // sect.used > 0
    +                const QByteArray latinZone(zoneName == QLatin1String("Z")
    +                                           ? QByteArray("UTC") : zoneName.toLatin1());
    +                timeZone = QTimeZone(latinZone);
    +                tspec = timeZone.isValid()
    +                    ? (QTimeZone::isTimeZoneIdAvailable(latinZone)
    +                       ? Qt::TimeZone
    +                       : Qt::OffsetFromUTC)
    +                    : (Q_ASSERT(startsWithLocalTimeZone(zoneName)), Qt::LocalTime);
    +#else
    +                tspec = Qt::LocalTime;
    +#endif
    +            }
    +            break;
    +        case Hour24Section: current = &hour; break;
    +        case Hour12Section: current = &hour12; break;
    +        case MinuteSection: current = &minute; break;
    +        case SecondSection: current = &second; break;
    +        case MSecSection: current = &msec; break;
    +        case YearSection: current = &year; break;
    +        case YearSection2Digits: current = &year2digits; break;
    +        case MonthSection: current = &month; break;
    +        case DayOfWeekSectionShort:
    +        case DayOfWeekSectionLong: current = &dayofweek; break;
    +        case DaySection: current = &day; sect.value = qMax(1, sect.value); break;
    +        case AmPmSection: current = &m; break;
    +        default:
    +            qWarning("QDateTimeParser::parse Internal error (%ls)",
    +                     qUtf16Printable(sn.name()));
    +            break;
    +        }
    +
    +        if (sect.used > 0)
    +            pos += sect.used;
    +        QDTPDEBUG << index << sn.name() << "is set to"
    +                  << pos << "state is" << stateName(state);
    +
    +        if (!current) {
    +            qWarning("QDateTimeParser::parse Internal error 2");
    +            return StateNode();
    +        }
    +        if (isSet & sn.type && *current != sect.value) {
    +            QDTPDEBUG << "CONFLICT " << sn.name() << *current << sect.value;
    +            conflicts = true;
    +            if (index != currentSectionIndex || sect.state == Invalid) {
    +                continue;
    +            }
    +        }
    +        if (sect.state != Invalid)
    +            *current = sect.value;
    +
    +        // Record the present section:
    +        isSet |= sn.type;
    +    }
    +
    +    if (input->midRef(pos) != separators.last()) {
    +        QDTPDEBUG << "invalid because" << input->midRef(pos)
    +                  << "!=" << separators.last() << pos;
    +        return StateNode();
    +    }
    +
    +    if (parserType != QVariant::Time) {
    +        if (year % 100 != year2digits && (isSet & YearSection2Digits)) {
    +            if (!(isSet & YearSection)) {
    +                year = (year / 100) * 100;
    +                year += year2digits;
    +            } else {
    +                conflicts = true;
    +                const SectionNode &sn = sectionNode(currentSectionIndex);
    +                if (sn.type == YearSection2Digits) {
    +                    year = (year / 100) * 100;
    +                    year += year2digits;
    +                }
    +            }
    +        }
    +
    +        const QDate date(year, month, day);
    +        const int diff = dayofweek - date.dayOfWeek();
    +        if (diff != 0 && state == Acceptable && isSet & DayOfWeekSectionMask) {
    +            if (isSet & DaySection)
    +                conflicts = true;
    +            const SectionNode &sn = sectionNode(currentSectionIndex);
    +            if (sn.type & DayOfWeekSectionMask || currentSectionIndex == -1) {
    +                // dayofweek should be preferred
    +                day += diff;
    +                if (day <= 0) {
    +                    day += 7;
    +                } else if (day > date.daysInMonth()) {
    +                    day -= 7;
    +                }
    +                QDTPDEBUG << year << month << day << dayofweek
    +                          << diff << QDate(year, month, day).dayOfWeek();
    +            }
    +        }
    +
    +        bool needfixday = false;
    +        if (sectionType(currentSectionIndex) & DaySectionMask) {
    +            cachedDay = day;
    +        } else if (cachedDay > day) {
    +            day = cachedDay;
    +            needfixday = true;
    +        }
    +
    +        if (!QDate::isValid(year, month, day)) {
    +            if (day < 32) {
    +                cachedDay = day;
    +            }
    +            if (day > 28 && QDate::isValid(year, month, 1)) {
    +                needfixday = true;
    +            }
    +        }
    +        if (needfixday) {
    +            if (context == FromString) {
    +                return StateNode();
    +            }
    +            if (state == Acceptable && fixday) {
    +                day = qMin(day, QDate(year, month, 1).daysInMonth());
    +
    +                const QLocale loc = locale();
    +                for (int i=0; ireplace(sectionPos(sn), sectionSize(i), loc.toString(day));
    +                    } else if (sn.type & DayOfWeekSectionMask) {
    +                        const int dayOfWeek = QDate(year, month, day).dayOfWeek();
    +                        const QLocale::FormatType dayFormat =
    +                            (sn.type == DayOfWeekSectionShort
    +                             ? QLocale::ShortFormat : QLocale::LongFormat);
    +                        const QString dayName(loc.dayName(dayOfWeek, dayFormat));
    +                        input->replace(sectionPos(sn), sectionSize(i), dayName);
    +                    }
    +                }
    +            } else if (state > Intermediate) {
    +                state = Intermediate;
    +            }
    +        }
    +    }
    +
    +    if (parserType != QVariant::Date) {
    +        if (isSet & Hour12Section) {
    +            const bool hasHour = isSet & Hour24Section;
    +            if (ampm == -1) {
    +                if (hasHour) {
    +                    ampm = (hour < 12 ? 0 : 1);
    +                } else {
    +                    ampm = 0; // no way to tell if this is am or pm so I assume am
    +                }
    +            }
    +            hour12 = (ampm == 0 ? hour12 % 12 : (hour12 % 12) + 12);
    +            if (!hasHour) {
    +                hour = hour12;
    +            } else if (hour != hour12) {
    +                conflicts = true;
    +            }
    +        } else if (ampm != -1) {
    +            if (!(isSet & (Hour24Section))) {
    +                hour = (12 * ampm); // special case. Only ap section
    +            } else if ((ampm == 0) != (hour < 12)) {
    +                conflicts = true;
    +            }
    +        }
    +
    +    }
    +
    +    QDTPDEBUG << year << month << day << hour << minute << second << msec;
    +    Q_ASSERT(state != Invalid);
    +
    +    const QDate date(year, month, day);
    +    const QTime time(hour, minute, second, msec);
    +    const QDateTime when =
    +#if QT_CONFIG(timezone)
    +            tspec == Qt::TimeZone ? QDateTime(date, time, timeZone) :
    +#endif
    +            QDateTime(date, time, tspec, zoneOffset);
    +
    +    // If hour wasn't specified, check the default we're using exists on the
    +    // given date (which might be a spring-forward, skipping an hour).
    +    if (parserType == QVariant::DateTime && !(isSet & HourSectionMask) && !when.isValid()) {
    +        qint64 msecs = when.toMSecsSinceEpoch();
    +        // Fortunately, that gets a useful answer ...
    +        const QDateTime replace =
    +#if QT_CONFIG(timezone)
    +            tspec == Qt::TimeZone
    +            ? QDateTime::fromMSecsSinceEpoch(msecs, timeZone) :
    +#endif
    +            QDateTime::fromMSecsSinceEpoch(msecs, tspec, zoneOffset);
    +        const QTime tick = replace.time();
    +        if (replace.date() == date
    +            && (!(isSet & MinuteSection) || tick.minute() == minute)
    +            && (!(isSet & SecondSection) || tick.second() == second)
    +            && (!(isSet & MSecSection)   || tick.msec() == msec)) {
    +            return StateNode(replace, state, padding, conflicts);
    +        }
    +    }
    +
    +    return StateNode(when, state, padding, conflicts);
    +}
    +
    +/*!
    +  \internal
    +*/
    +
    +QDateTimeParser::StateNode
    +QDateTimeParser::parse(QString input, int position, const QDateTime &defaultValue, bool fixup) const
    +{
    +    const QDateTime minimum = getMinimum();
    +    const QDateTime maximum = getMaximum();
    +
    +    QDTPDEBUG << "parse" << input;
    +    StateNode scan = scanString(defaultValue, fixup, &input);
    +    QDTPDEBUGN("'%s' => '%s'(%s)", input.toLatin1().constData(),
    +               scan.value.toString(QLatin1String("yyyy/MM/dd hh:mm:ss.zzz")).toLatin1().constData(),
    +               stateName(scan.state).toLatin1().constData());
    +
    +    if (scan.value.isValid() && scan.state != Invalid) {
    +        if (context != FromString && scan.value < minimum) {
    +            const QLatin1Char space(' ');
    +            if (scan.value >= minimum)
    +                qWarning("QDateTimeParser::parse Internal error 3 (%ls %ls)",
    +                         qUtf16Printable(scan.value.toString()), qUtf16Printable(minimum.toString()));
    +
    +            bool done = false;
    +            scan.state = Invalid;
    +            const int sectionNodesCount = sectionNodes.size();
    +            for (int i=0; i= minimum && copy <= maximum) {
    +                                scan.state = Intermediate;
    +                                done = true;
    +                            }
    +                            break; }
    +                        }
    +                        Q_FALLTHROUGH();
    +                    case MonthSection:
    +                        if (sn.count >= 3) {
    +                            const int finalMonth = scan.value.date().month();
    +                            int tmp = finalMonth;
    +                            // I know the first possible month makes the date too early
    +                            while ((tmp = findMonth(t, tmp + 1, i)) != -1) {
    +                                const QDateTime copy(scan.value.addMonths(tmp - finalMonth));
    +                                if (copy >= minimum && copy <= maximum)
    +                                    break; // break out of while
    +                            }
    +                            if (tmp != -1) {
    +                                scan.state = Intermediate;
    +                                done = true;
    +                            }
    +                            break;
    +                        }
    +                        Q_FALLTHROUGH();
    +                    default: {
    +                        int toMin;
    +                        int toMax;
    +
    +                        if (sn.type & TimeSectionMask) {
    +                            if (scan.value.daysTo(minimum) != 0) {
    +                                break;
    +                            }
    +                            const QTime time = scan.value.time();
    +                            toMin = time.msecsTo(minimum.time());
    +                            if (scan.value.daysTo(maximum) > 0)
    +                                toMax = -1; // can't get to max
    +                            else
    +                                toMax = time.msecsTo(maximum.time());
    +                        } else {
    +                            toMin = scan.value.daysTo(minimum);
    +                            toMax = scan.value.daysTo(maximum);
    +                        }
    +                        const int maxChange = sn.maxChange();
    +                        if (toMin > maxChange) {
    +                            QDTPDEBUG << "invalid because toMin > maxChange" << toMin
    +                                      << maxChange << t << scan.value << minimum;
    +                            scan.state = Invalid;
    +                            done = true;
    +                            break;
    +                        } else if (toMax > maxChange) {
    +                            toMax = -1; // can't get to max
    +                        }
    +
    +                        const int min = getDigit(minimum, i);
    +                        if (min == -1) {
    +                            qWarning("QDateTimeParser::parse Internal error 4 (%ls)",
    +                                     qUtf16Printable(sn.name()));
    +                            scan.state = Invalid;
    +                            done = true;
    +                            break;
    +                        }
    +
    +                        int max = toMax != -1 ? getDigit(maximum, i) : absoluteMax(i, scan.value);
    +                        int pos = position + scan.padded - sn.pos;
    +                        if (pos < 0 || pos >= t.size())
    +                            pos = -1;
    +                        if (!potentialValue(t.simplified(), min, max, i, scan.value, pos)) {
    +                            QDTPDEBUG << "invalid because potentialValue(" << t.simplified() << min << max
    +                                      << sn.name() << "returned" << toMax << toMin << pos;
    +                            scan.state = Invalid;
    +                            done = true;
    +                            break;
    +                        }
    +                        scan.state = Intermediate;
    +                        done = true;
    +                        break; }
    +                    }
    +                }
    +            }
    +        } else {
    +            if (context == FromString) {
    +                // optimization
    +                Q_ASSERT(maximum.date().toJulianDay() == 5373484);
    +                if (scan.value.date().toJulianDay() > 5373484)
    +                    scan.state = Invalid;
    +            } else {
    +                if (scan.value > maximum)
    +                    scan.state = Invalid;
    +            }
    +
    +            QDTPDEBUG << "not checking intermediate because scanned value is" << scan.value << minimum << maximum;
    +        }
    +    }
    +    text = scan.input = input;
    +    // Set spec *after* all checking, so validity is a property of the string:
    +    scan.value = scan.value.toTimeSpec(spec);
    +    return scan;
    +}
    +
    +/*
    +  \internal
    +  \brief Returns the index in \a entries with the best prefix match to \a text
    +
    +  Scans \a entries looking for an entry overlapping \a text as much as possible
    +  (an exact match beats any prefix match; a match of the full entry as prefix of
    +  text beats any entry but one matching a longer prefix; otherwise, the match of
    +  longest prefix wins, earlier entries beating later on a draw).  Records the
    +  length of overlap in *used (if \a used is non-NULL) and the first entry that
    +  overlapped this much in *usedText (if \a usedText is non-NULL).
    + */
    +static int findTextEntry(const QString &text, const QVector &entries, QString *usedText, int *used)
    +{
    +    if (text.isEmpty())
    +        return -1;
    +
    +    int bestMatch = -1;
    +    int bestCount = 0;
    +    for (int n = 0; n < entries.size(); ++n)
    +    {
    +        const QString &name = entries.at(n);
    +
    +        const int limit = qMin(text.size(), name.size());
    +        int i = 0;
    +        while (i < limit && text.at(i) == name.at(i).toLower())
    +            ++i;
    +        // Full match beats an equal prefix match:
    +        if (i > bestCount || (i == bestCount && i == name.size())) {
    +            bestCount = i;
    +            bestMatch = n;
    +            if (i == name.size() && i == text.size())
    +                break; // Exact match, name == text, wins.
    +        }
    +    }
    +    if (usedText && bestMatch != -1)
    +        *usedText = entries.at(bestMatch);
    +    if (used)
    +        *used = bestCount;
    +
    +    return bestMatch;
    +}
    +
    +/*!
    +  \internal
    +  finds the first possible monthname that \a str1 can
    +  match. Starting from \a index; str should already by lowered
    +*/
    +
    +int QDateTimeParser::findMonth(const QString &str1, int startMonth, int sectionIndex,
    +                               QString *usedMonth, int *used) const
    +{
    +    const SectionNode &sn = sectionNode(sectionIndex);
    +    if (sn.type != MonthSection) {
    +        qWarning("QDateTimeParser::findMonth Internal error");
    +        return -1;
    +    }
    +
    +    QLocale::FormatType type = sn.count == 3 ? QLocale::ShortFormat : QLocale::LongFormat;
    +    QLocale l = locale();
    +    QVector monthNames;
    +    monthNames.reserve(13 - startMonth);
    +    for (int month = startMonth; month <= 12; ++month)
    +        monthNames.append(l.monthName(month, type));
    +
    +    const int index = findTextEntry(str1, monthNames, usedMonth, used);
    +    return index < 0 ? index : index + startMonth;
    +}
    +
    +int QDateTimeParser::findDay(const QString &str1, int startDay, int sectionIndex, QString *usedDay, int *used) const
    +{
    +    const SectionNode &sn = sectionNode(sectionIndex);
    +    if (!(sn.type & DaySectionMask)) {
    +        qWarning("QDateTimeParser::findDay Internal error");
    +        return -1;
    +    }
    +
    +    QLocale::FormatType type = sn.count == 4 ? QLocale::LongFormat : QLocale::ShortFormat;
    +    QLocale l = locale();
    +    QVector daysOfWeek;
    +    daysOfWeek.reserve(8 - startDay);
    +    for (int day = startDay; day <= 7; ++day)
    +        daysOfWeek.append(l.dayName(day, type));
    +
    +    const int index = findTextEntry(str1, daysOfWeek, usedDay, used);
    +    return index < 0 ? index : index + startDay;
    +}
    +
    +/*!
    +  \internal
    +
    +  Return's .value is zone's offset, zone time - UTC time, in seconds.
    +  See QTimeZonePrivate::isValidId() for the format of zone names.
    + */
    +QDateTimeParser::ParsedSection
    +QDateTimeParser::findTimeZone(QStringRef str, const QDateTime &when,
    +                              int maxVal, int minVal) const
    +{
    +#if QT_CONFIG(timezone)
    +    int index = startsWithLocalTimeZone(str);
    +    int offset;
    +
    +    if (index > 0) {
    +        // We won't actually use this, but we need a valid return:
    +        offset = QDateTime(when.date(), when.time(), Qt::LocalTime).offsetFromUtc();
    +    } else {
    +        int size = str.length();
    +        offset = std::numeric_limits::max(); // deliberately out of range
    +        Q_ASSERT(offset > QTimeZone::MaxUtcOffsetSecs); // cf. absoluteMax()
    +
    +        // Collect up plausibly-valid characters; let QTimeZone work out what's truly valid.
    +        while (index < size) {
    +            QChar here = str[index];
    +            if (here < 127
    +                && (here.isLetterOrNumber()
    +                    || here == '/' || here == '-'
    +                    || here == '_' || here == '.'
    +                    || here == '+' || here == ':'))
    +                index++;
    +            else
    +                break;
    +        }
    +
    +        while (index > 0) {
    +            str.truncate(index);
    +            if (str == QLatin1String("Z")) {
    +                offset = 0; // "Zulu" time - a.k.a. UTC
    +                break;
    +            }
    +            QTimeZone zone(str.toLatin1());
    +            if (zone.isValid()) {
    +                offset = zone.offsetFromUtc(when);
    +                break;
    +            }
    +            index--; // maybe we collected too much ...
    +        }
    +    }
    +
    +    if (index > 0 && maxVal >= offset && offset >= minVal)
    +        return ParsedSection(Acceptable, offset, index);
    +
    +#endif // timezone
    +    return ParsedSection();
    +}
    +
    +/*!
    +  \internal
    +
    +  Returns
    +  AM if str == tr("AM")
    +  PM if str == tr("PM")
    +  PossibleAM if str can become tr("AM")
    +  PossiblePM if str can become tr("PM")
    +  PossibleBoth if str can become tr("PM") and can become tr("AM")
    +  Neither if str can't become anything sensible
    +*/
    +QDateTimeParser::AmPmFinder QDateTimeParser::findAmPm(QString &str, int sectionIndex, int *used) const
    +{
    +    const SectionNode &s = sectionNode(sectionIndex);
    +    if (s.type != AmPmSection) {
    +        qWarning("QDateTimeParser::findAmPm Internal error");
    +        return Neither;
    +    }
    +    if (used)
    +        *used = str.size();
    +    if (QStringRef(&str).trimmed().isEmpty()) {
    +        return PossibleBoth;
    +    }
    +    const QLatin1Char space(' ');
    +    int size = sectionMaxSize(sectionIndex);
    +
    +    enum {
    +        amindex = 0,
    +        pmindex = 1
    +    };
    +    QString ampm[2];
    +    ampm[amindex] = getAmPmText(AmText, s.count == 1 ? UpperCase : LowerCase);
    +    ampm[pmindex] = getAmPmText(PmText, s.count == 1 ? UpperCase : LowerCase);
    +    for (int i=0; i<2; ++i)
    +        ampm[i].truncate(size);
    +
    +    QDTPDEBUG << "findAmPm" << str << ampm[0] << ampm[1];
    +
    +    if (str.indexOf(ampm[amindex], 0, Qt::CaseInsensitive) == 0) {
    +        str = ampm[amindex];
    +        return AM;
    +    } else if (str.indexOf(ampm[pmindex], 0, Qt::CaseInsensitive) == 0) {
    +        str = ampm[pmindex];
    +        return PM;
    +    } else if (context == FromString || (str.count(space) == 0 && str.size() >= size)) {
    +        return Neither;
    +    }
    +    size = qMin(size, str.size());
    +
    +    bool broken[2] = {false, false};
    +    for (int i=0; i= min && val <= max && str.size() == size) {
    +        return true;
    +    } else if (val > max) {
    +        return false;
    +    } else if (str.size() == size && val < min) {
    +        return false;
    +    }
    +
    +    const int len = size - str.size();
    +    for (int i=0; i= 0) {
    +                const QString tmp = str.left(insert) + QLatin1Char('0' + j) + str.mid(insert);
    +                if (potentialValue(tmp, min, max, index, currentValue, insert))
    +                    return true;
    +            }
    +        }
    +    }
    +
    +    return false;
    +}
    +
    +/*!
    +  \internal
    +*/
    +bool QDateTimeParser::skipToNextSection(int index, const QDateTime ¤t, const QStringRef &text) const
    +{
    +    Q_ASSERT(text.size() < sectionMaxSize(index));
    +    const SectionNode &node = sectionNode(index);
    +    int min = absoluteMin(index);
    +    int max = absoluteMax(index, current);
    +    // Time-zone field is only numeric if given as offset from UTC:
    +    if (node.type != TimeZoneSection || current.timeSpec() == Qt::OffsetFromUTC) {
    +        const QDateTime maximum = getMaximum();
    +        const QDateTime minimum = getMinimum();
    +        Q_ASSERT(current >= minimum && current <= maximum);
    +
    +        QDateTime tmp = current;
    +        if (!setDigit(tmp, index, min) || tmp < minimum)
    +            min = getDigit(minimum, index);
    +
    +        if (!setDigit(tmp, index, max) || tmp > maximum)
    +            max = getDigit(maximum, index);
    +    }
    +    int pos = cursorPosition() - node.pos;
    +    if (pos < 0 || pos >= text.size())
    +        pos = -1;
    +
    +    /*
    +      If the value potentially can become another valid entry we don't want to
    +      skip to the next. E.g. In a M field (month without leading 0) if you type
    +      1 we don't want to autoskip (there might be [012] following) but if you
    +      type 3 we do.
    +    */
    +    return !potentialValue(text, min, max, index, current, pos);
    +}
    +
    +/*!
    +  \internal
    +  For debugging. Returns the name of the section \a s.
    +*/
    +
    +QString QDateTimeParser::SectionNode::name(QDateTimeParser::Section s)
    +{
    +    switch (s) {
    +    case QDateTimeParser::AmPmSection: return QLatin1String("AmPmSection");
    +    case QDateTimeParser::DaySection: return QLatin1String("DaySection");
    +    case QDateTimeParser::DayOfWeekSectionShort: return QLatin1String("DayOfWeekSectionShort");
    +    case QDateTimeParser::DayOfWeekSectionLong: return QLatin1String("DayOfWeekSectionLong");
    +    case QDateTimeParser::Hour24Section: return QLatin1String("Hour24Section");
    +    case QDateTimeParser::Hour12Section: return QLatin1String("Hour12Section");
    +    case QDateTimeParser::MSecSection: return QLatin1String("MSecSection");
    +    case QDateTimeParser::MinuteSection: return QLatin1String("MinuteSection");
    +    case QDateTimeParser::MonthSection: return QLatin1String("MonthSection");
    +    case QDateTimeParser::SecondSection: return QLatin1String("SecondSection");
    +    case QDateTimeParser::TimeZoneSection: return QLatin1String("TimeZoneSection");
    +    case QDateTimeParser::YearSection: return QLatin1String("YearSection");
    +    case QDateTimeParser::YearSection2Digits: return QLatin1String("YearSection2Digits");
    +    case QDateTimeParser::NoSection: return QLatin1String("NoSection");
    +    case QDateTimeParser::FirstSection: return QLatin1String("FirstSection");
    +    case QDateTimeParser::LastSection: return QLatin1String("LastSection");
    +    default: return QLatin1String("Unknown section ") + QString::number(int(s));
    +    }
    +}
    +
    +/*!
    +  \internal
    +  For debugging. Returns the name of the state \a s.
    +*/
    +
    +QString QDateTimeParser::stateName(State s) const
    +{
    +    switch (s) {
    +    case Invalid: return QLatin1String("Invalid");
    +    case Intermediate: return QLatin1String("Intermediate");
    +    case Acceptable: return QLatin1String("Acceptable");
    +    default: return QLatin1String("Unknown state ") + QString::number(s);
    +    }
    +}
    +
    +#if QT_CONFIG(datestring)
    +bool QDateTimeParser::fromString(const QString &t, QDate *date, QTime *time) const
    +{
    +    QDateTime val(QDate(1900, 1, 1).startOfDay());
    +    const StateNode tmp = parse(t, -1, val, false);
    +    if (tmp.state != Acceptable || tmp.conflicts) {
    +        return false;
    +    }
    +    if (time) {
    +        const QTime t = tmp.value.time();
    +        if (!t.isValid()) {
    +            return false;
    +        }
    +        *time = t;
    +    }
    +
    +    if (date) {
    +        const QDate d = tmp.value.date();
    +        if (!d.isValid()) {
    +            return false;
    +        }
    +        *date = d;
    +    }
    +    return true;
    +}
    +#endif // datestring
    +
    +QDateTime QDateTimeParser::getMinimum() const
    +{
    +    // Cache the most common case
    +    if (spec == Qt::LocalTime) {
    +        static const QDateTime localTimeMin(QDATETIMEEDIT_DATE_MIN.startOfDay(Qt::LocalTime));
    +        return localTimeMin;
    +    }
    +    return QDateTime(QDATETIMEEDIT_DATE_MIN.startOfDay(spec));
    +}
    +
    +QDateTime QDateTimeParser::getMaximum() const
    +{
    +    // Cache the most common case
    +    if (spec == Qt::LocalTime) {
    +        static const QDateTime localTimeMax(QDATETIMEEDIT_DATE_MAX.endOfDay(Qt::LocalTime));
    +        return localTimeMax;
    +    }
    +    return QDateTime(QDATETIMEEDIT_DATE_MAX.endOfDay(spec));
    +}
    +
    +QString QDateTimeParser::getAmPmText(AmPm ap, Case cs) const
    +{
    +    const QLocale loc = locale();
    +    QString raw = ap == AmText ? loc.amText() : loc.pmText();
    +    return cs == UpperCase ? raw.toUpper() : raw.toLower();
    +}
    +
    +/*
    +  \internal
    +
    +  I give arg2 preference because arg1 is always a QDateTime.
    +*/
    +
    +bool operator==(const QDateTimeParser::SectionNode &s1, const QDateTimeParser::SectionNode &s2)
    +{
    +    return (s1.type == s2.type) && (s1.pos == s2.pos) && (s1.count == s2.count);
    +}
    +
    +QT_END_NAMESPACE
    diff --git a/src/corelib/time/qdatetimeparser_p.h b/src/corelib/time/qdatetimeparser_p.h
    new file mode 100644
    index 0000000000..d9e39f0795
    --- /dev/null
    +++ b/src/corelib/time/qdatetimeparser_p.h
    @@ -0,0 +1,310 @@
    +/****************************************************************************
    +**
    +** Copyright (C) 2016 The Qt Company Ltd.
    +** Contact: https://www.qt.io/licensing/
    +**
    +** This file is part of the QtCore module of the Qt Toolkit.
    +**
    +** $QT_BEGIN_LICENSE:LGPL$
    +** Commercial License Usage
    +** Licensees holding valid commercial Qt licenses may use this file in
    +** accordance with the commercial license agreement provided with the
    +** Software or, alternatively, in accordance with the terms contained in
    +** a written agreement between you and The Qt Company. For licensing terms
    +** and conditions see https://www.qt.io/terms-conditions. For further
    +** information use the contact form at https://www.qt.io/contact-us.
    +**
    +** GNU Lesser General Public License Usage
    +** Alternatively, this file may be used under the terms of the GNU Lesser
    +** General Public License version 3 as published by the Free Software
    +** Foundation and appearing in the file LICENSE.LGPL3 included in the
    +** packaging of this file. Please review the following information to
    +** ensure the GNU Lesser General Public License version 3 requirements
    +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
    +**
    +** GNU General Public License Usage
    +** Alternatively, this file may be used under the terms of the GNU
    +** General Public License version 2.0 or (at your option) the GNU General
    +** Public license version 3 or any later version approved by the KDE Free
    +** Qt Foundation. The licenses are as published by the Free Software
    +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
    +** included in the packaging of this file. Please review the following
    +** information to ensure the GNU General Public License requirements will
    +** be met: https://www.gnu.org/licenses/gpl-2.0.html and
    +** https://www.gnu.org/licenses/gpl-3.0.html.
    +**
    +** $QT_END_LICENSE$
    +**
    +****************************************************************************/
    +
    +#ifndef QDATETIMEPARSER_P_H
    +#define QDATETIMEPARSER_P_H
    +
    +//
    +//  W A R N I N G
    +//  -------------
    +//
    +// This file is not part of the Qt API.  It exists purely as an
    +// implementation detail.  This header file may change from version to
    +// version without notice, or even be removed.
    +//
    +// We mean it.
    +//
    +
    +#include 
    +#include "qplatformdefs.h"
    +#include "QtCore/qatomic.h"
    +#include "QtCore/qdatetime.h"
    +#include "QtCore/qstringlist.h"
    +#include "QtCore/qlocale.h"
    +#ifndef QT_BOOTSTRAPPED
    +# include "QtCore/qvariant.h"
    +#endif
    +#include "QtCore/qvector.h"
    +#include "QtCore/qcoreapplication.h"
    +
    +QT_REQUIRE_CONFIG(datetimeparser);
    +
    +#define QDATETIMEEDIT_TIME_MIN QTime(0, 0) // Prefer QDate::startOfDay()
    +#define QDATETIMEEDIT_TIME_MAX QTime(23, 59, 59, 999) // Prefer QDate::endOfDay()
    +#define QDATETIMEEDIT_DATE_MIN QDate(100, 1, 1)
    +#define QDATETIMEEDIT_COMPAT_DATE_MIN QDate(1752, 9, 14)
    +#define QDATETIMEEDIT_DATE_MAX QDate(9999, 12, 31)
    +#define QDATETIMEEDIT_DATE_INITIAL QDate(2000, 1, 1)
    +
    +QT_BEGIN_NAMESPACE
    +
    +class Q_CORE_EXPORT QDateTimeParser
    +{
    +    Q_DECLARE_TR_FUNCTIONS(QDateTimeParser)
    +public:
    +    enum Context {
    +        FromString,
    +        DateTimeEdit
    +    };
    +    QDateTimeParser(QVariant::Type t, Context ctx)
    +        : currentSectionIndex(-1), display(nullptr), cachedDay(-1), parserType(t),
    +        fixday(false), spec(Qt::LocalTime), context(ctx)
    +    {
    +        defaultLocale = QLocale::system();
    +        first.type = FirstSection;
    +        first.pos = -1;
    +        first.count = -1;
    +        first.zeroesAdded = 0;
    +        last.type = LastSection;
    +        last.pos = -1;
    +        last.count = -1;
    +        last.zeroesAdded = 0;
    +        none.type = NoSection;
    +        none.pos = -1;
    +        none.count = -1;
    +        none.zeroesAdded = 0;
    +    }
    +    virtual ~QDateTimeParser();
    +
    +    enum Section {
    +        NoSection     = 0x00000,
    +        AmPmSection   = 0x00001,
    +        MSecSection   = 0x00002,
    +        SecondSection = 0x00004,
    +        MinuteSection = 0x00008,
    +        Hour12Section   = 0x00010,
    +        Hour24Section   = 0x00020,
    +        TimeZoneSection = 0x00040,
    +        HourSectionMask = (Hour12Section | Hour24Section),
    +        TimeSectionMask = (MSecSection | SecondSection | MinuteSection |
    +                           HourSectionMask | AmPmSection | TimeZoneSection),
    +
    +        DaySection         = 0x00100,
    +        MonthSection       = 0x00200,
    +        YearSection        = 0x00400,
    +        YearSection2Digits = 0x00800,
    +        YearSectionMask = YearSection | YearSection2Digits,
    +        DayOfWeekSectionShort = 0x01000,
    +        DayOfWeekSectionLong  = 0x02000,
    +        DayOfWeekSectionMask = DayOfWeekSectionShort | DayOfWeekSectionLong,
    +        DaySectionMask = DaySection | DayOfWeekSectionMask,
    +        DateSectionMask = DaySectionMask | MonthSection | YearSectionMask,
    +
    +        Internal             = 0x10000,
    +        FirstSection         = 0x20000 | Internal,
    +        LastSection          = 0x40000 | Internal,
    +        CalendarPopupSection = 0x80000 | Internal,
    +
    +        NoSectionIndex = -1,
    +        FirstSectionIndex = -2,
    +        LastSectionIndex = -3,
    +        CalendarPopupIndex = -4
    +    }; // extending qdatetimeedit.h's equivalent
    +    Q_DECLARE_FLAGS(Sections, Section)
    +
    +    struct Q_CORE_EXPORT SectionNode {
    +        Section type;
    +        mutable int pos;
    +        int count;
    +        int zeroesAdded;
    +
    +        static QString name(Section s);
    +        QString name() const { return name(type); }
    +        QString format() const;
    +        int maxChange() const;
    +    };
    +
    +    enum State { // duplicated from QValidator
    +        Invalid,
    +        Intermediate,
    +        Acceptable
    +    };
    +
    +    struct StateNode {
    +        StateNode() : state(Invalid), padded(0), conflicts(false) {}
    +        StateNode(const QDateTime &val, State ok=Acceptable, int pad=0, bool bad=false)
    +            : value(val), state(ok), padded(pad), conflicts(bad) {}
    +        QString input;
    +        QDateTime value;
    +        State state;
    +        int padded;
    +        bool conflicts;
    +    };
    +
    +    enum AmPm {
    +        AmText,
    +        PmText
    +    };
    +
    +    enum Case {
    +        UpperCase,
    +        LowerCase
    +    };
    +
    +#if QT_CONFIG(datestring)
    +    StateNode parse(QString input, int position, const QDateTime &defaultValue, bool fixup) const;
    +    bool fromString(const QString &text, QDate *date, QTime *time) const;
    +#endif
    +    bool parseFormat(const QString &format);
    +
    +    enum FieldInfoFlag {
    +        Numeric = 0x01,
    +        FixedWidth = 0x02,
    +        AllowPartial = 0x04,
    +        Fraction = 0x08
    +    };
    +    Q_DECLARE_FLAGS(FieldInfo, FieldInfoFlag)
    +
    +    FieldInfo fieldInfo(int index) const;
    +
    +    void setDefaultLocale(const QLocale &loc) { defaultLocale = loc; }
    +    virtual QString displayText() const { return text; }
    +
    +private:
    +    int sectionMaxSize(Section s, int count) const;
    +    QString sectionText(const QString &text, int sectionIndex, int index) const;
    +#if QT_CONFIG(datestring)
    +    StateNode scanString(const QDateTime &defaultValue,
    +                         bool fixup, QString *input) const;
    +    struct ParsedSection {
    +        int value;
    +        int used;
    +        int zeroes;
    +        State state;
    +        Q_DECL_CONSTEXPR ParsedSection(State ok = Invalid,
    +                                       int val = 0, int read = 0, int zs = 0)
    +            : value(ok == Invalid ? -1 : val), used(read), zeroes(zs), state(ok)
    +            {}
    +    };
    +    ParsedSection parseSection(const QDateTime ¤tValue, int sectionIndex,
    +                               int offset, QString *text) const;
    +    int findMonth(const QString &str1, int monthstart, int sectionIndex,
    +                  QString *monthName = nullptr, int *used = nullptr) const;
    +    int findDay(const QString &str1, int intDaystart, int sectionIndex,
    +                QString *dayName = nullptr, int *used = nullptr) const;
    +    ParsedSection findTimeZone(QStringRef str, const QDateTime &when,
    +                               int maxVal, int minVal) const;
    +#if QT_CONFIG(timezone)
    +    // Implemented in qdatetime.cpp:
    +    static int startsWithLocalTimeZone(const QStringRef name);
    +#endif
    +
    +    enum AmPmFinder {
    +        Neither = -1,
    +        AM = 0,
    +        PM = 1,
    +        PossibleAM = 2,
    +        PossiblePM = 3,
    +        PossibleBoth = 4
    +    };
    +    AmPmFinder findAmPm(QString &str, int index, int *used = nullptr) const;
    +#endif // datestring
    +
    +    bool potentialValue(const QStringRef &str, int min, int max, int index,
    +                        const QDateTime ¤tValue, int insert) const;
    +    bool potentialValue(const QString &str, int min, int max, int index,
    +                        const QDateTime ¤tValue, int insert) const
    +    {
    +        return potentialValue(QStringRef(&str), min, max, index, currentValue, insert);
    +    }
    +
    +protected: // for the benefit of QDateTimeEditPrivate
    +    int sectionSize(int index) const;
    +    int sectionMaxSize(int index) const;
    +    int sectionPos(int index) const;
    +    int sectionPos(const SectionNode &sn) const;
    +
    +    const SectionNode §ionNode(int index) const;
    +    Section sectionType(int index) const;
    +    QString sectionText(int sectionIndex) const;
    +    int getDigit(const QDateTime &dt, int index) const;
    +    bool setDigit(QDateTime &t, int index, int newval) const;
    +
    +    int absoluteMax(int index, const QDateTime &value = QDateTime()) const;
    +    int absoluteMin(int index) const;
    +
    +    bool skipToNextSection(int section, const QDateTime ¤t, const QStringRef §ionText) const;
    +    bool skipToNextSection(int section, const QDateTime ¤t, const QString §ionText) const
    +    {
    +        return skipToNextSection(section, current, QStringRef(§ionText));
    +    }
    +    QString stateName(State s) const;
    +    virtual QDateTime getMinimum() const;
    +    virtual QDateTime getMaximum() const;
    +    virtual int cursorPosition() const { return -1; }
    +    virtual QString getAmPmText(AmPm ap, Case cs) const;
    +    virtual QLocale locale() const { return defaultLocale; }
    +
    +    mutable int currentSectionIndex;
    +    Sections display;
    +    /*
    +        This stores the most recently selected day.
    +        It is useful when considering the following scenario:
    +
    +        1. Date is: 31/01/2000
    +        2. User increments month: 29/02/2000
    +        3. User increments month: 31/03/2000
    +
    +        At step 1, cachedDay stores 31. At step 2, the 31 is invalid for February, so the cachedDay is not updated.
    +        At step 3, the month is changed to March, for which 31 is a valid day. Since 29 < 31, the day is set to cachedDay.
    +        This is good for when users have selected their desired day and are scrolling up or down in the month or year section
    +        and do not want smaller months (or non-leap years) to alter the day that they chose.
    +    */
    +    mutable int cachedDay;
    +    mutable QString text;
    +    QVector sectionNodes;
    +    SectionNode first, last, none, popup;
    +    QStringList separators;
    +    QString displayFormat;
    +    QLocale defaultLocale;
    +    QVariant::Type parserType;
    +    bool fixday;
    +    Qt::TimeSpec spec; // spec if used by QDateTimeEdit
    +    Context context;
    +};
    +Q_DECLARE_TYPEINFO(QDateTimeParser::SectionNode, Q_PRIMITIVE_TYPE);
    +
    +Q_CORE_EXPORT bool operator==(const QDateTimeParser::SectionNode &s1, const QDateTimeParser::SectionNode &s2);
    +
    +Q_DECLARE_OPERATORS_FOR_FLAGS(QDateTimeParser::Sections)
    +Q_DECLARE_OPERATORS_FOR_FLAGS(QDateTimeParser::FieldInfo)
    +
    +QT_END_NAMESPACE
    +
    +#endif // QDATETIME_P_H
    diff --git a/src/corelib/time/qtimezone.cpp b/src/corelib/time/qtimezone.cpp
    new file mode 100644
    index 0000000000..ef323de14a
    --- /dev/null
    +++ b/src/corelib/time/qtimezone.cpp
    @@ -0,0 +1,997 @@
    +/****************************************************************************
    +**
    +** Copyright (C) 2013 John Layt 
    +** Contact: https://www.qt.io/licensing/
    +**
    +** This file is part of the QtCore module of the Qt Toolkit.
    +**
    +** $QT_BEGIN_LICENSE:LGPL$
    +** Commercial License Usage
    +** Licensees holding valid commercial Qt licenses may use this file in
    +** accordance with the commercial license agreement provided with the
    +** Software or, alternatively, in accordance with the terms contained in
    +** a written agreement between you and The Qt Company. For licensing terms
    +** and conditions see https://www.qt.io/terms-conditions. For further
    +** information use the contact form at https://www.qt.io/contact-us.
    +**
    +** GNU Lesser General Public License Usage
    +** Alternatively, this file may be used under the terms of the GNU Lesser
    +** General Public License version 3 as published by the Free Software
    +** Foundation and appearing in the file LICENSE.LGPL3 included in the
    +** packaging of this file. Please review the following information to
    +** ensure the GNU Lesser General Public License version 3 requirements
    +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
    +**
    +** GNU General Public License Usage
    +** Alternatively, this file may be used under the terms of the GNU
    +** General Public License version 2.0 or (at your option) the GNU General
    +** Public license version 3 or any later version approved by the KDE Free
    +** Qt Foundation. The licenses are as published by the Free Software
    +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
    +** included in the packaging of this file. Please review the following
    +** information to ensure the GNU General Public License requirements will
    +** be met: https://www.gnu.org/licenses/gpl-2.0.html and
    +** https://www.gnu.org/licenses/gpl-3.0.html.
    +**
    +** $QT_END_LICENSE$
    +**
    +****************************************************************************/
    +
    +
    +#include "qtimezone.h"
    +#include "qtimezoneprivate_p.h"
    +
    +#include 
    +#include 
    +
    +#include 
    +
    +#include 
    +
    +QT_BEGIN_NAMESPACE
    +
    +// Create default time zone using appropriate backend
    +static QTimeZonePrivate *newBackendTimeZone()
    +{
    +#ifdef QT_NO_SYSTEMLOCALE
    +#if QT_CONFIG(icu)
    +    return new QIcuTimeZonePrivate();
    +#else
    +    return new QUtcTimeZonePrivate();
    +#endif
    +#else
    +#if defined Q_OS_MAC
    +    return new QMacTimeZonePrivate();
    +#elif defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
    +    return new QAndroidTimeZonePrivate();
    +#elif defined(Q_OS_UNIX) || defined(Q_OS_ANDROID_EMBEDDED)
    +    return new QTzTimeZonePrivate();
    +#elif QT_CONFIG(icu)
    +    return new QIcuTimeZonePrivate();
    +#elif defined Q_OS_WIN
    +    return new QWinTimeZonePrivate();
    +#else
    +    return new QUtcTimeZonePrivate();
    +#endif // System Locales
    +#endif // QT_NO_SYSTEMLOCALE
    +}
    +
    +// Create named time zone using appropriate backend
    +static QTimeZonePrivate *newBackendTimeZone(const QByteArray &ianaId)
    +{
    +#ifdef QT_NO_SYSTEMLOCALE
    +#if QT_CONFIG(icu)
    +    return new QIcuTimeZonePrivate(ianaId);
    +#else
    +    return new QUtcTimeZonePrivate(ianaId);
    +#endif
    +#else
    +#if defined Q_OS_MAC
    +    return new QMacTimeZonePrivate(ianaId);
    +#elif defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
    +    return new QAndroidTimeZonePrivate(ianaId);
    +#elif defined(Q_OS_UNIX) || defined(Q_OS_ANDROID_EMBEDDED)
    +    return new QTzTimeZonePrivate(ianaId);
    +#elif QT_CONFIG(icu)
    +    return new QIcuTimeZonePrivate(ianaId);
    +#elif defined Q_OS_WIN
    +    return new QWinTimeZonePrivate(ianaId);
    +#else
    +    return new QUtcTimeZonePrivate(ianaId);
    +#endif // System Locales
    +#endif // QT_NO_SYSTEMLOCALE
    +}
    +
    +class QTimeZoneSingleton
    +{
    +public:
    +    QTimeZoneSingleton() : backend(newBackendTimeZone()) {}
    +
    +    // The backend_tz is the tz to use in static methods such as availableTimeZoneIds() and
    +    // isTimeZoneIdAvailable() and to create named IANA time zones.  This is usually the host
    +    // system, but may be different if the host resources are insufficient or if
    +    // QT_NO_SYSTEMLOCALE is set.  A simple UTC backend is used if no alternative is available.
    +    QSharedDataPointer backend;
    +};
    +
    +Q_GLOBAL_STATIC(QTimeZoneSingleton, global_tz);
    +
    +/*!
    +    \class QTimeZone
    +    \inmodule QtCore
    +    \since 5.2
    +
    +    \brief The QTimeZone class converts between UTC and local time in a specific
    +           time zone.
    +
    +    \threadsafe
    +
    +    This class provides a stateless calculator for time zone conversions
    +    between UTC and the local time in a specific time zone.  By default it uses
    +    the host system time zone data to perform these conversions.
    +
    +    This class is primarily designed for use in QDateTime; most applications
    +    will not need to access this class directly and should instead use
    +    QDateTime with a Qt::TimeSpec of Qt::TimeZone.
    +
    +    \note For consistency with QDateTime, QTimeZone does not account for leap
    +    seconds.
    +
    +    \section1 Remarks
    +
    +    \section2 IANA Time Zone IDs
    +
    +    QTimeZone uses the IANA time zone IDs as defined in the IANA Time Zone
    +    Database (http://www.iana.org/time-zones). This is to ensure a standard ID
    +    across all supported platforms.  Most platforms support the IANA IDs
    +    and the IANA Database natively, but for Windows a mapping is required to
    +    the native IDs.  See below for more details.
    +
    +    The IANA IDs can and do change on a regular basis, and can vary depending
    +    on how recently the host system data was updated.  As such you cannot rely
    +    on any given ID existing on any host system.  You must use
    +    availableTimeZoneIds() to determine what IANA IDs are available.
    +
    +    The IANA IDs and database are also know as the Olson IDs and database,
    +    named after their creator.
    +
    +    \section2 UTC Offset Time Zones
    +
    +    A default UTC time zone backend is provided which is always guaranteed to
    +    be available.  This provides a set of generic Offset From UTC time zones
    +    in the range UTC-14:00 to UTC+14:00.  These time zones can be created
    +    using either the standard ISO format names "UTC+00:00" as listed by
    +    availableTimeZoneIds(), or using the number of offset seconds.
    +
    +    \section2 Windows Time Zones
    +
    +    Windows native time zone support is severely limited compared to the
    +    standard IANA TZ Database.  Windows time zones cover larger geographic
    +    areas and are thus less accurate in their conversions.  They also do not
    +    support as much historic conversion data and so may only be accurate for
    +    the current year.
    +
    +    QTimeZone uses a conversion table derived form the Unicode CLDR data to map
    +    between IANA IDs and Windows IDs.  Depending on your version of Windows
    +    and Qt, this table may not be able to provide a valid conversion, in which
    +    "UTC" will be returned.
    +
    +    QTimeZone provides a public API to use this conversion table.  The Windows ID
    +    used is the Windows Registry Key for the time zone which is also the MS
    +    Exchange EWS ID as well, but is different to the Time Zone Name (TZID) and
    +    COD code used by MS Exchange in versions before 2007.
    +
    +    \section2 System Time Zone
    +
    +    QTimeZone does not support any concept of a system or default time zone.
    +    If you require a QDateTime that uses the current system time zone at any
    +    given moment then you should use a Qt::TimeSpec of Qt::LocalTime.
    +
    +    The method systemTimeZoneId() returns the current system IANA time zone
    +    ID which on Unix-like systems will always be correct.  On Windows this ID is
    +    translated from the Windows system ID using an internal translation
    +    table and the user's selected country.  As a consequence there is a small
    +    chance any Windows install may have IDs not known by Qt, in which case
    +    "UTC" will be returned.
    +
    +    Creating a new QTimeZone instance using the system time zone ID will only
    +    produce a fixed named copy of the time zone, it will not change if the
    +    system time zone changes.
    +
    +    \section2 Time Zone Offsets
    +
    +    The difference between UTC and the local time in a time zone is expressed
    +    as an offset in seconds from UTC, i.e. the number of seconds to add to UTC
    +    to obtain the local time.  The total offset is comprised of two component
    +    parts, the standard time offset and the daylight-saving time offset.  The
    +    standard time offset is the number of seconds to add to UTC to obtain
    +    standard time in the time zone.  The daylight-saving time offset is the
    +    number of seconds to add to the standard time offset to obtain
    +    daylight-saving time (abbreviated DST and sometimes called "daylight time"
    +    or "summer time") in the time zone.
    +
    +    Note that the standard and DST offsets for a time zone may change over time
    +    as countries have changed DST laws or even their standard time offset.
    +
    +    \section2 License
    +
    +    This class includes data obtained from the CLDR data files under the terms
    +    of the Unicode Data Files and Software License. See
    +    \l{Unicode Common Locale Data Repository (CLDR)} for details.
    +
    +    \sa QDateTime
    +*/
    +
    +/*!
    +  \enum QTimeZone::anonymous
    +
    +  Sane UTC offsets range from -14 to +14 hours.
    +  No known zone > 12 hrs West of Greenwich (Baker Island, USA).
    +  No known zone > 14 hrs East of Greenwich (Kiritimati, Christmas Island, Kiribati).
    +
    +  \value MinUtcOffsetSecs
    +          -14 * 3600,
    +
    +  \value MaxUtcOffsetSecs
    +          +14 * 3600
    +*/
    +
    +/*!
    +    \enum QTimeZone::TimeType
    +
    +    The type of time zone time, for example when requesting the name.  In time
    +    zones that do not apply DST, all three values may return the same result.
    +
    +    \value StandardTime
    +           The standard time in a time zone, i.e. when Daylight-Saving is not
    +           in effect.
    +           For example when formatting a display name this will show something
    +           like "Pacific Standard Time".
    +    \value DaylightTime
    +           A time when Daylight-Saving is in effect.
    +           For example when formatting a display name this will show something
    +           like "Pacific daylight-saving time".
    +    \value GenericTime
    +           A time which is not specifically Standard or Daylight-Saving time,
    +           either an unknown time or a neutral form.
    +           For example when formatting a display name this will show something
    +           like "Pacific Time".
    +*/
    +
    +/*!
    +    \enum QTimeZone::NameType
    +
    +    The type of time zone name.
    +
    +    \value DefaultName
    +           The default form of the time zone name, e.g. LongName, ShortName or OffsetName
    +    \value LongName
    +           The long form of the time zone name, e.g. "Central European Time"
    +    \value ShortName
    +           The short form of the time zone name, usually an abbreviation, e.g. "CET"
    +    \value OffsetName
    +           The standard ISO offset form of the time zone name, e.g. "UTC+01:00"
    +*/
    +
    +/*!
    +    \class QTimeZone::OffsetData
    +    \inmodule QtCore
    +
    +    The time zone offset data for a given moment in time, i.e. the time zone
    +    offsets and abbreviation to use at that moment in time.
    +
    +    \list
    +    \li OffsetData::atUtc  The datetime of the offset data in UTC time.
    +    \li OffsetData::offsetFromUtc  The total offset from UTC in effect at the datetime.
    +    \li OffsetData::standardTimeOffset  The standard time offset component of the total offset.
    +    \li OffsetData::daylightTimeOffset  The DST offset component of the total offset.
    +    \li OffsetData::abbreviation  The abbreviation in effect at the datetime.
    +    \endlist
    +
    +    For example, for time zone "Europe/Berlin" the OffsetDate in standard and DST might be:
    +
    +    \list
    +    \li atUtc = QDateTime(QDate(2013, 1, 1), QTime(0, 0, 0), Qt::UTC)
    +    \li offsetFromUtc = 3600
    +    \li standardTimeOffset = 3600
    +    \li daylightTimeOffset = 0
    +    \li abbreviation = "CET"
    +    \endlist
    +
    +    \list
    +    \li atUtc = QDateTime(QDate(2013, 6, 1), QTime(0, 0, 0), Qt::UTC)
    +    \li offsetFromUtc = 7200
    +    \li standardTimeOffset = 3600
    +    \li daylightTimeOffset = 3600
    +    \li abbreviation = "CEST"
    +    \endlist
    +*/
    +
    +/*!
    +    \typedef QTimeZone::OffsetDataList
    +
    +    Synonym for QVector.
    +*/
    +
    +/*!
    +    Create a null/invalid time zone instance.
    +*/
    +
    +QTimeZone::QTimeZone() noexcept
    +    : d(0)
    +{
    +}
    +
    +/*!
    +    Creates an instance of the requested time zone \a ianaId.
    +
    +    The ID must be one of the available system IDs otherwise an invalid
    +    time zone will be returned.
    +
    +    \sa availableTimeZoneIds()
    +*/
    +
    +QTimeZone::QTimeZone(const QByteArray &ianaId)
    +{
    +    // Try and see if it's a valid UTC offset ID, just as quick to try create as look-up
    +    d = new QUtcTimeZonePrivate(ianaId);
    +    // If not a valid UTC offset ID then try create it with the system backend
    +    // Relies on backend not creating valid tz with invalid name
    +    if (!d->isValid())
    +        d = newBackendTimeZone(ianaId);
    +}
    +
    +/*!
    +    Creates an instance of a time zone with the requested Offset from UTC of
    +    \a offsetSeconds.
    +
    +    The \a offsetSeconds from UTC must be in the range -14 hours to +14 hours
    +    otherwise an invalid time zone will be returned.
    +*/
    +
    +QTimeZone::QTimeZone(int offsetSeconds)
    +    : d((offsetSeconds >= MinUtcOffsetSecs && offsetSeconds <= MaxUtcOffsetSecs)
    +        ? new QUtcTimeZonePrivate(offsetSeconds) : nullptr)
    +{
    +}
    +
    +/*!
    +    Creates a custom time zone with an ID of \a ianaId and an offset from UTC
    +    of \a offsetSeconds.  The \a name will be the name used by displayName()
    +    for the LongName, the \a abbreviation will be used by displayName() for the
    +    ShortName and by abbreviation(), and the optional \a country will be used
    +    by country().  The \a comment is an optional note that may be displayed in
    +    a GUI to assist users in selecting a time zone.
    +
    +    The \a ianaId must not be one of the available system IDs returned by
    +    availableTimeZoneIds().  The \a offsetSeconds from UTC must be in the range
    +    -14 hours to +14 hours.
    +
    +    If the custom time zone does not have a specific country then set it to the
    +    default value of QLocale::AnyCountry.
    +*/
    +
    +QTimeZone::QTimeZone(const QByteArray &ianaId, int offsetSeconds, const QString &name,
    +                     const QString &abbreviation, QLocale::Country country, const QString &comment)
    +    : d()
    +{
    +    if (!isTimeZoneIdAvailable(ianaId))
    +        d = new QUtcTimeZonePrivate(ianaId, offsetSeconds, name, abbreviation, country, comment);
    +}
    +
    +/*!
    +    \internal
    +
    +    Private. Create time zone with given private backend
    +*/
    +
    +QTimeZone::QTimeZone(QTimeZonePrivate &dd)
    +    : d(&dd)
    +{
    +}
    +
    +/*!
    +    Copy constructor, copy \a other to this.
    +*/
    +
    +QTimeZone::QTimeZone(const QTimeZone &other)
    +    : d(other.d)
    +{
    +}
    +
    +/*!
    +    Destroys the time zone.
    +*/
    +
    +QTimeZone::~QTimeZone()
    +{
    +}
    +
    +/*!
    +    \fn QTimeZone::swap(QTimeZone &other)
    +
    +    Swaps this time zone instance with \a other. This function is very
    +    fast and never fails.
    +*/
    +
    +/*!
    +    Assignment operator, assign \a other to this.
    +*/
    +
    +QTimeZone &QTimeZone::operator=(const QTimeZone &other)
    +{
    +    d = other.d;
    +    return *this;
    +}
    +
    +/*
    +    \fn void QTimeZone::swap(QTimeZone &other)
    +
    +    Swaps this timezone with \a other. This function is very fast and
    +    never fails.
    +*/
    +
    +/*!
    +    \fn QTimeZone &QTimeZone::operator=(QTimeZone &&other)
    +
    +    Move-assigns \a other to this QTimeZone instance, transferring the
    +    ownership of the managed pointer to this instance.
    +*/
    +
    +/*!
    +    Returns \c true if this time zone is equal to the \a other time zone.
    +*/
    +
    +bool QTimeZone::operator==(const QTimeZone &other) const
    +{
    +    if (d && other.d)
    +        return (*d == *other.d);
    +    else
    +        return (d == other.d);
    +}
    +
    +/*!
    +    Returns \c true if this time zone is not equal to the \a other time zone.
    +*/
    +
    +bool QTimeZone::operator!=(const QTimeZone &other) const
    +{
    +    if (d && other.d)
    +        return (*d != *other.d);
    +    else
    +        return (d != other.d);
    +}
    +
    +/*!
    +    Returns \c true if this time zone is valid.
    +*/
    +
    +bool QTimeZone::isValid() const
    +{
    +    if (d)
    +        return d->isValid();
    +    else
    +        return false;
    +}
    +
    +/*!
    +    Returns the IANA ID for the time zone.
    +
    +    IANA IDs are used on all platforms.  On Windows these are translated
    +    from the Windows ID into the closest IANA ID for the time zone and country.
    +*/
    +
    +QByteArray QTimeZone::id() const
    +{
    +    if (d)
    +        return d->id();
    +    else
    +        return QByteArray();
    +}
    +
    +/*!
    +    Returns the country for the time zone.
    +*/
    +
    +QLocale::Country QTimeZone::country() const
    +{
    +    if (isValid())
    +        return d->country();
    +    else
    +        return QLocale::AnyCountry;
    +}
    +
    +/*!
    +    Returns any comment for the time zone.
    +
    +    A comment may be provided by the host platform to assist users in
    +    choosing the correct time zone.  Depending on the platform this may not
    +    be localized.
    +*/
    +
    +QString QTimeZone::comment() const
    +{
    +    if (isValid())
    +        return d->comment();
    +    else
    +        return QString();
    +}
    +
    +/*!
    +    Returns the localized time zone display name at the given \a atDateTime
    +    for the given \a nameType in the given \a locale.  The \a nameType and
    +    \a locale requested may not be supported on all platforms, in which case
    +    the best available option will be returned.
    +
    +    If the \a locale is not provided then the application default locale will
    +    be used.
    +
    +    The display name may change depending on DST or historical events.
    +
    +    \sa abbreviation()
    +*/
    +
    +QString QTimeZone::displayName(const QDateTime &atDateTime, NameType nameType,
    +                               const QLocale &locale) const
    +{
    +    if (isValid())
    +        return d->displayName(atDateTime.toMSecsSinceEpoch(), nameType, locale);
    +    else
    +        return QString();
    +}
    +
    +/*!
    +    Returns the localized time zone display name for the given \a timeType
    +    and \a nameType in the given \a locale. The \a nameType and \a locale
    +    requested may not be supported on all platforms, in which case the best
    +    available option will be returned.
    +
    +    If the \a locale is not provided then the application default locale will
    +    be used.
    +
    +    Where the time zone display names have changed over time then the most
    +    recent names will be used.
    +
    +    \sa abbreviation()
    +*/
    +
    +QString QTimeZone::displayName(TimeType timeType, NameType nameType,
    +                               const QLocale &locale) const
    +{
    +    if (isValid())
    +        return d->displayName(timeType, nameType, locale);
    +    else
    +        return QString();
    +}
    +
    +/*!
    +    Returns the time zone abbreviation at the given \a atDateTime.  The
    +    abbreviation may change depending on DST or even historical events.
    +
    +    Note that the abbreviation is not guaranteed to be unique to this time zone
    +    and should not be used in place of the ID or display name.
    +
    +    \sa displayName()
    +*/
    +
    +QString QTimeZone::abbreviation(const QDateTime &atDateTime) const
    +{
    +    if (isValid())
    +        return d->abbreviation(atDateTime.toMSecsSinceEpoch());
    +    else
    +        return QString();
    +}
    +
    +/*!
    +    Returns the total effective offset at the given \a atDateTime, i.e. the
    +    number of seconds to add to UTC to obtain the local time.  This includes
    +    any DST offset that may be in effect, i.e. it is the sum of
    +    standardTimeOffset() and daylightTimeOffset() for the given datetime.
    +
    +    For example, for the time zone "Europe/Berlin" the standard time offset is
    +    +3600 seconds and the DST offset is +3600 seconds.  During standard time
    +    offsetFromUtc() will return +3600 (UTC+01:00), and during DST it will
    +    return +7200 (UTC+02:00).
    +
    +    \sa standardTimeOffset(), daylightTimeOffset()
    +*/
    +
    +int QTimeZone::offsetFromUtc(const QDateTime &atDateTime) const
    +{
    +    if (isValid())
    +        return d->offsetFromUtc(atDateTime.toMSecsSinceEpoch());
    +    else
    +        return 0;
    +}
    +
    +/*!
    +    Returns the standard time offset at the given \a atDateTime, i.e. the
    +    number of seconds to add to UTC to obtain the local Standard Time.  This
    +    excludes any DST offset that may be in effect.
    +
    +    For example, for the time zone "Europe/Berlin" the standard time offset is
    +    +3600 seconds.  During both standard and DST offsetFromUtc() will return
    +    +3600 (UTC+01:00).
    +
    +    \sa offsetFromUtc(), daylightTimeOffset()
    +*/
    +
    +int QTimeZone::standardTimeOffset(const QDateTime &atDateTime) const
    +{
    +    if (isValid())
    +        return d->standardTimeOffset(atDateTime.toMSecsSinceEpoch());
    +    else
    +        return 0;
    +}
    +
    +/*!
    +    Returns the daylight-saving time offset at the given \a atDateTime,
    +    i.e. the number of seconds to add to the standard time offset to obtain the
    +    local daylight-saving time.
    +
    +    For example, for the time zone "Europe/Berlin" the DST offset is +3600
    +    seconds.  During standard time daylightTimeOffset() will return 0, and when
    +    daylight-saving is in effect it will return +3600.
    +
    +    \sa offsetFromUtc(), standardTimeOffset()
    +*/
    +
    +int QTimeZone::daylightTimeOffset(const QDateTime &atDateTime) const
    +{
    +    if (hasDaylightTime())
    +        return d->daylightTimeOffset(atDateTime.toMSecsSinceEpoch());
    +    else
    +        return 0;
    +}
    +
    +/*!
    +    Returns \c true if the time zone has practiced daylight-saving at any time.
    +
    +    \sa isDaylightTime(), daylightTimeOffset()
    +*/
    +
    +bool QTimeZone::hasDaylightTime() const
    +{
    +    if (isValid())
    +        return d->hasDaylightTime();
    +    else
    +        return false;
    +}
    +
    +/*!
    +    Returns \c true if daylight-saving was in effect at the given \a atDateTime.
    +
    +    \sa hasDaylightTime(), daylightTimeOffset()
    +*/
    +
    +bool QTimeZone::isDaylightTime(const QDateTime &atDateTime) const
    +{
    +    if (hasDaylightTime())
    +        return d->isDaylightTime(atDateTime.toMSecsSinceEpoch());
    +    else
    +        return false;
    +}
    +
    +/*!
    +    Returns the effective offset details at the given \a forDateTime. This is
    +    the equivalent of calling offsetFromUtc(), abbreviation(), etc individually but is
    +    more efficient.
    +
    +    \sa offsetFromUtc(), standardTimeOffset(), daylightTimeOffset(), abbreviation()
    +*/
    +
    +QTimeZone::OffsetData QTimeZone::offsetData(const QDateTime &forDateTime) const
    +{
    +    if (hasTransitions())
    +        return QTimeZonePrivate::toOffsetData(d->data(forDateTime.toMSecsSinceEpoch()));
    +    else
    +        return QTimeZonePrivate::invalidOffsetData();
    +}
    +
    +/*!
    +    Returns \c true if the system backend supports obtaining transitions.
    +
    +    Transitions are changes in the time-zone: these happen when DST turns on or
    +    off and when authorities alter the offsets for the time-zone.
    +
    +    \sa nextTransition(), previousTransition(), transitions()
    +*/
    +
    +bool QTimeZone::hasTransitions() const
    +{
    +    if (isValid())
    +        return d->hasTransitions();
    +    else
    +        return false;
    +}
    +
    +/*!
    +    Returns the first time zone Transition after the given \a afterDateTime.
    +    This is most useful when you have a Transition time and wish to find the
    +    Transition after it.
    +
    +    If there is no transition after the given \a afterDateTime then an invalid
    +    OffsetData will be returned with an invalid QDateTime.
    +
    +    The given \a afterDateTime is exclusive.
    +
    +    \sa hasTransitions(), previousTransition(), transitions()
    +*/
    +
    +QTimeZone::OffsetData QTimeZone::nextTransition(const QDateTime &afterDateTime) const
    +{
    +    if (hasTransitions())
    +        return QTimeZonePrivate::toOffsetData(d->nextTransition(afterDateTime.toMSecsSinceEpoch()));
    +    else
    +        return QTimeZonePrivate::invalidOffsetData();
    +}
    +
    +/*!
    +    Returns the first time zone Transition before the given \a beforeDateTime.
    +    This is most useful when you have a Transition time and wish to find the
    +    Transition before it.
    +
    +    If there is no transition before the given \a beforeDateTime then an invalid
    +    OffsetData will be returned with an invalid QDateTime.
    +
    +    The given \a beforeDateTime is exclusive.
    +
    +    \sa hasTransitions(), nextTransition(), transitions()
    +*/
    +
    +QTimeZone::OffsetData QTimeZone::previousTransition(const QDateTime &beforeDateTime) const
    +{
    +    if (hasTransitions())
    +        return QTimeZonePrivate::toOffsetData(d->previousTransition(beforeDateTime.toMSecsSinceEpoch()));
    +    else
    +        return QTimeZonePrivate::invalidOffsetData();
    +}
    +
    +/*!
    +    Returns a list of all time zone transitions between the given datetimes.
    +
    +    The given \a fromDateTime and \a toDateTime are inclusive.
    +
    +    \sa hasTransitions(), nextTransition(), previousTransition()
    +*/
    +
    +QTimeZone::OffsetDataList QTimeZone::transitions(const QDateTime &fromDateTime,
    +                                                 const QDateTime &toDateTime) const
    +{
    +    OffsetDataList list;
    +    if (hasTransitions()) {
    +        const QTimeZonePrivate::DataList plist = d->transitions(fromDateTime.toMSecsSinceEpoch(),
    +                                                                toDateTime.toMSecsSinceEpoch());
    +        list.reserve(plist.count());
    +        for (const QTimeZonePrivate::Data &pdata : plist)
    +            list.append(QTimeZonePrivate::toOffsetData(pdata));
    +    }
    +    return list;
    +}
    +
    +// Static methods
    +
    +/*!
    +    Returns the current system time zone IANA ID.
    +
    +    On Windows this ID is translated from the Windows ID using an internal
    +    translation table and the user's selected country.  As a consequence there
    +    is a small chance any Windows install may have IDs not known by Qt, in
    +    which case "UTC" will be returned.
    +*/
    +
    +QByteArray QTimeZone::systemTimeZoneId()
    +{
    +    return global_tz->backend->systemTimeZoneId();
    +}
    +
    +/*!
    +    \since 5.5
    +    Returns a QTimeZone object that refers to the local system time, as
    +    specified by systemTimeZoneId().
    +
    +    \sa utc()
    +*/
    +QTimeZone QTimeZone::systemTimeZone()
    +{
    +    return QTimeZone(QTimeZone::systemTimeZoneId());
    +}
    +
    +/*!
    +    \since 5.5
    +    Returns a QTimeZone object that refers to UTC (Universal Time Coordinated).
    +
    +    \sa systemTimeZone()
    +*/
    +QTimeZone QTimeZone::utc()
    +{
    +    return QTimeZone(QTimeZonePrivate::utcQByteArray());
    +}
    +
    +/*!
    +    Returns \c true if a given time zone \a ianaId is available on this system.
    +
    +    \sa availableTimeZoneIds()
    +*/
    +
    +bool QTimeZone::isTimeZoneIdAvailable(const QByteArray &ianaId)
    +{
    +    // isValidId is not strictly required, but faster to weed out invalid
    +    // IDs as availableTimeZoneIds() may be slow
    +    if (!QTimeZonePrivate::isValidId(ianaId))
    +        return false;
    +    return QUtcTimeZonePrivate().isTimeZoneIdAvailable(ianaId) ||
    +           global_tz->backend->isTimeZoneIdAvailable(ianaId);
    +}
    +
    +static QList set_union(const QList &l1, const QList &l2)
    +{
    +    QList result;
    +    result.reserve(l1.size() + l2.size());
    +    std::set_union(l1.begin(), l1.end(),
    +                   l2.begin(), l2.end(),
    +                   std::back_inserter(result));
    +    return result;
    +}
    +
    +/*!
    +    Returns a list of all available IANA time zone IDs on this system.
    +
    +    \sa isTimeZoneIdAvailable()
    +*/
    +
    +QList QTimeZone::availableTimeZoneIds()
    +{
    +    return set_union(QUtcTimeZonePrivate().availableTimeZoneIds(),
    +                     global_tz->backend->availableTimeZoneIds());
    +}
    +
    +/*!
    +    Returns a list of all available IANA time zone IDs for a given \a country.
    +
    +    As a special case, a \a country of Qt::AnyCountry returns those time zones
    +    that do not have any country related to them, such as UTC.  If you require
    +    a list of all time zone IDs for all countries then use the standard
    +    availableTimeZoneIds() method.
    +
    +    \sa isTimeZoneIdAvailable()
    +*/
    +
    +QList QTimeZone::availableTimeZoneIds(QLocale::Country country)
    +{
    +    return set_union(QUtcTimeZonePrivate().availableTimeZoneIds(country),
    +                     global_tz->backend->availableTimeZoneIds(country));
    +}
    +
    +/*!
    +    Returns a list of all available IANA time zone IDs with a given standard
    +    time offset of \a offsetSeconds.
    +
    +    \sa isTimeZoneIdAvailable()
    +*/
    +
    +QList QTimeZone::availableTimeZoneIds(int offsetSeconds)
    +{
    +    return set_union(QUtcTimeZonePrivate().availableTimeZoneIds(offsetSeconds),
    +                     global_tz->backend->availableTimeZoneIds(offsetSeconds));
    +}
    +
    +/*!
    +    Returns the Windows ID equivalent to the given \a ianaId.
    +
    +    \sa windowsIdToDefaultIanaId(), windowsIdToIanaIds()
    +*/
    +
    +QByteArray QTimeZone::ianaIdToWindowsId(const QByteArray &ianaId)
    +{
    +    return QTimeZonePrivate::ianaIdToWindowsId(ianaId);
    +}
    +
    +/*!
    +    Returns the default IANA ID for a given \a windowsId.
    +
    +    Because a Windows ID can cover several IANA IDs in several different
    +    countries, this function returns the most frequently used IANA ID with no
    +    regard for the country and should thus be used with care.  It is usually
    +    best to request the default for a specific country.
    +
    +    \sa ianaIdToWindowsId(), windowsIdToIanaIds()
    +*/
    +
    +QByteArray QTimeZone::windowsIdToDefaultIanaId(const QByteArray &windowsId)
    +{
    +    return QTimeZonePrivate::windowsIdToDefaultIanaId(windowsId);
    +}
    +
    +/*!
    +    Returns the default IANA ID for a given \a windowsId and \a country.
    +
    +    Because a Windows ID can cover several IANA IDs within a given country,
    +    the most frequently used IANA ID in that country is returned.
    +
    +    As a special case, QLocale::AnyCountry returns the default of those IANA IDs
    +    that do not have any specific country.
    +
    +    \sa ianaIdToWindowsId(), windowsIdToIanaIds()
    +*/
    +
    +QByteArray QTimeZone::windowsIdToDefaultIanaId(const QByteArray &windowsId,
    +                                                QLocale::Country country)
    +{
    +    return QTimeZonePrivate::windowsIdToDefaultIanaId(windowsId, country);
    +}
    +
    +/*!
    +    Returns all the IANA IDs for a given \a windowsId.
    +
    +    The returned list is sorted alphabetically.
    +
    +    \sa ianaIdToWindowsId(), windowsIdToDefaultIanaId()
    +*/
    +
    +QList QTimeZone::windowsIdToIanaIds(const QByteArray &windowsId)
    +{
    +    return QTimeZonePrivate::windowsIdToIanaIds(windowsId);
    +}
    +
    +/*!
    +    Returns all the IANA IDs for a given \a windowsId and \a country.
    +
    +    As a special case QLocale::AnyCountry returns those IANA IDs that do
    +    not have any specific country.
    +
    +    The returned list is in order of frequency of usage, i.e. larger zones
    +    within a country are listed first.
    +
    +    \sa ianaIdToWindowsId(), windowsIdToDefaultIanaId()
    +*/
    +
    +QList QTimeZone::windowsIdToIanaIds(const QByteArray &windowsId,
    +                                                    QLocale::Country country)
    +{
    +    return QTimeZonePrivate::windowsIdToIanaIds(windowsId, country);
    +}
    +
    +#ifndef QT_NO_DATASTREAM
    +QDataStream &operator<<(QDataStream &ds, const QTimeZone &tz)
    +{
    +    tz.d->serialize(ds);
    +    return ds;
    +}
    +
    +QDataStream &operator>>(QDataStream &ds, QTimeZone &tz)
    +{
    +    QString ianaId;
    +    ds >> ianaId;
    +    if (ianaId == QLatin1String("OffsetFromUtc")) {
    +        int utcOffset;
    +        QString name;
    +        QString abbreviation;
    +        int country;
    +        QString comment;
    +        ds >> ianaId >> utcOffset >> name >> abbreviation >> country >> comment;
    +        // Try creating as a system timezone, which succeeds (producing a valid
    +        // zone) iff ianaId is valid; we can then ignore the other data.
    +        tz = QTimeZone(ianaId.toUtf8());
    +        // If not, then construct a custom timezone using all the saved values:
    +        if (!tz.isValid())
    +            tz = QTimeZone(ianaId.toUtf8(), utcOffset, name, abbreviation,
    +                           QLocale::Country(country), comment);
    +    } else {
    +        tz = QTimeZone(ianaId.toUtf8());
    +    }
    +    return ds;
    +}
    +#endif // QT_NO_DATASTREAM
    +
    +#ifndef QT_NO_DEBUG_STREAM
    +QDebug operator<<(QDebug dbg, const QTimeZone &tz)
    +{
    +    QDebugStateSaver saver(dbg);
    +    //TODO Include backend and data version details?
    +    dbg.nospace() << "QTimeZone(" << QString::fromUtf8(tz.id()) << ')';
    +    return dbg;
    +}
    +#endif
    +
    +QT_END_NAMESPACE
    diff --git a/src/corelib/time/qtimezone.h b/src/corelib/time/qtimezone.h
    new file mode 100644
    index 0000000000..62ecee49bb
    --- /dev/null
    +++ b/src/corelib/time/qtimezone.h
    @@ -0,0 +1,188 @@
    +/****************************************************************************
    +**
    +** Copyright (C) 2013 John Layt 
    +** Contact: https://www.qt.io/licensing/
    +**
    +** This file is part of the QtCore module of the Qt Toolkit.
    +**
    +** $QT_BEGIN_LICENSE:LGPL$
    +** Commercial License Usage
    +** Licensees holding valid commercial Qt licenses may use this file in
    +** accordance with the commercial license agreement provided with the
    +** Software or, alternatively, in accordance with the terms contained in
    +** a written agreement between you and The Qt Company. For licensing terms
    +** and conditions see https://www.qt.io/terms-conditions. For further
    +** information use the contact form at https://www.qt.io/contact-us.
    +**
    +** GNU Lesser General Public License Usage
    +** Alternatively, this file may be used under the terms of the GNU Lesser
    +** General Public License version 3 as published by the Free Software
    +** Foundation and appearing in the file LICENSE.LGPL3 included in the
    +** packaging of this file. Please review the following information to
    +** ensure the GNU Lesser General Public License version 3 requirements
    +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
    +**
    +** GNU General Public License Usage
    +** Alternatively, this file may be used under the terms of the GNU
    +** General Public License version 2.0 or (at your option) the GNU General
    +** Public license version 3 or any later version approved by the KDE Free
    +** Qt Foundation. The licenses are as published by the Free Software
    +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
    +** included in the packaging of this file. Please review the following
    +** information to ensure the GNU General Public License requirements will
    +** be met: https://www.gnu.org/licenses/gpl-2.0.html and
    +** https://www.gnu.org/licenses/gpl-3.0.html.
    +**
    +** $QT_END_LICENSE$
    +**
    +****************************************************************************/
    +
    +
    +#ifndef QTIMEZONE_H
    +#define QTIMEZONE_H
    +
    +#include 
    +#include 
    +#include 
    +
    +QT_REQUIRE_CONFIG(timezone);
    +
    +#if (defined(Q_OS_DARWIN) || defined(Q_QDOC)) && !defined(QT_NO_SYSTEMLOCALE)
    +Q_FORWARD_DECLARE_CF_TYPE(CFTimeZone);
    +Q_FORWARD_DECLARE_OBJC_CLASS(NSTimeZone);
    +#endif
    +
    +QT_BEGIN_NAMESPACE
    +
    +class QTimeZonePrivate;
    +
    +class Q_CORE_EXPORT QTimeZone
    +{
    +public:
    +    // Sane UTC offsets range from -14 to +14 hours:
    +    enum {
    +        // No known zone > 12 hrs West of Greenwich (Baker Island, USA)
    +        MinUtcOffsetSecs = -14 * 3600,
    +        // No known zone > 14 hrs East of Greenwich (Kiritimati, Christmas Island, Kiribati)
    +        MaxUtcOffsetSecs = +14 * 3600
    +    };
    +
    +    enum TimeType {
    +        StandardTime = 0,
    +        DaylightTime = 1,
    +        GenericTime = 2
    +    };
    +
    +    enum NameType {
    +        DefaultName = 0,
    +        LongName = 1,
    +        ShortName = 2,
    +        OffsetName = 3
    +    };
    +
    +    struct OffsetData {
    +        QString abbreviation;
    +        QDateTime atUtc;
    +        int offsetFromUtc;
    +        int standardTimeOffset;
    +        int daylightTimeOffset;
    +    };
    +    typedef QVector OffsetDataList;
    +
    +    QTimeZone() noexcept;
    +    explicit QTimeZone(const QByteArray &ianaId);
    +    explicit QTimeZone(int offsetSeconds);
    +    /*implicit*/ QTimeZone(const QByteArray &zoneId, int offsetSeconds, const QString &name,
    +              const QString &abbreviation, QLocale::Country country = QLocale::AnyCountry,
    +              const QString &comment = QString());
    +    QTimeZone(const QTimeZone &other);
    +    ~QTimeZone();
    +
    +    QTimeZone &operator=(const QTimeZone &other);
    +    QTimeZone &operator=(QTimeZone &&other) noexcept { swap(other); return *this; }
    +
    +    void swap(QTimeZone &other) noexcept
    +    { d.swap(other.d); }
    +
    +    bool operator==(const QTimeZone &other) const;
    +    bool operator!=(const QTimeZone &other) const;
    +
    +    bool isValid() const;
    +
    +    QByteArray id() const;
    +    QLocale::Country country() const;
    +    QString comment() const;
    +
    +    QString displayName(const QDateTime &atDateTime,
    +                        QTimeZone::NameType nameType = QTimeZone::DefaultName,
    +                        const QLocale &locale = QLocale()) const;
    +    QString displayName(QTimeZone::TimeType timeType,
    +                        QTimeZone::NameType nameType = QTimeZone::DefaultName,
    +                        const QLocale &locale = QLocale()) const;
    +    QString abbreviation(const QDateTime &atDateTime) const;
    +
    +    int offsetFromUtc(const QDateTime &atDateTime) const;
    +    int standardTimeOffset(const QDateTime &atDateTime) const;
    +    int daylightTimeOffset(const QDateTime &atDateTime) const;
    +
    +    bool hasDaylightTime() const;
    +    bool isDaylightTime(const QDateTime &atDateTime) const;
    +
    +    OffsetData offsetData(const QDateTime &forDateTime) const;
    +
    +    bool hasTransitions() const;
    +    OffsetData nextTransition(const QDateTime &afterDateTime) const;
    +    OffsetData previousTransition(const QDateTime &beforeDateTime) const;
    +    OffsetDataList transitions(const QDateTime &fromDateTime, const QDateTime &toDateTime) const;
    +
    +    static QByteArray systemTimeZoneId();
    +    static QTimeZone systemTimeZone();
    +    static QTimeZone utc();
    +
    +    static bool isTimeZoneIdAvailable(const QByteArray &ianaId);
    +
    +    static QList availableTimeZoneIds();
    +    static QList availableTimeZoneIds(QLocale::Country country);
    +    static QList availableTimeZoneIds(int offsetSeconds);
    +
    +    static QByteArray ianaIdToWindowsId(const QByteArray &ianaId);
    +    static QByteArray windowsIdToDefaultIanaId(const QByteArray &windowsId);
    +    static QByteArray windowsIdToDefaultIanaId(const QByteArray &windowsId,
    +                                                QLocale::Country country);
    +    static QList windowsIdToIanaIds(const QByteArray &windowsId);
    +    static QList windowsIdToIanaIds(const QByteArray &windowsId,
    +                                                 QLocale::Country country);
    +
    +#if (defined(Q_OS_DARWIN) || defined(Q_QDOC)) && !defined(QT_NO_SYSTEMLOCALE)
    +    static QTimeZone fromCFTimeZone(CFTimeZoneRef timeZone);
    +    CFTimeZoneRef toCFTimeZone() const Q_DECL_CF_RETURNS_RETAINED;
    +    static QTimeZone fromNSTimeZone(const NSTimeZone *timeZone);
    +    NSTimeZone *toNSTimeZone() const Q_DECL_NS_RETURNS_AUTORELEASED;
    +#endif
    +
    +private:
    +    QTimeZone(QTimeZonePrivate &dd);
    +#ifndef QT_NO_DATASTREAM
    +    friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &ds, const QTimeZone &tz);
    +#endif
    +    friend class QTimeZonePrivate;
    +    friend class QDateTime;
    +    friend class QDateTimePrivate;
    +    QSharedDataPointer d;
    +};
    +
    +Q_DECLARE_TYPEINFO(QTimeZone::OffsetData, Q_MOVABLE_TYPE);
    +Q_DECLARE_SHARED(QTimeZone)
    +
    +#ifndef QT_NO_DATASTREAM
    +Q_CORE_EXPORT QDataStream &operator<<(QDataStream &ds, const QTimeZone &tz);
    +Q_CORE_EXPORT QDataStream &operator>>(QDataStream &ds, QTimeZone &tz);
    +#endif
    +
    +#ifndef QT_NO_DEBUG_STREAM
    +Q_CORE_EXPORT QDebug operator<<(QDebug dbg, const QTimeZone &tz);
    +#endif
    +
    +QT_END_NAMESPACE
    +
    +#endif // QTIMEZONE_H
    diff --git a/src/corelib/time/qtimezoneprivate.cpp b/src/corelib/time/qtimezoneprivate.cpp
    new file mode 100644
    index 0000000000..569b343187
    --- /dev/null
    +++ b/src/corelib/time/qtimezoneprivate.cpp
    @@ -0,0 +1,926 @@
    +/****************************************************************************
    +**
    +** Copyright (C) 2013 John Layt 
    +** Contact: https://www.qt.io/licensing/
    +**
    +** This file is part of the QtCore module of the Qt Toolkit.
    +**
    +** $QT_BEGIN_LICENSE:LGPL$
    +** Commercial License Usage
    +** Licensees holding valid commercial Qt licenses may use this file in
    +** accordance with the commercial license agreement provided with the
    +** Software or, alternatively, in accordance with the terms contained in
    +** a written agreement between you and The Qt Company. For licensing terms
    +** and conditions see https://www.qt.io/terms-conditions. For further
    +** information use the contact form at https://www.qt.io/contact-us.
    +**
    +** GNU Lesser General Public License Usage
    +** Alternatively, this file may be used under the terms of the GNU Lesser
    +** General Public License version 3 as published by the Free Software
    +** Foundation and appearing in the file LICENSE.LGPL3 included in the
    +** packaging of this file. Please review the following information to
    +** ensure the GNU Lesser General Public License version 3 requirements
    +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
    +**
    +** GNU General Public License Usage
    +** Alternatively, this file may be used under the terms of the GNU
    +** General Public License version 2.0 or (at your option) the GNU General
    +** Public license version 3 or any later version approved by the KDE Free
    +** Qt Foundation. The licenses are as published by the Free Software
    +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
    +** included in the packaging of this file. Please review the following
    +** information to ensure the GNU General Public License requirements will
    +** be met: https://www.gnu.org/licenses/gpl-2.0.html and
    +** https://www.gnu.org/licenses/gpl-3.0.html.
    +**
    +** $QT_END_LICENSE$
    +**
    +****************************************************************************/
    +
    +
    +#include "qtimezone.h"
    +#include "qtimezoneprivate_p.h"
    +#include "qtimezoneprivate_data_p.h"
    +
    +#include 
    +#include 
    +
    +#include 
    +
    +QT_BEGIN_NAMESPACE
    +
    +/*
    +    Static utilities for looking up Windows ID tables
    +*/
    +
    +static const int windowsDataTableSize = sizeof(windowsDataTable) / sizeof(QWindowsData) - 1;
    +static const int zoneDataTableSize = sizeof(zoneDataTable) / sizeof(QZoneData) - 1;
    +static const int utcDataTableSize = sizeof(utcDataTable) / sizeof(QUtcData) - 1;
    +
    +
    +static const QZoneData *zoneData(quint16 index)
    +{
    +    Q_ASSERT(index < zoneDataTableSize);
    +    return &zoneDataTable[index];
    +}
    +
    +static const QWindowsData *windowsData(quint16 index)
    +{
    +    Q_ASSERT(index < windowsDataTableSize);
    +    return &windowsDataTable[index];
    +}
    +
    +static const QUtcData *utcData(quint16 index)
    +{
    +    Q_ASSERT(index < utcDataTableSize);
    +    return &utcDataTable[index];
    +}
    +
    +// Return the Windows ID literal for a given QWindowsData
    +static QByteArray windowsId(const QWindowsData *windowsData)
    +{
    +    return (windowsIdData + windowsData->windowsIdIndex);
    +}
    +
    +// Return the IANA ID literal for a given QWindowsData
    +static QByteArray ianaId(const QWindowsData *windowsData)
    +{
    +    return (ianaIdData + windowsData->ianaIdIndex);
    +}
    +
    +// Return the IANA ID literal for a given QZoneData
    +static QByteArray ianaId(const QZoneData *zoneData)
    +{
    +    return (ianaIdData + zoneData->ianaIdIndex);
    +}
    +
    +static QByteArray utcId(const QUtcData *utcData)
    +{
    +    return (ianaIdData + utcData->ianaIdIndex);
    +}
    +
    +static quint16 toWindowsIdKey(const QByteArray &winId)
    +{
    +    for (quint16 i = 0; i < windowsDataTableSize; ++i) {
    +        const QWindowsData *data = windowsData(i);
    +        if (windowsId(data) == winId)
    +            return data->windowsIdKey;
    +    }
    +    return 0;
    +}
    +
    +static QByteArray toWindowsIdLiteral(quint16 windowsIdKey)
    +{
    +    for (quint16 i = 0; i < windowsDataTableSize; ++i) {
    +        const QWindowsData *data = windowsData(i);
    +        if (data->windowsIdKey == windowsIdKey)
    +            return windowsId(data);
    +    }
    +    return QByteArray();
    +}
    +
    +/*
    +    Base class implementing common utility routines, only intantiate for a null tz.
    +*/
    +
    +QTimeZonePrivate::QTimeZonePrivate()
    +{
    +}
    +
    +QTimeZonePrivate::QTimeZonePrivate(const QTimeZonePrivate &other)
    +    : QSharedData(other), m_id(other.m_id)
    +{
    +}
    +
    +QTimeZonePrivate::~QTimeZonePrivate()
    +{
    +}
    +
    +QTimeZonePrivate *QTimeZonePrivate::clone() const
    +{
    +    return new QTimeZonePrivate(*this);
    +}
    +
    +bool QTimeZonePrivate::operator==(const QTimeZonePrivate &other) const
    +{
    +    // TODO Too simple, but need to solve problem of comparing different derived classes
    +    // Should work for all System and ICU classes as names guaranteed unique, but not for Simple.
    +    // Perhaps once all classes have working transitions can compare full list?
    +    return (m_id == other.m_id);
    +}
    +
    +bool QTimeZonePrivate::operator!=(const QTimeZonePrivate &other) const
    +{
    +    return !(*this == other);
    +}
    +
    +bool QTimeZonePrivate::isValid() const
    +{
    +    return !m_id.isEmpty();
    +}
    +
    +QByteArray QTimeZonePrivate::id() const
    +{
    +    return m_id;
    +}
    +
    +QLocale::Country QTimeZonePrivate::country() const
    +{
    +    // Default fall-back mode, use the zoneTable to find Region of known Zones
    +    for (int i = 0; i < zoneDataTableSize; ++i) {
    +        const QZoneData *data = zoneData(i);
    +        if (ianaId(data).split(' ').contains(m_id))
    +            return (QLocale::Country)data->country;
    +    }
    +    return QLocale::AnyCountry;
    +}
    +
    +QString QTimeZonePrivate::comment() const
    +{
    +    return QString();
    +}
    +
    +QString QTimeZonePrivate::displayName(qint64 atMSecsSinceEpoch,
    +                                      QTimeZone::NameType nameType,
    +                                      const QLocale &locale) const
    +{
    +    if (nameType == QTimeZone::OffsetName)
    +        return isoOffsetFormat(offsetFromUtc(atMSecsSinceEpoch));
    +
    +    if (isDaylightTime(atMSecsSinceEpoch))
    +        return displayName(QTimeZone::DaylightTime, nameType, locale);
    +    else
    +        return displayName(QTimeZone::StandardTime, nameType, locale);
    +}
    +
    +QString QTimeZonePrivate::displayName(QTimeZone::TimeType timeType,
    +                                      QTimeZone::NameType nameType,
    +                                      const QLocale &locale) const
    +{
    +    Q_UNUSED(timeType)
    +    Q_UNUSED(nameType)
    +    Q_UNUSED(locale)
    +    return QString();
    +}
    +
    +QString QTimeZonePrivate::abbreviation(qint64 atMSecsSinceEpoch) const
    +{
    +    Q_UNUSED(atMSecsSinceEpoch)
    +    return QString();
    +}
    +
    +int QTimeZonePrivate::offsetFromUtc(qint64 atMSecsSinceEpoch) const
    +{
    +    return standardTimeOffset(atMSecsSinceEpoch) + daylightTimeOffset(atMSecsSinceEpoch);
    +}
    +
    +int QTimeZonePrivate::standardTimeOffset(qint64 atMSecsSinceEpoch) const
    +{
    +    Q_UNUSED(atMSecsSinceEpoch)
    +    return invalidSeconds();
    +}
    +
    +int QTimeZonePrivate::daylightTimeOffset(qint64 atMSecsSinceEpoch) const
    +{
    +    Q_UNUSED(atMSecsSinceEpoch)
    +    return invalidSeconds();
    +}
    +
    +bool QTimeZonePrivate::hasDaylightTime() const
    +{
    +    return false;
    +}
    +
    +bool QTimeZonePrivate::isDaylightTime(qint64 atMSecsSinceEpoch) const
    +{
    +    Q_UNUSED(atMSecsSinceEpoch)
    +    return false;
    +}
    +
    +QTimeZonePrivate::Data QTimeZonePrivate::data(qint64 forMSecsSinceEpoch) const
    +{
    +    Q_UNUSED(forMSecsSinceEpoch)
    +    return invalidData();
    +}
    +
    +// Private only method for use by QDateTime to convert local msecs to epoch msecs
    +QTimeZonePrivate::Data QTimeZonePrivate::dataForLocalTime(qint64 forLocalMSecs, int hint) const
    +{
    +    if (!hasDaylightTime()) // No DST means same offset for all local msecs
    +        return data(forLocalMSecs - standardTimeOffset(forLocalMSecs) * 1000);
    +
    +    /*
    +      We need a UTC time at which to ask for the offset, in order to be able to
    +      add that offset to forLocalMSecs, to get the UTC time we
    +      need. Fortunately, no time-zone offset is more than 14 hours; and DST
    +      transitions happen (much) more than thirty-two hours apart.  So sampling
    +      offset sixteen hours each side gives us information we can be sure
    +      brackets the correct time and at most one DST transition.
    +    */
    +    const qint64 sixteenHoursInMSecs(16 * 3600 * 1000);
    +    Q_STATIC_ASSERT(-sixteenHoursInMSecs / 1000 < QTimeZone::MinUtcOffsetSecs
    +                  && sixteenHoursInMSecs / 1000 > QTimeZone::MaxUtcOffsetSecs);
    +    const qint64 recent = forLocalMSecs - sixteenHoursInMSecs;
    +    const qint64 imminent = forLocalMSecs + sixteenHoursInMSecs;
    +    /*
    +      Offsets are Local - UTC, positive to the east of Greenwich, negative to
    +      the west; DST offset always exceeds standard offset, when DST applies.
    +      When we have offsets on either side of a transition, the lower one is
    +      standard, the higher is DST.
    +
    +      Non-DST transitions (jurisdictions changing time-zone and time-zones
    +      changing their standard offset, typically) are described below as if they
    +      were DST transitions (since these are more usual and familiar); the code
    +      mostly concerns itself with offsets from UTC, described in terms of the
    +      common case for changes in that.  If there is no actual change in offset
    +      (e.g. a DST transition cancelled by a standard offset change), this code
    +      should handle it gracefully; without transitions, it'll see early == late
    +      and take the easy path; with transitions, tran and nextTran get the
    +      correct UTC time as atMSecsSinceEpoch so comparing to nextStart selects
    +      the right one.  In all other cases, the transition changes offset and the
    +      reasoning that applies to DST applies just the same.  Aside from hinting,
    +      the only thing that looks at DST-ness at all, other than inferred from
    +      offset changes, is the case without transition data handling an invalid
    +      time in the gap that a transition passed over.
    +
    +      The handling of hint (see below) is apt to go wrong in non-DST
    +      transitions.  There isn't really a great deal we can hope to do about that
    +      without adding yet more unreliable complexity to the heuristics in use for
    +      already obscure corner-cases.
    +     */
    +
    +    /*
    +      The hint (really a QDateTimePrivate::DaylightStatus) is > 0 if caller
    +      thinks we're in DST, 0 if in standard.  A value of -2 means never-DST, so
    +      should have been handled above; if it slips through, it's wrong but we
    +      should probably treat it as standard anyway (never-DST means
    +      always-standard, after all).  If the hint turns out to be wrong, fall back
    +      on trying the other possibility: which makes it harmless to treat -1
    +      (meaning unknown) as standard (i.e. try standard first, then try DST).  In
    +      practice, away from a transition, the only difference hint makes is to
    +      which candidate we try first: if the hint is wrong (or unknown and
    +      standard fails), we'll try the other candidate and it'll work.
    +
    +      For the obscure (and invalid) case where forLocalMSecs falls in a
    +      spring-forward's missing hour, a common case is that we started with a
    +      date/time for which the hint was valid and adjusted it naively; for that
    +      case, we should correct the adjustment by shunting across the transition
    +      into where hint is wrong.  So half-way through the gap, arrived at from
    +      the DST side, should be read as an hour earlier, in standard time; but, if
    +      arrived at from the standard side, should be read as an hour later, in
    +      DST.  (This shall be wrong in some cases; for example, when a country
    +      changes its transition dates and changing a date/time by more than six
    +      months lands it on a transition.  However, these cases are even more
    +      obscure than those where the heuristic is good.)
    +     */
    +
    +    if (hasTransitions()) {
    +        /*
    +          We have transitions.
    +
    +          Each transition gives the offsets to use until the next; so we need the
    +          most recent transition before the time forLocalMSecs describes.  If it
    +          describes a time *in* a transition, we'll need both that transition and
    +          the one before it.  So find one transition that's probably after (and not
    +          much before, otherwise) and another that's definitely before, then work
    +          out which one to use.  When both or neither work on forLocalMSecs, use
    +          hint to disambiguate.
    +        */
    +
    +        // Get a transition definitely before the local MSecs; usually all we need.
    +        // Only around the transition times might we need another.
    +        Data tran = previousTransition(recent);
    +        Q_ASSERT(forLocalMSecs < 0 || // Pre-epoch TZ info may be unavailable
    +                 forLocalMSecs - tran.offsetFromUtc * 1000 >= tran.atMSecsSinceEpoch);
    +        Data nextTran = nextTransition(tran.atMSecsSinceEpoch);
    +        /*
    +          Now walk those forward until they bracket forLocalMSecs with transitions.
    +
    +          One of the transitions should then be telling us the right offset to use.
    +          In a transition, we need the transition before it (to describe the run-up
    +          to the transition) and the transition itself; so we need to stop when
    +          nextTran is that transition.
    +        */
    +        while (nextTran.atMSecsSinceEpoch != invalidMSecs()
    +               && forLocalMSecs > nextTran.atMSecsSinceEpoch + nextTran.offsetFromUtc * 1000) {
    +            Data newTran = nextTransition(nextTran.atMSecsSinceEpoch);
    +            if (newTran.atMSecsSinceEpoch == invalidMSecs()
    +                || newTran.atMSecsSinceEpoch + newTran.offsetFromUtc * 1000 > imminent) {
    +                // Definitely not a relevant tansition: too far in the future.
    +                break;
    +            }
    +            tran = nextTran;
    +            nextTran = newTran;
    +        }
    +
    +        // Check we do *really* have transitions for this zone:
    +        if (tran.atMSecsSinceEpoch != invalidMSecs()) {
    +
    +            /*
    +              So now tran is definitely before and nextTran is either after or only
    +              slightly before.  One is standard time; we interpret the other as DST
    +              (although the transition might in fact by a change in standard offset).  Our
    +              hint tells us which of those to use (defaulting to standard if no hint): try
    +              it first; if that fails, try the other; if both fail, life's tricky.
    +            */
    +            Q_ASSERT(forLocalMSecs < 0
    +                     || forLocalMSecs - tran.offsetFromUtc * 1000 > tran.atMSecsSinceEpoch);
    +            const qint64 nextStart = nextTran.atMSecsSinceEpoch;
    +            // Work out the UTC values it might make sense to return:
    +            nextTran.atMSecsSinceEpoch = forLocalMSecs - nextTran.offsetFromUtc * 1000;
    +            tran.atMSecsSinceEpoch = forLocalMSecs - tran.offsetFromUtc * 1000;
    +
    +            // If both or neither have zero DST, treat the one with lower offset as standard:
    +            const bool nextIsDst = !nextTran.daylightTimeOffset == !tran.daylightTimeOffset
    +                ? tran.offsetFromUtc < nextTran.offsetFromUtc : nextTran.daylightTimeOffset;
    +            // If that agrees with hint > 0, our first guess is to use nextTran; else tran.
    +            const bool nextFirst = nextIsDst == (hint > 0) && nextStart != invalidMSecs();
    +            for (int i = 0; i < 2; i++) {
    +                /*
    +                  On the first pass, the case we consider is what hint told us to expect
    +                  (except when hint was -1 and didn't actually tell us what to expect),
    +                  so it's likely right.  We only get a second pass if the first failed,
    +                  by which time the second case, that we're trying, is likely right.  If
    +                  an overwhelming majority of calls have hint == -1, the Q_LIKELY here
    +                  shall be wrong half the time; otherwise, its errors shall be rarer
    +                  than that.
    +                */
    +                if (nextFirst ? i == 0 : i) {
    +                    Q_ASSERT(nextStart != invalidMSecs());
    +                    if (Q_LIKELY(nextStart <= nextTran.atMSecsSinceEpoch))
    +                        return nextTran;
    +                } else {
    +                    // If next is invalid, nextFirst is false, to route us here first:
    +                    if (nextStart == invalidMSecs() || Q_LIKELY(nextStart > tran.atMSecsSinceEpoch))
    +                        return tran;
    +                }
    +            }
    +
    +            /*
    +              Neither is valid (e.g. in a spring-forward's gap) and
    +              nextTran.atMSecsSinceEpoch < nextStart <= tran.atMSecsSinceEpoch, so
    +              0 < tran.atMSecsSinceEpoch - nextTran.atMSecsSinceEpoch
    +              = (nextTran.offsetFromUtc - tran.offsetFromUtc) * 1000
    +            */
    +            int dstStep = (nextTran.offsetFromUtc - tran.offsetFromUtc) * 1000;
    +            Q_ASSERT(dstStep > 0); // How else could we get here ?
    +            if (nextFirst) { // hint thought we needed nextTran, so use tran
    +                tran.atMSecsSinceEpoch -= dstStep;
    +                return tran;
    +            }
    +            nextTran.atMSecsSinceEpoch += dstStep;
    +            return nextTran;
    +        }
    +        // System has transitions but not for this zone.
    +        // Try falling back to offsetFromUtc
    +    }
    +
    +    /* Bracket and refine to discover offset. */
    +    qint64 utcEpochMSecs;
    +
    +    int early = offsetFromUtc(recent);
    +    int late = offsetFromUtc(imminent);
    +    if (Q_LIKELY(early == late)) { // > 99% of the time
    +        utcEpochMSecs = forLocalMSecs - early * 1000;
    +    } else {
    +        // Close to a DST transition: early > late is near a fall-back,
    +        // early < late is near a spring-forward.
    +        const int offsetInDst = qMax(early, late);
    +        const int offsetInStd = qMin(early, late);
    +        // Candidate values for utcEpochMSecs (if forLocalMSecs is valid):
    +        const qint64 forDst = forLocalMSecs - offsetInDst * 1000;
    +        const qint64 forStd = forLocalMSecs - offsetInStd * 1000;
    +        // Best guess at the answer:
    +        const qint64 hinted = hint > 0 ? forDst : forStd;
    +        if (Q_LIKELY(offsetFromUtc(hinted) == (hint > 0 ? offsetInDst : offsetInStd))) {
    +            utcEpochMSecs = hinted;
    +        } else if (hint <= 0 && offsetFromUtc(forDst) == offsetInDst) {
    +            utcEpochMSecs = forDst;
    +        } else if (hint > 0 && offsetFromUtc(forStd) == offsetInStd) {
    +            utcEpochMSecs = forStd;
    +        } else {
    +            // Invalid forLocalMSecs: in spring-forward gap.
    +            const int dstStep = daylightTimeOffset(early < late ? imminent : recent) * 1000;
    +            Q_ASSERT(dstStep); // There can't be a transition without it !
    +            utcEpochMSecs = (hint > 0) ? forStd - dstStep : forDst + dstStep;
    +        }
    +    }
    +
    +    return data(utcEpochMSecs);
    +}
    +
    +bool QTimeZonePrivate::hasTransitions() const
    +{
    +    return false;
    +}
    +
    +QTimeZonePrivate::Data QTimeZonePrivate::nextTransition(qint64 afterMSecsSinceEpoch) const
    +{
    +    Q_UNUSED(afterMSecsSinceEpoch)
    +    return invalidData();
    +}
    +
    +QTimeZonePrivate::Data QTimeZonePrivate::previousTransition(qint64 beforeMSecsSinceEpoch) const
    +{
    +    Q_UNUSED(beforeMSecsSinceEpoch)
    +    return invalidData();
    +}
    +
    +QTimeZonePrivate::DataList QTimeZonePrivate::transitions(qint64 fromMSecsSinceEpoch,
    +                                                         qint64 toMSecsSinceEpoch) const
    +{
    +    DataList list;
    +    if (toMSecsSinceEpoch >= fromMSecsSinceEpoch) {
    +        // fromMSecsSinceEpoch is inclusive but nextTransitionTime() is exclusive so go back 1 msec
    +        Data next = nextTransition(fromMSecsSinceEpoch - 1);
    +        while (next.atMSecsSinceEpoch != invalidMSecs()
    +               && next.atMSecsSinceEpoch <= toMSecsSinceEpoch) {
    +            list.append(next);
    +            next = nextTransition(next.atMSecsSinceEpoch);
    +        }
    +    }
    +    return list;
    +}
    +
    +QByteArray QTimeZonePrivate::systemTimeZoneId() const
    +{
    +    return QByteArray();
    +}
    +
    +bool QTimeZonePrivate::isTimeZoneIdAvailable(const QByteArray& ianaId) const
    +{
    +    // Fall-back implementation, can be made faster in subclasses
    +    const QList tzIds = availableTimeZoneIds();
    +    return std::binary_search(tzIds.begin(), tzIds.end(), ianaId);
    +}
    +
    +QList QTimeZonePrivate::availableTimeZoneIds() const
    +{
    +    return QList();
    +}
    +
    +QList QTimeZonePrivate::availableTimeZoneIds(QLocale::Country country) const
    +{
    +    // Default fall-back mode, use the zoneTable to find Region of know Zones
    +    QList regions;
    +
    +    // First get all Zones in the Zones table belonging to the Region
    +    for (int i = 0; i < zoneDataTableSize; ++i) {
    +        if (zoneData(i)->country == country)
    +            regions += ianaId(zoneData(i)).split(' ');
    +    }
    +
    +    std::sort(regions.begin(), regions.end());
    +    regions.erase(std::unique(regions.begin(), regions.end()), regions.end());
    +
    +    // Then select just those that are available
    +    const QList all = availableTimeZoneIds();
    +    QList result;
    +    result.reserve(qMin(all.size(), regions.size()));
    +    std::set_intersection(all.begin(), all.end(), regions.cbegin(), regions.cend(),
    +                          std::back_inserter(result));
    +    return result;
    +}
    +
    +QList QTimeZonePrivate::availableTimeZoneIds(int offsetFromUtc) const
    +{
    +    // Default fall-back mode, use the zoneTable to find Offset of know Zones
    +    QList offsets;
    +    // First get all Zones in the table using the Offset
    +    for (int i = 0; i < windowsDataTableSize; ++i) {
    +        const QWindowsData *winData = windowsData(i);
    +        if (winData->offsetFromUtc == offsetFromUtc) {
    +            for (int j = 0; j < zoneDataTableSize; ++j) {
    +                const QZoneData *data = zoneData(j);
    +                if (data->windowsIdKey == winData->windowsIdKey)
    +                    offsets += ianaId(data).split(' ');
    +            }
    +        }
    +    }
    +
    +    std::sort(offsets.begin(), offsets.end());
    +    offsets.erase(std::unique(offsets.begin(), offsets.end()), offsets.end());
    +
    +    // Then select just those that are available
    +    const QList all = availableTimeZoneIds();
    +    QList result;
    +    result.reserve(qMin(all.size(), offsets.size()));
    +    std::set_intersection(all.begin(), all.end(), offsets.cbegin(), offsets.cend(),
    +                          std::back_inserter(result));
    +    return result;
    +}
    +
    +#ifndef QT_NO_DATASTREAM
    +void QTimeZonePrivate::serialize(QDataStream &ds) const
    +{
    +    ds << QString::fromUtf8(m_id);
    +}
    +#endif // QT_NO_DATASTREAM
    +
    +// Static Utility Methods
    +
    +QTimeZonePrivate::Data QTimeZonePrivate::invalidData()
    +{
    +    Data data;
    +    data.atMSecsSinceEpoch = invalidMSecs();
    +    data.offsetFromUtc = invalidSeconds();
    +    data.standardTimeOffset = invalidSeconds();
    +    data.daylightTimeOffset = invalidSeconds();
    +    return data;
    +}
    +
    +QTimeZone::OffsetData QTimeZonePrivate::invalidOffsetData()
    +{
    +    QTimeZone::OffsetData offsetData;
    +    offsetData.atUtc = QDateTime();
    +    offsetData.offsetFromUtc = invalidSeconds();
    +    offsetData.standardTimeOffset = invalidSeconds();
    +    offsetData.daylightTimeOffset = invalidSeconds();
    +    return offsetData;
    +}
    +
    +QTimeZone::OffsetData QTimeZonePrivate::toOffsetData(const QTimeZonePrivate::Data &data)
    +{
    +    QTimeZone::OffsetData offsetData = invalidOffsetData();
    +    if (data.atMSecsSinceEpoch != invalidMSecs()) {
    +        offsetData.atUtc = QDateTime::fromMSecsSinceEpoch(data.atMSecsSinceEpoch, Qt::UTC);
    +        offsetData.offsetFromUtc = data.offsetFromUtc;
    +        offsetData.standardTimeOffset = data.standardTimeOffset;
    +        offsetData.daylightTimeOffset = data.daylightTimeOffset;
    +        offsetData.abbreviation = data.abbreviation;
    +    }
    +    return offsetData;
    +}
    +
    +// Is the format of the ID valid ?
    +bool QTimeZonePrivate::isValidId(const QByteArray &ianaId)
    +{
    +    /*
    +      Main rules for defining TZ/IANA names as per ftp://ftp.iana.org/tz/code/Theory
    +       1. Use only valid POSIX file name components
    +       2. Within a file name component, use only ASCII letters, `.', `-' and `_'.
    +       3. Do not use digits (except in a [+-]\d+ suffix, when used).
    +       4. A file name component must not exceed 14 characters or start with `-'
    +      However, the rules are really guidelines - a later one says
    +       - Do not change established names if they only marginally violate the
    +         above rules.
    +      We may, therefore, need to be a bit slack in our check here, if we hit
    +      legitimate exceptions in real time-zone databases.
    +
    +      In particular, aliases such as "Etc/GMT+7" and "SystemV/EST5EDT" are valid
    +      so we need to accept digits, ':', and '+'; aliases typically have the form
    +      of POSIX TZ strings, which allow a suffix to a proper IANA name.  A POSIX
    +      suffix starts with an offset (as in GMT+7) and may continue with another
    +      name (as in EST5EDT, giving the DST name of the zone); a further offset is
    +      allowed (for DST).  The ("hard to describe and [...] error-prone in
    +      practice") POSIX form even allows a suffix giving the dates (and
    +      optionally times) of the annual DST transitions.  Hopefully, no TZ aliases
    +      go that far, but we at least need to accept an offset and (single
    +      fragment) DST-name.
    +
    +      But for the legacy complications, the following would be preferable if
    +      QRegExp would work on QByteArrays directly:
    +          const QRegExp rx(QStringLiteral("[a-z+._][a-z+._-]{,13}"
    +                                      "(?:/[a-z+._][a-z+._-]{,13})*"
    +                                          // Optional suffix:
    +                                          "(?:[+-]?\d{1,2}(?::\d{1,2}){,2}" // offset
    +                                             // one name fragment (DST):
    +                                             "(?:[a-z+._][a-z+._-]{,13})?)"),
    +                           Qt::CaseInsensitive);
    +          return rx.exactMatch(ianaId);
    +    */
    +
    +    // Somewhat slack hand-rolled version:
    +    const int MinSectionLength = 1;
    +    const int MaxSectionLength = 14;
    +    int sectionLength = 0;
    +    for (const char *it = ianaId.begin(), * const end = ianaId.end(); it != end; ++it, ++sectionLength) {
    +        const char ch = *it;
    +        if (ch == '/') {
    +            if (sectionLength < MinSectionLength || sectionLength > MaxSectionLength)
    +                return false; // violates (4)
    +            sectionLength = -1;
    +        } else if (ch == '-') {
    +            if (sectionLength == 0)
    +                return false; // violates (4)
    +        } else if (!(ch >= 'a' && ch <= 'z')
    +                && !(ch >= 'A' && ch <= 'Z')
    +                && !(ch == '_')
    +                && !(ch == '.')
    +                   // Should ideally check these only happen as an offset:
    +                && !(ch >= '0' && ch <= '9')
    +                && !(ch == '+')
    +                && !(ch == ':')) {
    +            return false; // violates (2)
    +        }
    +    }
    +    if (sectionLength < MinSectionLength || sectionLength > MaxSectionLength)
    +        return false; // violates (4)
    +    return true;
    +}
    +
    +QString QTimeZonePrivate::isoOffsetFormat(int offsetFromUtc)
    +{
    +    const int mins = offsetFromUtc / 60;
    +    return QString::fromUtf8("UTC%1%2:%3").arg(mins >= 0 ? QLatin1Char('+') : QLatin1Char('-'))
    +                                          .arg(qAbs(mins) / 60, 2, 10, QLatin1Char('0'))
    +                                          .arg(qAbs(mins) % 60, 2, 10, QLatin1Char('0'));
    +}
    +
    +QByteArray QTimeZonePrivate::ianaIdToWindowsId(const QByteArray &id)
    +{
    +    for (int i = 0; i < zoneDataTableSize; ++i) {
    +        const QZoneData *data = zoneData(i);
    +        if (ianaId(data).split(' ').contains(id))
    +            return toWindowsIdLiteral(data->windowsIdKey);
    +    }
    +    return QByteArray();
    +}
    +
    +QByteArray QTimeZonePrivate::windowsIdToDefaultIanaId(const QByteArray &windowsId)
    +{
    +    const quint16 windowsIdKey = toWindowsIdKey(windowsId);
    +    for (int i = 0; i < windowsDataTableSize; ++i) {
    +        const QWindowsData *data = windowsData(i);
    +        if (data->windowsIdKey == windowsIdKey)
    +            return ianaId(data);
    +    }
    +    return QByteArray();
    +}
    +
    +QByteArray QTimeZonePrivate::windowsIdToDefaultIanaId(const QByteArray &windowsId,
    +                                                       QLocale::Country country)
    +{
    +    const QList list = windowsIdToIanaIds(windowsId, country);
    +    if (list.count() > 0)
    +        return list.first();
    +    else
    +        return QByteArray();
    +}
    +
    +QList QTimeZonePrivate::windowsIdToIanaIds(const QByteArray &windowsId)
    +{
    +    const quint16 windowsIdKey = toWindowsIdKey(windowsId);
    +    QList list;
    +
    +    for (int i = 0; i < zoneDataTableSize; ++i) {
    +        const QZoneData *data = zoneData(i);
    +        if (data->windowsIdKey == windowsIdKey)
    +            list << ianaId(data).split(' ');
    +    }
    +
    +    // Return the full list in alpha order
    +    std::sort(list.begin(), list.end());
    +    return list;
    +}
    +
    +QList QTimeZonePrivate::windowsIdToIanaIds(const QByteArray &windowsId,
    +                                                        QLocale::Country country)
    +{
    +    const quint16 windowsIdKey = toWindowsIdKey(windowsId);
    +    for (int i = 0; i < zoneDataTableSize; ++i) {
    +        const QZoneData *data = zoneData(i);
    +        // Return the region matches in preference order
    +        if (data->windowsIdKey == windowsIdKey && data->country == (quint16) country)
    +            return ianaId(data).split(' ');
    +    }
    +
    +    return QList();
    +}
    +
    +// Define template for derived classes to reimplement so QSharedDataPointer clone() works correctly
    +template<> QTimeZonePrivate *QSharedDataPointer::clone()
    +{
    +    return d->clone();
    +}
    +
    +/*
    +    UTC Offset implementation, used when QT_NO_SYSTEMLOCALE set and ICU is not being used,
    +    or for QDateTimes with a Qt:Spec of Qt::OffsetFromUtc.
    +*/
    +
    +// Create default UTC time zone
    +QUtcTimeZonePrivate::QUtcTimeZonePrivate()
    +{
    +    const QString name = utcQString();
    +    init(utcQByteArray(), 0, name, name, QLocale::AnyCountry, name);
    +}
    +
    +// Create a named UTC time zone
    +QUtcTimeZonePrivate::QUtcTimeZonePrivate(const QByteArray &id)
    +{
    +    // Look for the name in the UTC list, if found set the values
    +    for (int i = 0; i < utcDataTableSize; ++i) {
    +        const QUtcData *data = utcData(i);
    +        const QByteArray uid = utcId(data);
    +        if (uid == id) {
    +            QString name = QString::fromUtf8(id);
    +            init(id, data->offsetFromUtc, name, name, QLocale::AnyCountry, name);
    +            break;
    +        }
    +    }
    +}
    +
    +// Create offset from UTC
    +QUtcTimeZonePrivate::QUtcTimeZonePrivate(qint32 offsetSeconds)
    +{
    +    QString utcId;
    +
    +    if (offsetSeconds == 0)
    +        utcId = utcQString();
    +    else
    +        utcId = isoOffsetFormat(offsetSeconds);
    +
    +    init(utcId.toUtf8(), offsetSeconds, utcId, utcId, QLocale::AnyCountry, utcId);
    +}
    +
    +QUtcTimeZonePrivate::QUtcTimeZonePrivate(const QByteArray &zoneId, int offsetSeconds,
    +                                         const QString &name, const QString &abbreviation,
    +                                         QLocale::Country country, const QString &comment)
    +{
    +    init(zoneId, offsetSeconds, name, abbreviation, country, comment);
    +}
    +
    +QUtcTimeZonePrivate::QUtcTimeZonePrivate(const QUtcTimeZonePrivate &other)
    +    : QTimeZonePrivate(other), m_name(other.m_name),
    +      m_abbreviation(other.m_abbreviation),
    +      m_comment(other.m_comment),
    +      m_country(other.m_country),
    +      m_offsetFromUtc(other.m_offsetFromUtc)
    +{
    +}
    +
    +QUtcTimeZonePrivate::~QUtcTimeZonePrivate()
    +{
    +}
    +
    +QUtcTimeZonePrivate *QUtcTimeZonePrivate::clone() const
    +{
    +    return new QUtcTimeZonePrivate(*this);
    +}
    +
    +QTimeZonePrivate::Data QUtcTimeZonePrivate::data(qint64 forMSecsSinceEpoch) const
    +{
    +    Data d;
    +    d.abbreviation = m_abbreviation;
    +    d.atMSecsSinceEpoch = forMSecsSinceEpoch;
    +    d.standardTimeOffset = d.offsetFromUtc = m_offsetFromUtc;
    +    d.daylightTimeOffset = 0;
    +    return d;
    +}
    +
    +void QUtcTimeZonePrivate::init(const QByteArray &zoneId)
    +{
    +    m_id = zoneId;
    +}
    +
    +void QUtcTimeZonePrivate::init(const QByteArray &zoneId, int offsetSeconds, const QString &name,
    +                               const QString &abbreviation, QLocale::Country country,
    +                               const QString &comment)
    +{
    +    m_id = zoneId;
    +    m_offsetFromUtc = offsetSeconds;
    +    m_name = name;
    +    m_abbreviation = abbreviation;
    +    m_country = country;
    +    m_comment = comment;
    +}
    +
    +QLocale::Country QUtcTimeZonePrivate::country() const
    +{
    +    return m_country;
    +}
    +
    +QString QUtcTimeZonePrivate::comment() const
    +{
    +    return m_comment;
    +}
    +
    +QString QUtcTimeZonePrivate::displayName(QTimeZone::TimeType timeType,
    +                                         QTimeZone::NameType nameType,
    +                                         const QLocale &locale) const
    +{
    +    Q_UNUSED(timeType)
    +    Q_UNUSED(locale)
    +    if (nameType == QTimeZone::ShortName)
    +        return m_abbreviation;
    +    else if (nameType == QTimeZone::OffsetName)
    +        return isoOffsetFormat(m_offsetFromUtc);
    +    return m_name;
    +}
    +
    +QString QUtcTimeZonePrivate::abbreviation(qint64 atMSecsSinceEpoch) const
    +{
    +    Q_UNUSED(atMSecsSinceEpoch)
    +    return m_abbreviation;
    +}
    +
    +qint32 QUtcTimeZonePrivate::standardTimeOffset(qint64 atMSecsSinceEpoch) const
    +{
    +    Q_UNUSED(atMSecsSinceEpoch)
    +    return m_offsetFromUtc;
    +}
    +
    +qint32 QUtcTimeZonePrivate::daylightTimeOffset(qint64 atMSecsSinceEpoch) const
    +{
    +    Q_UNUSED(atMSecsSinceEpoch)
    +    return 0;
    +}
    +
    +QByteArray QUtcTimeZonePrivate::systemTimeZoneId() const
    +{
    +    return utcQByteArray();
    +}
    +
    +bool QUtcTimeZonePrivate::isTimeZoneIdAvailable(const QByteArray &ianaId) const
    +{
    +    for (int i = 0; i < utcDataTableSize; ++i) {
    +        const QUtcData *data = utcData(i);
    +        if (utcId(data) == ianaId) {
    +            return true;
    +        }
    +    }
    +    return false;
    +}
    +
    +QList QUtcTimeZonePrivate::availableTimeZoneIds() const
    +{
    +    QList result;
    +    result.reserve(utcDataTableSize);
    +    for (int i = 0; i < utcDataTableSize; ++i)
    +        result << utcId(utcData(i));
    +    std::sort(result.begin(), result.end()); // ### or already sorted??
    +    // ### assuming no duplicates
    +    return result;
    +}
    +
    +QList QUtcTimeZonePrivate::availableTimeZoneIds(QLocale::Country country) const
    +{
    +    // If AnyCountry then is request for all non-region offset codes
    +    if (country == QLocale::AnyCountry)
    +        return availableTimeZoneIds();
    +    return QList();
    +}
    +
    +QList QUtcTimeZonePrivate::availableTimeZoneIds(qint32 offsetSeconds) const
    +{
    +    QList result;
    +    for (int i = 0; i < utcDataTableSize; ++i) {
    +        const QUtcData *data = utcData(i);
    +        if (data->offsetFromUtc == offsetSeconds)
    +            result << utcId(data);
    +    }
    +    std::sort(result.begin(), result.end()); // ### or already sorted??
    +    // ### assuming no duplicates
    +    return result;
    +}
    +
    +#ifndef QT_NO_DATASTREAM
    +void QUtcTimeZonePrivate::serialize(QDataStream &ds) const
    +{
    +    ds << QStringLiteral("OffsetFromUtc") << QString::fromUtf8(m_id) << m_offsetFromUtc << m_name
    +       << m_abbreviation << (qint32) m_country << m_comment;
    +}
    +#endif // QT_NO_DATASTREAM
    +
    +QT_END_NAMESPACE
    diff --git a/src/corelib/time/qtimezoneprivate_android.cpp b/src/corelib/time/qtimezoneprivate_android.cpp
    new file mode 100644
    index 0000000000..be4f374fdd
    --- /dev/null
    +++ b/src/corelib/time/qtimezoneprivate_android.cpp
    @@ -0,0 +1,257 @@
    +/****************************************************************************
    +**
    +** Copyright (C) 2014 Drew Parsons 
    +** Contact: https://www.qt.io/licensing/
    +**
    +** This file is part of the QtCore module of the Qt Toolkit.
    +**
    +** $QT_BEGIN_LICENSE:LGPL$
    +** Commercial License Usage
    +** Licensees holding valid commercial Qt licenses may use this file in
    +** accordance with the commercial license agreement provided with the
    +** Software or, alternatively, in accordance with the terms contained in
    +** a written agreement between you and The Qt Company. For licensing terms
    +** and conditions see https://www.qt.io/terms-conditions. For further
    +** information use the contact form at https://www.qt.io/contact-us.
    +**
    +** GNU Lesser General Public License Usage
    +** Alternatively, this file may be used under the terms of the GNU Lesser
    +** General Public License version 3 as published by the Free Software
    +** Foundation and appearing in the file LICENSE.LGPL3 included in the
    +** packaging of this file. Please review the following information to
    +** ensure the GNU Lesser General Public License version 3 requirements
    +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
    +**
    +** GNU General Public License Usage
    +** Alternatively, this file may be used under the terms of the GNU
    +** General Public License version 2.0 or (at your option) the GNU General
    +** Public license version 3 or any later version approved by the KDE Free
    +** Qt Foundation. The licenses are as published by the Free Software
    +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
    +** included in the packaging of this file. Please review the following
    +** information to ensure the GNU General Public License requirements will
    +** be met: https://www.gnu.org/licenses/gpl-2.0.html and
    +** https://www.gnu.org/licenses/gpl-3.0.html.
    +**
    +** $QT_END_LICENSE$
    +**
    +****************************************************************************/
    +
    +#include 
    +#include "qtimezone.h"
    +#include "qtimezoneprivate_p.h"
    +
    +QT_BEGIN_NAMESPACE
    +
    +/*
    +    Private
    +
    +    Android implementation
    +*/
    +
    +// Create the system default time zone
    +QAndroidTimeZonePrivate::QAndroidTimeZonePrivate()
    +    : QTimeZonePrivate()
    +{
    +    // start with system time zone
    +    androidTimeZone = QJNIObjectPrivate::callStaticObjectMethod("java.util.TimeZone", "getDefault", "()Ljava/util/TimeZone;");
    +    init("UTC");
    +}
    +
    +// Create a named time zone
    +QAndroidTimeZonePrivate::QAndroidTimeZonePrivate(const QByteArray &ianaId)
    +    : QTimeZonePrivate()
    +{
    +    init(ianaId);
    +}
    +
    +QAndroidTimeZonePrivate::QAndroidTimeZonePrivate(const QAndroidTimeZonePrivate &other)
    +    : QTimeZonePrivate(other)
    +{
    +    androidTimeZone = other.androidTimeZone;
    +    m_id = other.id();
    +}
    +
    +QAndroidTimeZonePrivate::~QAndroidTimeZonePrivate()
    +{
    +}
    +
    +
    +void QAndroidTimeZonePrivate::init(const QByteArray &ianaId)
    +{
    +    QJNIObjectPrivate jo_ianaId = QJNIObjectPrivate::fromString( QString::fromUtf8(ianaId) );
    +    androidTimeZone = QJNIObjectPrivate::callStaticObjectMethod( "java.util.TimeZone", "getTimeZone", "(Ljava/lang/String;)Ljava/util/TimeZone;",  static_cast(jo_ianaId.object()) );
    +
    +    // Painfully, JNI gives us back a default zone object if it doesn't
    +    // recognize the name; so check for whether ianaId is a recognized name of
    +    // the zone object we got and ignore the zone if not.
    +    // Try checking ianaId against getID(), getDisplayName():
    +    QJNIObjectPrivate jname = androidTimeZone.callObjectMethod("getID", "()Ljava/lang/String;");
    +    bool found = (jname.toString().toUtf8() == ianaId);
    +    for (int style = 1; !found && style-- > 0;) {
    +        for (int dst = 1; !found && dst-- > 0;) {
    +            jname = androidTimeZone.callObjectMethod("getDisplayName", "(ZI;)Ljava/lang/String;",
    +                                                     bool(dst), style);
    +            found = (jname.toString().toUtf8() == ianaId);
    +        }
    +    }
    +
    +    if (!found)
    +        m_id.clear();
    +    else if (ianaId.isEmpty())
    +        m_id = systemTimeZoneId();
    +    else
    +        m_id = ianaId;
    +}
    +
    +QAndroidTimeZonePrivate *QAndroidTimeZonePrivate::clone() const
    +{
    +    return new QAndroidTimeZonePrivate(*this);
    +}
    +
    +
    +QString QAndroidTimeZonePrivate::displayName(QTimeZone::TimeType timeType, QTimeZone::NameType nameType,
    +                                             const QLocale &locale) const
    +{
    +    QString name;
    +
    +    if (androidTimeZone.isValid()) {
    +        jboolean daylightTime = (timeType == QTimeZone::DaylightTime);  // treat QTimeZone::GenericTime as QTimeZone::StandardTime
    +
    +        // treat all NameTypes as java TimeZone style LONG (value 1), except of course QTimeZone::ShortName which is style SHORT (value 0);
    +        jint style = (nameType == QTimeZone::ShortName ? 0 : 1);
    +
    +        QJNIObjectPrivate jlanguage = QJNIObjectPrivate::fromString(QLocale::languageToString(locale.language()));
    +        QJNIObjectPrivate jcountry = QJNIObjectPrivate::fromString(QLocale::countryToString(locale.country()));
    +        QJNIObjectPrivate jvariant = QJNIObjectPrivate::fromString(QLocale::scriptToString(locale.script()));
    +        QJNIObjectPrivate jlocale("java.util.Locale", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V", static_cast(jlanguage.object()), static_cast(jcountry.object()), static_cast(jvariant.object()));
    +
    +        QJNIObjectPrivate jname = androidTimeZone.callObjectMethod("getDisplayName", "(ZILjava/util/Locale;)Ljava/lang/String;", daylightTime, style, jlocale.object());
    +
    +        name = jname.toString();
    +    }
    +
    +    return name;
    +}
    +
    +QString QAndroidTimeZonePrivate::abbreviation(qint64 atMSecsSinceEpoch) const
    +{
    +    if ( isDaylightTime( atMSecsSinceEpoch ) )
    +        return displayName(QTimeZone::DaylightTime, QTimeZone::ShortName, QLocale() );
    +    else
    +        return displayName(QTimeZone::StandardTime, QTimeZone::ShortName, QLocale() );
    +}
    +
    +int QAndroidTimeZonePrivate::offsetFromUtc(qint64 atMSecsSinceEpoch) const
    +{
    +    // offsetFromUtc( ) is invoked when androidTimeZone may not yet be set at startup,
    +    // so a validity test is needed here
    +    if ( androidTimeZone.isValid() )
    +        // the java method getOffset() returns milliseconds, but QTimeZone returns seconds
    +        return androidTimeZone.callMethod( "getOffset", "(J)I", static_cast(atMSecsSinceEpoch) ) / 1000;
    +    else
    +        return 0;
    +}
    +
    +int QAndroidTimeZonePrivate::standardTimeOffset(qint64 atMSecsSinceEpoch) const
    +{
    +    // the java method does not use a reference time
    +    Q_UNUSED( atMSecsSinceEpoch );
    +    if ( androidTimeZone.isValid() )
    +        // the java method getRawOffset() returns milliseconds, but QTimeZone returns seconds
    +        return androidTimeZone.callMethod( "getRawOffset" ) / 1000;
    +    else
    +        return 0;
    +}
    +
    +int QAndroidTimeZonePrivate::daylightTimeOffset(qint64 atMSecsSinceEpoch) const
    +{
    +    return ( offsetFromUtc(atMSecsSinceEpoch) - standardTimeOffset(atMSecsSinceEpoch) );
    +}
    +
    +bool QAndroidTimeZonePrivate::hasDaylightTime() const
    +{
    +    if ( androidTimeZone.isValid() )
    +        /* note: the Java function only tests for future DST transtions, not past */
    +        return androidTimeZone.callMethod("useDaylightTime" );
    +    else
    +        return false;
    +}
    +
    +bool QAndroidTimeZonePrivate::isDaylightTime(qint64 atMSecsSinceEpoch) const
    +{
    +    if ( androidTimeZone.isValid() ) {
    +        QJNIObjectPrivate jDate( "java/util/Date", "(J)V", static_cast(atMSecsSinceEpoch) );
    +        return androidTimeZone.callMethod("inDaylightTime", "(Ljava/util/Date;)Z", jDate.object() );
    +    }
    +    else
    +        return false;
    +}
    +
    +QTimeZonePrivate::Data QAndroidTimeZonePrivate::data(qint64 forMSecsSinceEpoch) const
    +{
    +    if (androidTimeZone.isValid()) {
    +        Data data;
    +        data.atMSecsSinceEpoch = forMSecsSinceEpoch;
    +        data.standardTimeOffset = standardTimeOffset(forMSecsSinceEpoch);
    +        data.offsetFromUtc = offsetFromUtc(forMSecsSinceEpoch);
    +        data.daylightTimeOffset = data.offsetFromUtc - data.standardTimeOffset;
    +        data.abbreviation = abbreviation(forMSecsSinceEpoch);
    +        return data;
    +    } else {
    +        return invalidData();
    +    }
    +}
    +
    +bool QAndroidTimeZonePrivate::hasTransitions() const
    +{
    +    // java.util.TimeZone does not directly provide transitions
    +    return false;
    +}
    +
    +QTimeZonePrivate::Data QAndroidTimeZonePrivate::nextTransition(qint64 afterMSecsSinceEpoch) const
    +{
    +    // transitions not available on Android, so return an invalid data object
    +    Q_UNUSED( afterMSecsSinceEpoch );
    +    return invalidData();
    +}
    +
    +QTimeZonePrivate::Data QAndroidTimeZonePrivate::previousTransition(qint64 beforeMSecsSinceEpoch) const
    +{
    +    // transitions not available on Android, so return an invalid data object
    +    Q_UNUSED( beforeMSecsSinceEpoch );
    +    return invalidData();
    +}
    +
    +QByteArray QAndroidTimeZonePrivate::systemTimeZoneId() const
    +{
    +    QJNIObjectPrivate androidSystemTimeZone = QJNIObjectPrivate::callStaticObjectMethod("java.util.TimeZone", "getDefault", "()Ljava/util/TimeZone;");
    +    QJNIObjectPrivate systemTZIdAndroid = androidSystemTimeZone.callObjectMethod("getID");
    +    QByteArray systemTZid = systemTZIdAndroid.toString().toUtf8();
    +
    +    return systemTZid;
    +}
    +
    +QList QAndroidTimeZonePrivate::availableTimeZoneIds() const
    +{
    +    QList availableTimeZoneIdList;
    +    QJNIObjectPrivate androidAvailableIdList = QJNIObjectPrivate::callStaticObjectMethod("java.util.TimeZone", "getAvailableIDs", "()[Ljava/lang/String;");
    +
    +    QJNIEnvironmentPrivate jniEnv;
    +    int androidTZcount = jniEnv->GetArrayLength( static_cast(androidAvailableIdList.object()) );
    +
    +    // need separate jobject and QAndroidJniObject here so that we can delete (DeleteLocalRef) the reference to the jobject
    +    // (or else the JNI reference table fills after 512 entries from GetObjectArrayElement)
    +    jobject androidTZobject;
    +    QJNIObjectPrivate androidTZ;
    +    for (int i=0; iGetObjectArrayElement( static_cast( androidAvailableIdList.object() ), i );
    +        androidTZ = androidTZobject;
    +        availableTimeZoneIdList.append( androidTZ.toString().toUtf8() );
    +        jniEnv->DeleteLocalRef(androidTZobject);
    +    }
    +
    +    return availableTimeZoneIdList;
    +}
    +
    +QT_END_NAMESPACE
    diff --git a/src/corelib/time/qtimezoneprivate_data_p.h b/src/corelib/time/qtimezoneprivate_data_p.h
    new file mode 100644
    index 0000000000..40d6c972c2
    --- /dev/null
    +++ b/src/corelib/time/qtimezoneprivate_data_p.h
    @@ -0,0 +1,1257 @@
    +/****************************************************************************
    +**
    +** Copyright (C) 2013 John Layt 
    +** Contact: https://www.qt.io/licensing/
    +**
    +** This file is part of the QtCore module of the Qt Toolkit.
    +**
    +** $QT_BEGIN_LICENSE:LGPL$
    +** Commercial License Usage
    +** Licensees holding valid commercial Qt licenses may use this file in
    +** accordance with the commercial license agreement provided with the
    +** Software or, alternatively, in accordance with the terms contained in
    +** a written agreement between you and The Qt Company. For licensing terms
    +** and conditions see https://www.qt.io/terms-conditions. For further
    +** information use the contact form at https://www.qt.io/contact-us.
    +**
    +** GNU Lesser General Public License Usage
    +** Alternatively, this file may be used under the terms of the GNU Lesser
    +** General Public License version 3 as published by the Free Software
    +** Foundation and appearing in the file LICENSE.LGPL3 included in the
    +** packaging of this file. Please review the following information to
    +** ensure the GNU Lesser General Public License version 3 requirements
    +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
    +**
    +** GNU General Public License Usage
    +** Alternatively, this file may be used under the terms of the GNU
    +** General Public License version 2.0 or (at your option) the GNU General
    +** Public license version 3 or any later version approved by the KDE Free
    +** Qt Foundation. The licenses are as published by the Free Software
    +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
    +** included in the packaging of this file. Please review the following
    +** information to ensure the GNU General Public License requirements will
    +** be met: https://www.gnu.org/licenses/gpl-2.0.html and
    +** https://www.gnu.org/licenses/gpl-3.0.html.
    +**
    +** $QT_END_LICENSE$
    +**
    +****************************************************************************/
    +
    +
    +#ifndef QTIMEZONEPRIVATE_DATA_P_H
    +#define QTIMEZONEPRIVATE_DATA_P_H
    +
    +//
    +//  W A R N I N G
    +//  -------------
    +//
    +// This file is not part of the Qt API.  It exists for the convenience
    +// of internal files.  This header file may change from version to version
    +// without notice, or even be removed.
    +//
    +// We mean it.
    +//
    +
    +#include 
    +
    +QT_BEGIN_NAMESPACE
    +
    +/*
    +    Windows Zone ID support, included in default base class build so can be used on all platforms,
    +    e.g. an app running on Linux may need to communicate with a Windows Outlook server.  These
    +    tables can also be used to look-up Region Codes and UTC Offsets on platforms that don't directly
    +    support them., e.g. Mac does not support availableTimeZones() filtering by region or offset.
    +
    +    Another data table is provided for generic UTC+00:00 format time zones to be used as a
    +    fall-back if no system time zones are available (QT_NO_SYSTEMLOCALE is set) or for QDateTimes
    +    with a QT:Spec of OffsetFromUTC
    +
    +    These tables are automatically adapted from the CLDR supplemental/windowsZones.xml data file
    +    using a script in qtbase/util/locale_database.  Please do not edit this data directly.  In the
    +    future if ICU is made a hard dependency then the ICU resource can be used directly and this
    +    table removed
    +*/
    +
    +struct QZoneData {
    +    quint16 windowsIdKey;      // Windows ID Key
    +    quint16 country;           // Country of IANA ID's, AnyCountry means No Country
    +    quint16 ianaIdIndex;      // All IANA ID's for the Windows ID and Country, space separated
    +};
    +
    +struct QWindowsData {
    +    quint16 windowsIdKey;      // Windows ID Key
    +    quint16 windowsIdIndex;    // Windows ID Literal
    +    quint16 ianaIdIndex;      // Default IANA ID for the Windows ID
    +    qint32 offsetFromUtc;      // Standard Time Offset from UTC, used for quick look-ups
    +};
    +
    +struct QUtcData {
    +    quint16 ianaIdIndex;      // IANA ID's
    +    qint32 offsetFromUtc;      // Offset form UTC is seconds
    +};
    +
    +/*
    +    COPYRIGHT AND PERMISSION NOTICE
    +
    +    Copyright © 1991-2012 Unicode, Inc. All rights reserved. Distributed under
    +    the Terms of Use in http://www.unicode.org/copyright.html.
    +
    +    Permission is hereby granted, free of charge, to any person obtaining a
    +    copy of the Unicode data files and any associated documentation (the "Data
    +    Files") or Unicode software and any associated documentation (the "Software")
    +    to deal in the Data Files or Software without restriction, including without
    +    limitation the rights to use, copy, modify, merge, publish, distribute, and/or
    +    sell copies of the Data Files or Software, and to permit persons to whom the
    +    Data Files or Software are furnished to do so, provided that (a) the above
    +    copyright notice(s) and this permission notice appear with all copies of the
    +    Data Files or Software, (b) both the above copyright notice(s) and this
    +    permission notice appear in associated documentation, and (c) there is clear
    +    notice in each modified Data File or in the Software as well as in the
    +    documentation associated with the Data File(s) or Software that the data or
    +    software has been modified.
    +*/
    +
    +// GENERATED PART STARTS HERE
    +
    +/*
    +    This part of the file was generated on 2019-05-28 from the
    +    Common Locale Data Repository v35.1 supplemental/windowsZones.xml file $Revision: 14742 $
    +
    +    http://www.unicode.org/cldr/
    +
    +    Do not edit this code: run cldr2qtimezone.py on updated (or
    +    edited) CLDR data; see qtbase/util/locale_database/.
    +*/
    +
    +// Windows ID Key, Country Enum, IANA ID Index
    +static const QZoneData zoneDataTable[] = {
    +    {    131,   143,     0 }, // W. Mongolia Standard Time / Mongolia
    +    {    124,   112,    10 }, // UTC+12 / Kiribati
    +    {     52,    94,    25 }, // Haiti Standard Time / Haiti
    +    {     32,    44,    48 }, // China Standard Time / China
    +    {     95,   244,    62 }, // SA Western Standard Time / Saint Barthelemy
    +    {     25,   116,    84 }, // Central Asia Standard Time / Kyrgyzstan
    +    {     36,     8,    97 }, // E. Africa Standard Time / Antarctica
    +    {     33,   154,   114 }, // Chatham Islands Standard Time / New Zealand
    +    {     95,   144,   130 }, // SA Western Standard Time / Montserrat
    +    {     37,    13,   149 }, // E. Australia Standard Time / Australia
    +    {     61,     0,   187 }, // Line Islands Standard Time / AnyCountry
    +    {    132,   218,   198 }, // West Asia Standard Time / Turkmenistan
    +    {    122,    30,   212 }, // UTC-02 / Brazil
    +    {     24,    52,   228 }, // Central America Standard Time / Costa Rica
    +    {     36,    67,   247 }, // E. Africa Standard Time / Eritrea
    +    {    128,     8,   261 }, // W. Australia Standard Time / Antarctica
    +    {    101,   101,   278 }, // SE Asia Standard Time / Indonesia
    +    {     93,     8,   306 }, // SA Eastern Standard Time / Antarctica
    +    {      4,   178,   325 }, // Altai Standard Time / Russia
    +    {     95,   256,   338 }, // SA Western Standard Time / Sint Maarten
    +    {     95,    60,   360 }, // SA Western Standard Time / Dominica
    +    {    134,   167,   377 }, // West Pacific Standard Time / Papua New Guinea
    +    {     13,    13,   398 }, // AUS Eastern Standard Time / Australia
    +    {     69,   236,   435 }, // Morocco Standard Time / Western Sahara
    +    {     39,    30,   451 }, // E. South America Standard Time / Brazil
    +    {    124,   134,   469 }, // UTC+12 / Marshall Islands
    +    {    125,   112,   502 }, // UTC+13 / Kiribati
    +    {    103,   146,   520 }, // South Africa Standard Time / Mozambique
    +    {     94,    30,   534 }, // SA Pacific Standard Time / Brazil
    +    {     88,    74,   570 }, // Romance Standard Time / France
    +    {     71,    38,   583 }, // Mountain Standard Time / Canada
    +    {     72,   147,   657 }, // Myanmar Standard Time / Myanmar
    +    {     26,    30,   670 }, // Central Brazilian Standard Time / Brazil
    +    {    130,   123,   706 }, // W. Europe Standard Time / Liechtenstein
    +    {     46,    73,   719 }, // FLE Standard Time / Finland
    +    {     93,    70,   735 }, // SA Eastern Standard Time / Falkland Islands
    +    {     78,   159,   752 }, // Norfolk Standard Time / Norfolk Island
    +    {     53,     0,   768 }, // Hawaiian Standard Time / AnyCountry
    +    {     28,    54,   779 }, // Central European Standard Time / Croatia
    +    {     75,   150,   793 }, // Nepal Standard Time / Nepal
    +    {     46,    33,   807 }, // FLE Standard Time / Bulgaria
    +    {      6,   162,   820 }, // Arabian Standard Time / Oman
    +    {    132,   131,   832 }, // West Asia Standard Time / Maldives
    +    {     88,   197,   848 }, // Romance Standard Time / Spain
    +    {     50,    91,   875 }, // Greenwich Standard Time / Guinea
    +    {      5,   237,   890 }, // Arab Standard Time / Yemen
    +    {     92,   222,   900 }, // Russian Standard Time / Ukraine
    +    {    103,   204,   918 }, // South Africa Standard Time / Swaziland
    +    {    130,   203,   933 }, // W. Europe Standard Time / Svalbard And Jan Mayen Islands
    +    {      7,   103,   953 }, // Arabic Standard Time / Iraq
    +    {    119,   226,   966 }, // UTC-11 / United States Minor Outlying Islands
    +    {      5,   115,   981 }, // Arab Standard Time / Kuwait
    +    {     50,   189,   993 }, // Greenwich Standard Time / Sierra Leone
    +    {     31,     0,  1009 }, // Central Standard Time / AnyCountry
    +    {     53,    51,  1017 }, // Hawaiian Standard Time / Cook Islands
    +    {    129,    50,  1035 }, // W. Central Africa Standard Time / Congo Brazzaville
    +    {     64,    43,  1054 }, // Magallanes Standard Time / Chile
    +    {    119,     0,  1075 }, // UTC-11 / AnyCountry
    +    {     84,    38,  1086 }, // Pacific Standard Time / Canada
    +    {     22,    11,  1138 }, // Caucasus Standard Time / Armenia
    +    {    130,   142,  1151 }, // W. Europe Standard Time / Monaco
    +    {    103,   239,  1165 }, // South Africa Standard Time / Zambia
    +    {     46,   222,  1179 }, // FLE Standard Time / Ukraine
    +    {     87,   168,  1225 }, // Paraguay Standard Time / Paraguay
    +    {     57,   109,  1242 }, // Jordan Standard Time / Jordan
    +    {    109,    30,  1253 }, // Tocantins Standard Time / Brazil
    +    {     55,   102,  1271 }, // Iran Standard Time / Iran
    +    {    101,     8,  1283 }, // SE Asia Standard Time / Antarctica
    +    {     27,    57,  1300 }, // Central Europe Standard Time / Czech Republic
    +    {     95,   215,  1314 }, // SA Western Standard Time / Trinidad And Tobago
    +    {    103,    28,  1336 }, // South Africa Standard Time / Botswana
    +    {    132,     0,  1352 }, // West Asia Standard Time / AnyCountry
    +    {     94,    63,  1362 }, // SA Pacific Standard Time / Ecuador
    +    {     51,    85,  1380 }, // GTB Standard Time / Greece
    +    {     36,   128,  1394 }, // E. Africa Standard Time / Madagascar
    +    {     53,   226,  1414 }, // Hawaiian Standard Time / United States Minor Outlying Islands
    +    {     94,   107,  1431 }, // SA Pacific Standard Time / Jamaica
    +    {    104,   198,  1447 }, // Sri Lanka Standard Time / Sri Lanka
    +    {     27,   243,  1460 }, // Central Europe Standard Time / Serbia
    +    {     25,   110,  1476 }, // Central Asia Standard Time / Kazakhstan
    +    {    125,     0,  1502 }, // UTC+13 / AnyCountry
    +    {     94,    38,  1513 }, // SA Pacific Standard Time / Canada
    +    {     25,    31,  1535 }, // Central Asia Standard Time / British Indian Ocean Territory
    +    {    108,    13,  1549 }, // Tasmania Standard Time / Australia
    +    {     95,   174,  1583 }, // SA Western Standard Time / Puerto Rico
    +    {     95,   180,  1603 }, // SA Western Standard Time / Saint Kitts And Nevis
    +    {    130,   206,  1620 }, // W. Europe Standard Time / Switzerland
    +    {    117,   225,  1634 }, // US Eastern Standard Time / United States
    +    {     29,   140,  1701 }, // Central Pacific Standard Time / Micronesia
    +    {    120,    77,  1731 }, // UTC-09 / French Polynesia
    +    {    129,   156,  1747 }, // W. Central Africa Standard Time / Niger
    +    {    118,   139,  1761 }, // US Mountain Standard Time / Mexico
    +    {     36,   194,  1780 }, // E. Africa Standard Time / Somalia
    +    {    118,     0,  1797 }, // US Mountain Standard Time / AnyCountry
    +    {     10,    24,  1807 }, // Atlantic Standard Time / Bermuda
    +    {    103,   240,  1824 }, // South Africa Standard Time / Zimbabwe
    +    {     32,   126,  1838 }, // China Standard Time / Macau
    +    {    129,    66,  1849 }, // W. Central Africa Standard Time / Equatorial Guinea
    +    {     66,   137,  1863 }, // Mauritius Standard Time / Mauritius
    +    {     46,    68,  1880 }, // FLE Standard Time / Estonia
    +    {     50,   187,  1895 }, // Greenwich Standard Time / Senegal
    +    {    132,   110,  1908 }, // West Asia Standard Time / Kazakhstan
    +    {     25,    44,  1968 }, // Central Asia Standard Time / China
    +    {    130,   106,  1980 }, // W. Europe Standard Time / Italy
    +    {     48,   251,  1992 }, // GMT Standard Time / Isle Of Man
    +    {     36,   210,  2011 }, // E. Africa Standard Time / Tanzania
    +    {     10,    86,  2032 }, // Atlantic Standard Time / Greenland
    +    {    123,    86,  2046 }, // UTC / Greenland
    +    {     20,    38,  2067 }, // Canada Central Standard Time / Canada
    +    {     15,    86,  2104 }, // Azores Standard Time / Greenland
    +    {     69,   145,  2125 }, // Morocco Standard Time / Morocco
    +    {    115,   219,  2143 }, // Turks And Caicos Standard Time / Turks And Caicos Islands
    +    {     50,    80,  2162 }, // Greenwich Standard Time / Gambia
    +    {    129,    42,  2176 }, // W. Central Africa Standard Time / Chad
    +    {     56,   105,  2192 }, // Israel Standard Time / Israel
    +    {     64,     8,  2207 }, // Magallanes Standard Time / Antarctica
    +    {     12,    13,  2225 }, // Aus Central W. Standard Time / Australia
    +    {     24,   155,  2241 }, // Central America Standard Time / Nicaragua
    +    {    102,   170,  2257 }, // Singapore Standard Time / Philippines
    +    {    134,   160,  2269 }, // West Pacific Standard Time / Northern Mariana Islands
    +    {     43,    64,  2284 }, // Egypt Standard Time / Egypt
    +    {     88,    21,  2297 }, // Romance Standard Time / Belgium
    +    {     76,     8,  2313 }, // New Zealand Standard Time / Antarctica
    +    {     51,   177,  2332 }, // GTB Standard Time / Romania
    +    {    103,     0,  2349 }, // South Africa Standard Time / AnyCountry
    +    {     41,   225,  2359 }, // Eastern Standard Time / United States
    +    {    129,    23,  2516 }, // W. Central Africa Standard Time / Benin
    +    {     79,   178,  2534 }, // North Asia East Standard Time / Russia
    +    {    116,   143,  2547 }, // Ulaanbaatar Standard Time / Mongolia
    +    {    130,    14,  2580 }, // W. Europe Standard Time / Austria
    +    {     41,    38,  2594 }, // Eastern Standard Time / Canada
    +    {     95,   255,  2699 }, // SA Western Standard Time / Bonaire
    +    {    124,   149,  2718 }, // UTC+12 / Nauru
    +    {    134,     8,  2732 }, // West Pacific Standard Time / Antarctica
    +    {     63,   178,  2758 }, // Magadan Standard Time / Russia
    +    {    130,   161,  2771 }, // W. Europe Standard Time / Norway
    +    {    110,     0,  2783 }, // Tokyo Standard Time / AnyCountry
    +    {     24,    63,  2793 }, // Central America Standard Time / Ecuador
    +    {    103,    35,  2811 }, // South Africa Standard Time / Burundi
    +    {     10,    38,  2828 }, // Atlantic Standard Time / Canada
    +    {     29,     0,  2896 }, // Central Pacific Standard Time / AnyCountry
    +    {     95,    87,  2907 }, // SA Western Standard Time / Grenada
    +    {     29,   153,  2923 }, // Central Pacific Standard Time / New Caledonia
    +    {     42,   139,  2938 }, // Eastern Standard Time (Mexico) / Mexico
    +    {      2,   225,  2953 }, // Alaskan Standard Time / United States
    +    {     49,    86,  3029 }, // Greenland Standard Time / Greenland
    +    {     50,    92,  3045 }, // Greenwich Standard Time / Guinea Bissau
    +    {    130,   184,  3059 }, // W. Europe Standard Time / San Marino
    +    {     27,    98,  3077 }, // Central Europe Standard Time / Hungary
    +    {     24,    96,  3093 }, // Central America Standard Time / Honduras
    +    {     62,    13,  3113 }, // Lord Howe Standard Time / Australia
    +    {     36,     0,  3133 }, // E. Africa Standard Time / AnyCountry
    +    {    129,    79,  3143 }, // W. Central Africa Standard Time / Gabon
    +    {     95,   182,  3161 }, // SA Western Standard Time / Saint Vincent And The Grenadines
    +    {     48,   224,  3180 }, // GMT Standard Time / United Kingdom
    +    {     68,   227,  3194 }, // Montevideo Standard Time / Uruguay
    +    {    124,     0,  3213 }, // UTC+12 / AnyCountry
    +    {    130,   230,  3224 }, // W. Europe Standard Time / Vatican City State
    +    {     50,    99,  3239 }, // Greenwich Standard Time / Iceland
    +    {     34,    55,  3258 }, // Cuba Standard Time / Cuba
    +    {     41,    16,  3273 }, // Eastern Standard Time / Bahamas
    +    {    122,   196,  3288 }, // UTC-02 / South Georgia And The South Sandwich Islands
    +    {     24,    65,  3311 }, // Central America Standard Time / El Salvador
    +    {     31,   225,  3331 }, // Central Standard Time / United States
    +    {     95,     0,  3499 }, // SA Western Standard Time / AnyCountry
    +    {     94,   166,  3509 }, // SA Pacific Standard Time / Panama
    +    {     94,    47,  3524 }, // SA Pacific Standard Time / Colombia
    +    {     70,   139,  3539 }, // Mountain Standard Time (Mexico) / Mexico
    +    {    124,   220,  3574 }, // UTC+12 / Tuvalu
    +    {    130,    84,  3591 }, // W. Europe Standard Time / Gibraltar
    +    {     82,   178,  3608 }, // Omsk Standard Time / Russia
    +    {     60,   122,  3618 }, // Libya Standard Time / Libya
    +    {     25,     8,  3633 }, // Central Asia Standard Time / Antarctica
    +    {     95,    12,  3651 }, // SA Western Standard Time / Aruba
    +    {     67,   119,  3665 }, // Middle East Standard Time / Lebanon
    +    {    102,     0,  3677 }, // Singapore Standard Time / AnyCountry
    +    {     74,   148,  3687 }, // Namibia Standard Time / Namibia
    +    {    126,   231,  3703 }, // Venezuela Standard Time / Venezuela
    +    {     95,   234,  3719 }, // SA Western Standard Time / United States Virgin Islands
    +    {     21,     0,  3737 }, // Cape Verde Standard Time / AnyCountry
    +    {     95,     9,  3747 }, // SA Western Standard Time / Antigua And Barbuda
    +    {     94,   169,  3763 }, // SA Pacific Standard Time / Peru
    +    {     46,   248,  3776 }, // FLE Standard Time / Aland Islands
    +    {     50,   199,  3793 }, // Greenwich Standard Time / Saint Helena
    +    {    134,   140,  3812 }, // West Pacific Standard Time / Micronesia
    +    {    102,   190,  3825 }, // Singapore Standard Time / Singapore
    +    {     95,    61,  3840 }, // SA Western Standard Time / Dominican Republic
    +    {    103,   129,  3862 }, // South Africa Standard Time / Malawi
    +    {     30,   139,  3878 }, // Central Standard Time (Mexico) / Mexico
    +    {    102,   130,  3954 }, // Singapore Standard Time / Malaysia
    +    {     45,    72,  3985 }, // Fiji Standard Time / Fiji
    +    {    118,   225,  3998 }, // US Mountain Standard Time / United States
    +    {     17,    25,  4014 }, // Bangladesh Standard Time / Bhutan
    +    {    130,   133,  4027 }, // W. Europe Standard Time / Malta
    +    {     92,   178,  4040 }, // Russian Standard Time / Russia
    +    {     95,   135,  4084 }, // SA Western Standard Time / Martinique
    +    {     35,     0,  4103 }, // Dateline Standard Time / AnyCountry
    +    {    135,   178,  4114 }, // Yakutsk Standard Time / Russia
    +    {      1,     1,  4141 }, // Afghanistan Standard Time / Afghanistan
    +    {    123,     0,  4152 }, // UTC / AnyCountry
    +    {     31,   139,  4168 }, // Central Standard Time / Mexico
    +    {      6,     0,  4186 }, // Arabian Standard Time / AnyCountry
    +    {    101,    45,  4196 }, // SE Asia Standard Time / Christmas Island
    +    {     15,   173,  4213 }, // Azores Standard Time / Portugal
    +    {    129,     0,  4229 }, // W. Central Africa Standard Time / AnyCountry
    +    {     17,    18,  4239 }, // Bangladesh Standard Time / Bangladesh
    +    {     31,    38,  4250 }, // Central Standard Time / Canada
    +    {     94,     0,  4325 }, // SA Pacific Standard Time / AnyCountry
    +    {    125,   213,  4335 }, // UTC+13 / Tokelau
    +    {     73,   178,  4351 }, // N. Central Asia Standard Time / Russia
    +    {    133,   165,  4368 }, // West Bank Standard Time / Palestinian Territories
    +    {    114,   217,  4390 }, // Turkey Standard Time / Turkey
    +    {      3,   225,  4406 }, // Aleutian Standard Time / United States
    +    {    101,     0,  4419 }, // SE Asia Standard Time / AnyCountry
    +    {     71,   225,  4429 }, // Mountain Standard Time / United States
    +    {     36,    69,  4458 }, // E. Africa Standard Time / Ethiopia
    +    {    130,   151,  4477 }, // W. Europe Standard Time / Netherlands
    +    {     95,   245,  4494 }, // SA Western Standard Time / Saint Martin
    +    {     48,   173,  4510 }, // GMT Standard Time / Portugal
    +    {     46,   124,  4541 }, // FLE Standard Time / Lithuania
    +    {    130,    82,  4556 }, // W. Europe Standard Time / Germany
    +    {     65,    77,  4586 }, // Marquesas Standard Time / French Polynesia
    +    {     80,   178,  4604 }, // North Asia Standard Time / Russia
    +    {     61,   112,  4639 }, // Line Islands Standard Time / Kiribati
    +    {     96,   200,  4658 }, // Saint Pierre Standard Time / Saint Pierre And Miquelon
    +    {     48,   104,  4675 }, // GMT Standard Time / Ireland
    +    {      5,   186,  4689 }, // Arab Standard Time / Saudi Arabia
    +    {     83,    43,  4701 }, // Pacific SA Standard Time / Chile
    +    {     91,   178,  4718 }, // Russia Time Zone 11 / Russia
    +    {     36,    48,  4745 }, // E. Africa Standard Time / Comoros
    +    {     95,   152,  4759 }, // SA Western Standard Time / Cura Sao
    +    {     38,   141,  4775 }, // E. Europe Standard Time / Moldova
    +    {     24,    22,  4791 }, // Central America Standard Time / Belize
    +    {    103,   195,  4806 }, // South Africa Standard Time / South Africa
    +    {    127,   178,  4826 }, // Vladivostok Standard Time / Russia
    +    {    122,     0,  4857 }, // UTC-02 / AnyCountry
    +    {    106,   207,  4867 }, // Syria Standard Time / Syria
    +    {     93,    76,  4881 }, // SA Eastern Standard Time / French Guiana
    +    {     50,   136,  4897 }, // Greenwich Standard Time / Mauritania
    +    {     41,     0,  4915 }, // Eastern Standard Time / AnyCountry
    +    {     16,    30,  4923 }, // Bahia Standard Time / Brazil
    +    {     40,    43,  4937 }, // Easter Island Standard Time / Chile
    +    {     93,     0,  4952 }, // SA Eastern Standard Time / AnyCountry
    +    {      9,   178,  4962 }, // Astrakhan Standard Time / Russia
    +    {     95,    30,  4996 }, // SA Western Standard Time / Brazil
    +    {     18,    20,  5049 }, // Belarus Standard Time / Belarus
    +    {     95,   181,  5062 }, // SA Western Standard Time / Saint Lucia
    +    {    129,     6,  5079 }, // W. Central Africa Standard Time / Angola
    +    {    129,   157,  5093 }, // W. Central Africa Standard Time / Nigeria
    +    {    130,     5,  5106 }, // W. Europe Standard Time / Andorra
    +    {     58,   178,  5121 }, // Kaliningrad Standard Time / Russia
    +    {     71,     0,  5140 }, // Mountain Standard Time / AnyCountry
    +    {     95,     7,  5148 }, // SA Western Standard Time / Anguilla
    +    {    124,   235,  5165 }, // UTC+12 / Wallis And Futuna Islands
    +    {      6,   223,  5180 }, // Arabian Standard Time / United Arab Emirates
    +    {     94,    40,  5191 }, // SA Pacific Standard Time / Cayman Islands
    +    {    101,   211,  5206 }, // SE Asia Standard Time / Thailand
    +    {     29,   193,  5219 }, // Central Pacific Standard Time / Solomon Islands
    +    {     47,    81,  5239 }, // Georgian Standard Time / Georgia
    +    {    101,    36,  5252 }, // SE Asia Standard Time / Cambodia
    +    {    132,   228,  5268 }, // West Asia Standard Time / Uzbekistan
    +    {     51,    56,  5297 }, // GTB Standard Time / Cyprus
    +    {     95,    88,  5325 }, // SA Western Standard Time / Guadeloupe
    +    {    101,   232,  5344 }, // SE Asia Standard Time / Vietnam
    +    {    113,   178,  5356 }, // Transbaikal Standard Time / Russia
    +    {     50,   121,  5367 }, // Greenwich Standard Time / Liberia
    +    {     95,   233,  5383 }, // SA Western Standard Time / British Virgin Islands
    +    {    129,    49,  5399 }, // W. Central Africa Standard Time / Congo Kinshasa
    +    {     97,   178,  5415 }, // Sakhalin Standard Time / Russia
    +    {    124,   226,  5429 }, // UTC+12 / United States Minor Outlying Islands
    +    {     50,    83,  5442 }, // Greenwich Standard Time / Ghana
    +    {     76,   154,  5455 }, // New Zealand Standard Time / New Zealand
    +    {     23,    13,  5472 }, // Cen. Australia Standard Time / Australia
    +    {     53,    77,  5513 }, // Hawaiian Standard Time / French Polynesia
    +    {     50,    34,  5528 }, // Greenwich Standard Time / Burkina Faso
    +    {    132,    78,  5547 }, // West Asia Standard Time / French Southern Territories
    +    {    121,     0,  5564 }, // UTC-08 / AnyCountry
    +    {     27,     2,  5574 }, // Central Europe Standard Time / Albania
    +    {    107,   208,  5588 }, // Taipei Standard Time / Taiwan
    +    {     88,    58,  5600 }, // Romance Standard Time / Denmark
    +    {     36,   221,  5618 }, // E. Africa Standard Time / Uganda
    +    {     95,    19,  5633 }, // SA Western Standard Time / Barbados
    +    {     14,    15,  5650 }, // Azerbaijan Standard Time / Azerbaijan
    +    {     32,    97,  5660 }, // China Standard Time / Hong Kong
    +    {    110,   101,  5675 }, // Tokyo Standard Time / Indonesia
    +    {     53,   225,  5689 }, // Hawaiian Standard Time / United States
    +    {     36,   111,  5706 }, // E. Africa Standard Time / Kenya
    +    {    134,    89,  5721 }, // West Pacific Standard Time / Guam
    +    {     36,   254,  5734 }, // E. Africa Standard Time / South Sudan
    +    {     48,    71,  5746 }, // GMT Standard Time / Faroe Islands
    +    {     90,   178,  5762 }, // Russia Time Zone 10 / Russia
    +    {    119,   158,  5781 }, // UTC-11 / Niue
    +    {    129,     3,  5794 }, // W. Central Africa Standard Time / Algeria
    +    {    110,    62,  5809 }, // Tokyo Standard Time / East Timor
    +    {     93,    30,  5819 }, // SA Eastern Standard Time / Brazil
    +    {     27,   242,  5898 }, // Central Europe Standard Time / Montenegro
    +    {    129,    37,  5915 }, // W. Central Africa Standard Time / Cameroon
    +    {    101,   117,  5929 }, // SE Asia Standard Time / Laos
    +    {     85,   139,  5944 }, // Pacific Standard Time (Mexico) / Mexico
    +    {     50,   212,  5981 }, // Greenwich Standard Time / Togo
    +    {     46,   118,  5993 }, // FLE Standard Time / Latvia
    +    {     95,    38,  6005 }, // SA Western Standard Time / Canada
    +    {    132,   209,  6026 }, // West Asia Standard Time / Tajikistan
    +    {     77,    38,  6040 }, // Newfoundland Standard Time / Canada
    +    {    110,   108,  6057 }, // Tokyo Standard Time / Japan
    +    {     25,     0,  6068 }, // Central Asia Standard Time / AnyCountry
    +    {     28,    27,  6078 }, // Central European Standard Time / Bosnia And Herzegowina
    +    {     27,   191,  6094 }, // Central Europe Standard Time / Slovakia
    +    {     95,    93,  6112 }, // SA Western Standard Time / Guyana
    +    {     48,   197,  6127 }, // GMT Standard Time / Spain
    +    {     19,   167,  6143 }, // Bougainville Standard Time / Papua New Guinea
    +    {      5,    17,  6164 }, // Arab Standard Time / Bahrain
    +    {     24,    90,  6177 }, // Central America Standard Time / Guatemala
    +    {     95,    26,  6195 }, // SA Western Standard Time / Bolivia
    +    {     81,   113,  6210 }, // North Korea Standard Time / North Korea
    +    {    119,     4,  6225 }, // UTC-11 / American Samoa
    +    {     66,   176,  6243 }, // Mauritius Standard Time / Reunion
    +    {    103,   120,  6258 }, // South Africa Standard Time / Lesotho
    +    {     84,     0,  6272 }, // Pacific Standard Time / AnyCountry
    +    {    120,     0,  6280 }, // UTC-09 / AnyCountry
    +    {    129,   216,  6290 }, // W. Central Africa Standard Time / Tunisia
    +    {     99,   185,  6303 }, // Sao Tome Standard Time / Sao Tome And Principe
    +    {    100,   178,  6319 }, // Saratov Standard Time / Russia
    +    {    105,   201,  6334 }, // Sudan Standard Time / Sudan
    +    {     48,   252,  6350 }, // GMT Standard Time / Jersey
    +    {     29,    13,  6364 }, // Central Pacific Standard Time / Australia
    +    {     71,   139,  6385 }, // Mountain Standard Time / Mexico
    +    {     21,    39,  6401 }, // Cape Verde Standard Time / Cape Verde
    +    {    102,   101,  6421 }, // Singapore Standard Time / Indonesia
    +    {     27,   192,  6435 }, // Central Europe Standard Time / Slovenia
    +    {     48,    75,  6452 }, // GMT Standard Time / Guernsey
    +    {    132,     8,  6468 }, // West Asia Standard Time / Antarctica
    +    {      8,    10,  6486 }, // Argentina Standard Time / Argentina
    +    {     98,   183,  6759 }, // Samoa Standard Time / Samoa
    +    {    129,    41,  6772 }, // W. Central Africa Standard Time / Central African Republic
    +    {    111,   178,  6786 }, // Tomsk Standard Time / Russia
    +    {    110,   164,  6797 }, // Tokyo Standard Time / Palau
    +    {     11,    13,  6811 }, // AUS Central Standard Time / Australia
    +    {    121,   171,  6828 }, // UTC-08 / Pitcairn
    +    {    102,    32,  6845 }, // Singapore Standard Time / Brunei
    +    {    112,   214,  6857 }, // Tonga Standard Time / Tonga
    +    {     89,   178,  6875 }, // Russia Time Zone 3 / Russia
    +    {    128,    13,  6889 }, // W. Australia Standard Time / Australia
    +    {     28,   172,  6905 }, // Central European Standard Time / Poland
    +    {     72,    46,  6919 }, // Myanmar Standard Time / Cocos Islands
    +    {     66,   188,  6932 }, // Mauritius Standard Time / Seychelles
    +    {     84,   225,  6944 }, // Pacific Standard Time / United States
    +    {     54,   100,  6983 }, // India Standard Time / India
    +    {     50,    53,  6997 }, // Greenwich Standard Time / Ivory Coast
    +    {     24,     0,  7012 }, // Central America Standard Time / AnyCountry
    +    {     29,   229,  7022 }, // Central Pacific Standard Time / Vanuatu
    +    {    130,   125,  7036 }, // W. Europe Standard Time / Luxembourg
    +    {     50,   132,  7054 }, // Greenwich Standard Time / Mali
    +    {    103,   179,  7068 }, // South Africa Standard Time / Rwanda
    +    {      5,   175,  7082 }, // Arab Standard Time / Qatar
    +    {     86,   163,  7093 }, // Pakistan Standard Time / Pakistan
    +    {    134,     0,  7106 }, // West Pacific Standard Time / AnyCountry
    +    {     36,    59,  7117 }, // E. Africa Standard Time / Djibouti
    +    {     44,   178,  7133 }, // Ekaterinburg Standard Time / Russia
    +    {    118,    38,  7152 }, // US Mountain Standard Time / Canada
    +    {     36,   138,  7209 }, // E. Africa Standard Time / Mayotte
    +    {     28,   127,  7224 }, // Central European Standard Time / Macedonia
    +    {     59,   114,  7238 }, // Korea Standard Time / South Korea
    +    {     93,   202,  7249 }, // SA Eastern Standard Time / Suriname
    +    {    130,   205,  7268 }, // W. Europe Standard Time / Sweden
    +    {    103,    49,  7285 }, // South Africa Standard Time / Congo Kinshasa
    +    {      0,     0,     0 } // Trailing zeroes
    +};
    +
    +// Windows ID Key, Windows ID Index, IANA ID Index, UTC Offset
    +static const QWindowsData windowsDataTable[] = {
    +    {      1,     0,  4141, 16200 }, // Afghanistan Standard Time
    +    {      2,    26,  7303,-32400 }, // Alaskan Standard Time
    +    {      3,    48,  4406,-36000 }, // Aleutian Standard Time
    +    {      4,    71,   325, 25200 }, // Altai Standard Time
    +    {      5,    91,  4689, 10800 }, // Arab Standard Time
    +    {      6,   110,  5180, 14400 }, // Arabian Standard Time
    +    {      7,   132,   953, 10800 }, // Arabic Standard Time
    +    {      8,   153,  7321,-10800 }, // Argentina Standard Time
    +    {      9,   177,  7342, 14400 }, // Astrakhan Standard Time
    +    {     10,   201,  7359,-14400 }, // Atlantic Standard Time
    +    {     11,   224,  6811, 34200 }, // AUS Central Standard Time
    +    {     12,   250,  2225, 31500 }, // Aus Central W. Standard Time
    +    {     13,   279,  7375, 36000 }, // AUS Eastern Standard Time
    +    {     14,   305,  5650, 14400 }, // Azerbaijan Standard Time
    +    {     15,   330,  4213, -3600 }, // Azores Standard Time
    +    {     16,   351,  4923,-10800 }, // Bahia Standard Time
    +    {     17,   371,  4239, 21600 }, // Bangladesh Standard Time
    +    {     18,   396,  5049, 10800 }, // Belarus Standard Time
    +    {     19,   418,  6143, 39600 }, // Bougainville Standard Time
    +    {     20,   445,  7392,-21600 }, // Canada Central Standard Time
    +    {     21,   474,  6401, -3600 }, // Cape Verde Standard Time
    +    {     22,   499,  1138, 14400 }, // Caucasus Standard Time
    +    {     23,   522,  7407, 34200 }, // Cen. Australia Standard Time
    +    {     24,   551,  6177,-21600 }, // Central America Standard Time
    +    {     25,   581,  7426, 21600 }, // Central Asia Standard Time
    +    {     26,   608,  7438,-14400 }, // Central Brazilian Standard Time
    +    {     27,   640,  3077,  3600 }, // Central Europe Standard Time
    +    {     28,   669,  6905,  3600 }, // Central European Standard Time
    +    {     29,   700,  5219, 39600 }, // Central Pacific Standard Time
    +    {     30,   730,  7453,-21600 }, // Central Standard Time (Mexico)
    +    {     31,   761,  7473,-21600 }, // Central Standard Time
    +    {     32,   783,    48, 28800 }, // China Standard Time
    +    {     33,   803,   114, 45900 }, // Chatham Islands Standard Time
    +    {     34,   833,  3258,-18000 }, // Cuba Standard Time
    +    {     35,   852,  4103,-43200 }, // Dateline Standard Time
    +    {     36,   875,  5706, 10800 }, // E. Africa Standard Time
    +    {     37,   899,  7489, 36000 }, // E. Australia Standard Time
    +    {     38,   926,  4775,  7200 }, // E. Europe Standard Time
    +    {     39,   950,   451,-10800 }, // E. South America Standard Time
    +    {     40,   981,  4937,-21600 }, // Easter Island Standard Time
    +    {     41,  1009,  7508,-18000 }, // Eastern Standard Time
    +    {     42,  1031,  2938,-18000 }, // Eastern Standard Time (Mexico)
    +    {     43,  1062,  2284,  7200 }, // Egypt Standard Time
    +    {     44,  1082,  7133, 18000 }, // Ekaterinburg Standard Time
    +    {     45,  1109,  3985, 43200 }, // Fiji Standard Time
    +    {     46,  1128,  7525,  7200 }, // FLE Standard Time
    +    {     47,  1146,  5239, 14400 }, // Georgian Standard Time
    +    {     48,  1169,  3180,     0 }, // GMT Standard Time
    +    {     49,  1187,  3029,-10800 }, // Greenland Standard Time
    +    {     50,  1211,  3239,     0 }, // Greenwich Standard Time
    +    {     51,  1235,  2332,  7200 }, // GTB Standard Time
    +    {     52,  1253,    25,-18000 }, // Haiti Standard Time
    +    {     53,  1273,  5689,-36000 }, // Hawaiian Standard Time
    +    {     54,  1296,  6983, 19800 }, // India Standard Time
    +    {     55,  1316,  1271, 12600 }, // Iran Standard Time
    +    {     56,  1335,  2192,  7200 }, // Israel Standard Time
    +    {     57,  1356,  1242,  7200 }, // Jordan Standard Time
    +    {     58,  1377,  5121,  7200 }, // Kaliningrad Standard Time
    +    {     59,  1403,  7238, 32400 }, // Korea Standard Time
    +    {     60,  1423,  3618,  7200 }, // Libya Standard Time
    +    {     61,  1443,  4639, 50400 }, // Line Islands Standard Time
    +    {     62,  1470,  3113, 37800 }, // Lord Howe Standard Time
    +    {     63,  1494,  2758, 36000 }, // Magadan Standard Time
    +    {     64,  1516,  1054,-10800 }, // Magallanes Standard Time
    +    {     65,  1541,  4586,-34200 }, // Marquesas Standard Time
    +    {     66,  1565,  1863, 14400 }, // Mauritius Standard Time
    +    {     67,  1589,  3665,  7200 }, // Middle East Standard Time
    +    {     68,  1615,  3194,-10800 }, // Montevideo Standard Time
    +    {     69,  1640,  2125,     0 }, // Morocco Standard Time
    +    {     70,  1662,  7537,-25200 }, // Mountain Standard Time (Mexico)
    +    {     71,  1694,  7555,-25200 }, // Mountain Standard Time
    +    {     72,  1717,   657, 23400 }, // Myanmar Standard Time
    +    {     73,  1739,  4351, 21600 }, // N. Central Asia Standard Time
    +    {     74,  1769,  3687,  3600 }, // Namibia Standard Time
    +    {     75,  1791,   793, 20700 }, // Nepal Standard Time
    +    {     76,  1811,  5455, 43200 }, // New Zealand Standard Time
    +    {     77,  1837,  6040,-12600 }, // Newfoundland Standard Time
    +    {     78,  1864,   752, 39600 }, // Norfolk Standard Time
    +    {     79,  1886,  2534, 28800 }, // North Asia East Standard Time
    +    {     80,  1916,  7570, 25200 }, // North Asia Standard Time
    +    {     81,  1941,  6210, 30600 }, // North Korea Standard Time
    +    {     82,  1967,  3608, 21600 }, // Omsk Standard Time
    +    {     83,  1986,  4701,-10800 }, // Pacific SA Standard Time
    +    {     84,  2011,  7587,-28800 }, // Pacific Standard Time
    +    {     85,  2033,  7607,-28800 }, // Pacific Standard Time (Mexico)
    +    {     86,  2064,  7093, 18000 }, // Pakistan Standard Time
    +    {     87,  2087,  1225,-14400 }, // Paraguay Standard Time
    +    {     88,  2110,   570,  3600 }, // Romance Standard Time
    +    {     89,  2132,  6875, 14400 }, // Russia Time Zone 3
    +    {     90,  2151,  5762, 39600 }, // Russia Time Zone 10
    +    {     91,  2171,  7623, 43200 }, // Russia Time Zone 11
    +    {     92,  2191,  7638, 10800 }, // Russian Standard Time
    +    {     93,  2213,  4881,-10800 }, // SA Eastern Standard Time
    +    {     94,  2238,  3524,-18000 }, // SA Pacific Standard Time
    +    {     95,  2263,  6195,-14400 }, // SA Western Standard Time
    +    {     96,  2288,  4658,-10800 }, // Saint Pierre Standard Time
    +    {     97,  2315,  5415, 39600 }, // Sakhalin Standard Time
    +    {     98,  2338,  6759, 46800 }, // Samoa Standard Time
    +    {     99,  2358,  6303,     0 }, // Sao Tome Standard Time
    +    {    100,  2381,  6319, 14400 }, // Saratov Standard Time
    +    {    101,  2403,  5206, 25200 }, // SE Asia Standard Time
    +    {    102,  2425,  3825, 28800 }, // Singapore Standard Time
    +    {    103,  2449,  4806,  7200 }, // South Africa Standard Time
    +    {    104,  2476,  1447, 19800 }, // Sri Lanka Standard Time
    +    {    105,  2500,  6334,  7200 }, // Sudan Standard Time
    +    {    106,  2520,  4867,  7200 }, // Syria Standard Time
    +    {    107,  2540,  5588, 28800 }, // Taipei Standard Time
    +    {    108,  2561,  7652, 36000 }, // Tasmania Standard Time
    +    {    109,  2584,  1253,-10800 }, // Tocantins Standard Time
    +    {    110,  2608,  6057, 32400 }, // Tokyo Standard Time
    +    {    111,  2628,  6786, 25200 }, // Tomsk Standard Time
    +    {    112,  2648,  6857, 46800 }, // Tonga Standard Time
    +    {    113,  2668,  5356, 32400 }, // Transbaikal Standard Time
    +    {    114,  2694,  4390,  7200 }, // Turkey Standard Time
    +    {    115,  2715,  2143,-14400 }, // Turks And Caicos Standard Time
    +    {    116,  2746,  7669, 28800 }, // Ulaanbaatar Standard Time
    +    {    117,  2772,  7686,-18000 }, // US Eastern Standard Time
    +    {    118,  2797,  3998,-25200 }, // US Mountain Standard Time
    +    {    119,  2823,  1075,-39600 }, // UTC-11
    +    {    120,  2830,  6280,-32400 }, // UTC-09
    +    {    121,  2837,  5564,-28800 }, // UTC-08
    +    {    122,  2844,  4857, -7200 }, // UTC-02
    +    {    123,  2851,  7707,     0 }, // UTC
    +    {    124,  2855,  3213, 43200 }, // UTC+12
    +    {    125,  2862,  1502, 46800 }, // UTC+13
    +    {    126,  2869,  3703,-16200 }, // Venezuela Standard Time
    +    {    127,  2893,  7715, 36000 }, // Vladivostok Standard Time
    +    {    128,  2919,  6889, 28800 }, // W. Australia Standard Time
    +    {    129,  2946,  5093,  3600 }, // W. Central Africa Standard Time
    +    {    130,  2978,  7732,  3600 }, // W. Europe Standard Time
    +    {    131,  3002,     0, 25200 }, // W. Mongolia Standard Time
    +    {    132,  3028,  7746, 18000 }, // West Asia Standard Time
    +    {    133,  3052,  7760,  7200 }, // West Bank Standard Time
    +    {    134,  3076,   377, 36000 }, // West Pacific Standard Time
    +    {    135,  3103,  7772, 32400 }, // Yakutsk Standard Time
    +    {      0,     0,     0,     0 } // Trailing zeroes
    +};
    +
    +// IANA ID Index, UTC Offset
    +static const QUtcData utcDataTable[] = {
    +    {   7785,     0 }, // UTC
    +    {   7789,-50400 }, // UTC-14:00
    +    {   7799,-46800 }, // UTC-13:00
    +    {   7809,-43200 }, // UTC-12:00
    +    {   7819,-39600 }, // UTC-11:00
    +    {   7829,-36000 }, // UTC-10:00
    +    {   7839,-32400 }, // UTC-09:00
    +    {   7849,-28800 }, // UTC-08:00
    +    {   7859,-25200 }, // UTC-07:00
    +    {   7869,-21600 }, // UTC-06:00
    +    {   7879,-18000 }, // UTC-05:00
    +    {   7889,-16200 }, // UTC-04:30
    +    {   7899,-14400 }, // UTC-04:00
    +    {   7909,-12600 }, // UTC-03:30
    +    {   7919,-10800 }, // UTC-03:00
    +    {   7929, -7200 }, // UTC-02:00
    +    {   7939, -3600 }, // UTC-01:00
    +    {   7949,     0 }, // UTC-00:00
    +    {   7959,     0 }, // UTC+00:00
    +    {   7969,  3600 }, // UTC+01:00
    +    {   7979,  7200 }, // UTC+02:00
    +    {   7989, 10800 }, // UTC+03:00
    +    {   7999, 12600 }, // UTC+03:30
    +    {   8009, 14400 }, // UTC+04:00
    +    {   8019, 16200 }, // UTC+04:30
    +    {   8029, 18000 }, // UTC+05:00
    +    {   8039, 19800 }, // UTC+05:30
    +    {   8049, 20700 }, // UTC+05:45
    +    {   8059, 21600 }, // UTC+06:00
    +    {   8069, 23400 }, // UTC+06:30
    +    {   8079, 25200 }, // UTC+07:00
    +    {   8089, 28800 }, // UTC+08:00
    +    {   8099, 30600 }, // UTC+08:30
    +    {   8109, 32400 }, // UTC+09:00
    +    {   8119, 34200 }, // UTC+09:30
    +    {   8129, 36000 }, // UTC+10:00
    +    {   8139, 39600 }, // UTC+11:00
    +    {   8149, 43200 }, // UTC+12:00
    +    {   8159, 46800 }, // UTC+13:00
    +    {   8169, 50400 }, // UTC+14:00
    +    {     0,      0 } // Trailing zeroes
    +};
    +
    +static const char windowsIdData[] = {
    +0x41, 0x66, 0x67, 0x68, 0x61, 0x6e, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
    +0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x6c, 0x61, 0x73, 0x6b, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
    +0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x6c, 0x65, 0x75, 0x74, 0x69, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61,
    +0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x6c, 0x74, 0x61, 0x69, 0x20, 0x53, 0x74, 0x61,
    +0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x72, 0x61, 0x62, 0x20, 0x53, 0x74, 0x61, 0x6e,
    +0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x72, 0x61, 0x62, 0x69, 0x61, 0x6e, 0x20, 0x53, 0x74,
    +0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x72, 0x61, 0x62, 0x69, 0x63, 0x20, 0x53,
    +0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69,
    +0x6e, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x73, 0x74,
    +0x72, 0x61, 0x6b, 0x68, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65,
    +0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54,
    +0x69, 0x6d, 0x65, 0x0, 0x41, 0x55, 0x53, 0x20, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x53, 0x74, 0x61, 0x6e,
    +0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x75, 0x73, 0x20, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61,
    +0x6c, 0x20, 0x57, 0x2e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41,
    +0x55, 0x53, 0x20, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
    +0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x7a, 0x65, 0x72, 0x62, 0x61, 0x69, 0x6a, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e,
    +0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x7a, 0x6f, 0x72, 0x65, 0x73, 0x20, 0x53, 0x74, 0x61,
    +0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x42, 0x61, 0x68, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61,
    +0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x42, 0x61, 0x6e, 0x67, 0x6c, 0x61, 0x64, 0x65, 0x73,
    +0x68, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x42, 0x65, 0x6c, 0x61,
    +0x72, 0x75, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x42, 0x6f,
    +0x75, 0x67, 0x61, 0x69, 0x6e, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
    +0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x20, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20,
    +0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x61, 0x70, 0x65, 0x20, 0x56,
    +0x65, 0x72, 0x64, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43,
    +0x61, 0x75, 0x63, 0x61, 0x73, 0x75, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d,
    +0x65, 0x0, 0x43, 0x65, 0x6e, 0x2e, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61,
    +0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41,
    +0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65,
    +0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
    +0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x42, 0x72, 0x61, 0x7a,
    +0x69, 0x6c, 0x69, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0,
    +0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
    +0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x45, 0x75, 0x72,
    +0x6f, 0x70, 0x65, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0,
    +0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53, 0x74, 0x61, 0x6e,
    +0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x53, 0x74,
    +0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x28, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x29,
    +0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
    +0x6d, 0x65, 0x0, 0x43, 0x68, 0x69, 0x6e, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
    +0x6d, 0x65, 0x0, 0x43, 0x68, 0x61, 0x74, 0x68, 0x61, 0x6d, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x53,
    +0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x75, 0x62, 0x61, 0x20, 0x53, 0x74,
    +0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x44, 0x61, 0x74, 0x65, 0x6c, 0x69, 0x6e, 0x65,
    +0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x2e, 0x20, 0x41, 0x66,
    +0x72, 0x69, 0x63, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45,
    +0x2e, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
    +0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x2e, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e,
    +0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x2e, 0x20, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x41,
    +0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65,
    +0x0, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
    +0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x53, 0x74, 0x61,
    +0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x53,
    +0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x28, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f,
    +0x29, 0x0, 0x45, 0x67, 0x79, 0x70, 0x74, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d,
    +0x65, 0x0, 0x45, 0x6b, 0x61, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x62, 0x75, 0x72, 0x67, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
    +0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x46, 0x69, 0x6a, 0x69, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
    +0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x46, 0x4c, 0x45, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
    +0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x47, 0x65, 0x6f, 0x72, 0x67, 0x69, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
    +0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x47, 0x4d, 0x54, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72,
    +0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x47, 0x72, 0x65, 0x65, 0x6e, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x74, 0x61,
    +0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x47, 0x72, 0x65, 0x65, 0x6e, 0x77, 0x69, 0x63, 0x68,
    +0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x47, 0x54, 0x42, 0x20, 0x53,
    +0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x48, 0x61, 0x69, 0x74, 0x69, 0x20, 0x53,
    +0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x48, 0x61, 0x77, 0x61, 0x69, 0x69, 0x61,
    +0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x49, 0x6e, 0x64, 0x69,
    +0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x49, 0x72, 0x61, 0x6e,
    +0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x49, 0x73, 0x72, 0x61, 0x65,
    +0x6c, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4a, 0x6f, 0x72, 0x64,
    +0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4b, 0x61, 0x6c,
    +0x69, 0x6e, 0x69, 0x6e, 0x67, 0x72, 0x61, 0x64, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
    +0x6d, 0x65, 0x0, 0x4b, 0x6f, 0x72, 0x65, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
    +0x6d, 0x65, 0x0, 0x4c, 0x69, 0x62, 0x79, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
    +0x6d, 0x65, 0x0, 0x4c, 0x69, 0x6e, 0x65, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e,
    +0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4c, 0x6f, 0x72, 0x64, 0x20, 0x48, 0x6f, 0x77, 0x65, 0x20,
    +0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x61, 0x67, 0x61, 0x64, 0x61,
    +0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x61, 0x67, 0x61,
    +0x6c, 0x6c, 0x61, 0x6e, 0x65, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65,
    +0x0, 0x4d, 0x61, 0x72, 0x71, 0x75, 0x65, 0x73, 0x61, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
    +0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x69, 0x75, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
    +0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x20, 0x45, 0x61, 0x73, 0x74,
    +0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x6f, 0x6e, 0x74, 0x65,
    +0x76, 0x69, 0x64, 0x65, 0x6f, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0,
    +0x4d, 0x6f, 0x72, 0x6f, 0x63, 0x63, 0x6f, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d,
    +0x65, 0x0, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
    +0x54, 0x69, 0x6d, 0x65, 0x20, 0x28, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x29, 0x0, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x61,
    +0x69, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x79, 0x61,
    +0x6e, 0x6d, 0x61, 0x72, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e,
    +0x2e, 0x20, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
    +0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x61, 0x6d, 0x69, 0x62, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61,
    +0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x65, 0x70, 0x61, 0x6c, 0x20, 0x53, 0x74, 0x61,
    +0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x65, 0x77, 0x20, 0x5a, 0x65, 0x61, 0x6c, 0x61,
    +0x6e, 0x64, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x65, 0x77,
    +0x66, 0x6f, 0x75, 0x6e, 0x64, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54,
    +0x69, 0x6d, 0x65, 0x0, 0x4e, 0x6f, 0x72, 0x66, 0x6f, 0x6c, 0x6b, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
    +0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x45, 0x61, 0x73,
    +0x74, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x6f, 0x72, 0x74,
    +0x68, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65,
    +0x0, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x4b, 0x6f, 0x72, 0x65, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72,
    +0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4f, 0x6d, 0x73, 0x6b, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
    +0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53, 0x41, 0x20, 0x53, 0x74, 0x61,
    +0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53,
    +0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
    +0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x28, 0x4d, 0x65, 0x78, 0x69,
    +0x63, 0x6f, 0x29, 0x0, 0x50, 0x61, 0x6b, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72,
    +0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x50, 0x61, 0x72, 0x61, 0x67, 0x75, 0x61, 0x79, 0x20, 0x53, 0x74, 0x61, 0x6e,
    +0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x52, 0x6f, 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x53, 0x74,
    +0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x52, 0x75, 0x73, 0x73, 0x69, 0x61, 0x20, 0x54,
    +0x69, 0x6d, 0x65, 0x20, 0x5a, 0x6f, 0x6e, 0x65, 0x20, 0x33, 0x0, 0x52, 0x75, 0x73, 0x73, 0x69, 0x61, 0x20, 0x54, 0x69,
    +0x6d, 0x65, 0x20, 0x5a, 0x6f, 0x6e, 0x65, 0x20, 0x31, 0x30, 0x0, 0x52, 0x75, 0x73, 0x73, 0x69, 0x61, 0x20, 0x54, 0x69,
    +0x6d, 0x65, 0x20, 0x5a, 0x6f, 0x6e, 0x65, 0x20, 0x31, 0x31, 0x0, 0x52, 0x75, 0x73, 0x73, 0x69, 0x61, 0x6e, 0x20, 0x53,
    +0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x41, 0x20, 0x45, 0x61, 0x73, 0x74,
    +0x65, 0x72, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x41,
    +0x20, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
    +0x6d, 0x65, 0x0, 0x53, 0x41, 0x20, 0x57, 0x65, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
    +0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x61, 0x69, 0x6e, 0x74, 0x20, 0x50, 0x69, 0x65, 0x72, 0x72, 0x65,
    +0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x61, 0x6b, 0x68, 0x61,
    +0x6c, 0x69, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x61,
    +0x6d, 0x6f, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x61,
    +0x6f, 0x20, 0x54, 0x6f, 0x6d, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65,
    +0x0, 0x53, 0x61, 0x72, 0x61, 0x74, 0x6f, 0x76, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
    +0x6d, 0x65, 0x0, 0x53, 0x45, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
    +0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
    +0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63,
    +0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x72, 0x69, 0x20,
    +0x4c, 0x61, 0x6e, 0x6b, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0,
    +0x53, 0x75, 0x64, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0,
    +0x53, 0x79, 0x72, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0,
    +0x54, 0x61, 0x69, 0x70, 0x65, 0x69, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65,
    +0x0, 0x54, 0x61, 0x73, 0x6d, 0x61, 0x6e, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54,
    +0x69, 0x6d, 0x65, 0x0, 0x54, 0x6f, 0x63, 0x61, 0x6e, 0x74, 0x69, 0x6e, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
    +0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x6f, 0x6b, 0x79, 0x6f, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
    +0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x6f, 0x6d, 0x73, 0x6b, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
    +0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x6f, 0x6e, 0x67, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
    +0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x62, 0x61, 0x69, 0x6b, 0x61, 0x6c, 0x20,
    +0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x75, 0x72, 0x6b, 0x65, 0x79,
    +0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x75, 0x72, 0x6b, 0x73,
    +0x20, 0x41, 0x6e, 0x64, 0x20, 0x43, 0x61, 0x69, 0x63, 0x6f, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
    +0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x55, 0x6c, 0x61, 0x61, 0x6e, 0x62, 0x61, 0x61, 0x74, 0x61, 0x72, 0x20, 0x53, 0x74,
    +0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x55, 0x53, 0x20, 0x45, 0x61, 0x73, 0x74, 0x65,
    +0x72, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x55, 0x53, 0x20,
    +0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
    +0x6d, 0x65, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x31, 0x31, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x39, 0x0, 0x55, 0x54, 0x43,
    +0x2d, 0x30, 0x38, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x32, 0x0, 0x55, 0x54, 0x43, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31,
    +0x32, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x33, 0x0, 0x56, 0x65, 0x6e, 0x65, 0x7a, 0x75, 0x65, 0x6c, 0x61, 0x20, 0x53,
    +0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x56, 0x6c, 0x61, 0x64, 0x69, 0x76, 0x6f,
    +0x73, 0x74, 0x6f, 0x6b, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57,
    +0x2e, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
    +0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x2e, 0x20, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x66, 0x72,
    +0x69, 0x63, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x2e,
    +0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d,
    +0x65, 0x0, 0x57, 0x2e, 0x20, 0x4d, 0x6f, 0x6e, 0x67, 0x6f, 0x6c, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
    +0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x65, 0x73, 0x74, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x53, 0x74,
    +0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x65, 0x73, 0x74, 0x20, 0x42, 0x61, 0x6e,
    +0x6b, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x65, 0x73, 0x74,
    +0x20, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
    +0x6d, 0x65, 0x0, 0x59, 0x61, 0x6b, 0x75, 0x74, 0x73, 0x6b, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
    +0x54, 0x69, 0x6d, 0x65, 0x0
    +};
    +
    +static const char ianaIdData[] = {
    +0x41, 0x73, 0x69, 0x61, 0x2f, 0x48, 0x6f, 0x76, 0x64, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x54, 0x61,
    +0x72, 0x61, 0x77, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x2d, 0x61, 0x75,
    +0x2d, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x68, 0x61, 0x6e, 0x67, 0x68, 0x61,
    +0x69, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x42, 0x61, 0x72, 0x74, 0x68, 0x65, 0x6c,
    +0x65, 0x6d, 0x79, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x69, 0x73, 0x68, 0x6b, 0x65, 0x6b, 0x0, 0x41, 0x6e, 0x74,
    +0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x79, 0x6f, 0x77, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69,
    +0x63, 0x2f, 0x43, 0x68, 0x61, 0x74, 0x68, 0x61, 0x6d, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f,
    +0x6e, 0x74, 0x73, 0x65, 0x72, 0x72, 0x61, 0x74, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x42,
    +0x72, 0x69, 0x73, 0x62, 0x61, 0x6e, 0x65, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x4c, 0x69,
    +0x6e, 0x64, 0x65, 0x6d, 0x61, 0x6e, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x34, 0x0, 0x41, 0x73,
    +0x69, 0x61, 0x2f, 0x41, 0x73, 0x68, 0x67, 0x61, 0x62, 0x61, 0x74, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
    +0x4e, 0x6f, 0x72, 0x6f, 0x6e, 0x68, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x6f, 0x73, 0x74,
    +0x61, 0x5f, 0x52, 0x69, 0x63, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x73, 0x6d, 0x65, 0x72, 0x61,
    +0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x73, 0x65, 0x79, 0x0, 0x41, 0x73,
    +0x69, 0x61, 0x2f, 0x4a, 0x61, 0x6b, 0x61, 0x72, 0x74, 0x61, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x50, 0x6f, 0x6e, 0x74,
    +0x69, 0x61, 0x6e, 0x61, 0x6b, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x6f, 0x74,
    +0x68, 0x65, 0x72, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x72, 0x6e, 0x61, 0x75, 0x6c, 0x0, 0x41, 0x6d,
    +0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x77, 0x65, 0x72, 0x5f, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x65, 0x73, 0x0,
    +0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x6f, 0x6d, 0x69, 0x6e, 0x69, 0x63, 0x61, 0x0, 0x50, 0x61, 0x63,
    +0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x5f, 0x4d, 0x6f, 0x72, 0x65, 0x73, 0x62, 0x79, 0x0, 0x41, 0x75,
    +0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x53, 0x79, 0x64, 0x6e, 0x65, 0x79, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72,
    +0x61, 0x6c, 0x69, 0x61, 0x2f, 0x4d, 0x65, 0x6c, 0x62, 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63,
    +0x61, 0x2f, 0x45, 0x6c, 0x5f, 0x41, 0x61, 0x69, 0x75, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53,
    +0x61, 0x6f, 0x5f, 0x50, 0x61, 0x75, 0x6c, 0x6f, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4d, 0x61, 0x6a,
    +0x75, 0x72, 0x6f, 0x20, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4b, 0x77, 0x61, 0x6a, 0x61, 0x6c, 0x65, 0x69,
    +0x6e, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x45, 0x6e, 0x64, 0x65, 0x72, 0x62, 0x75, 0x72, 0x79, 0x0,
    +0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x70, 0x75, 0x74, 0x6f, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
    +0x61, 0x2f, 0x52, 0x69, 0x6f, 0x5f, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
    +0x2f, 0x45, 0x69, 0x72, 0x75, 0x6e, 0x65, 0x70, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x50, 0x61, 0x72,
    +0x69, 0x73, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45, 0x64, 0x6d, 0x6f, 0x6e, 0x74, 0x6f, 0x6e, 0x20,
    +0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x5f, 0x42, 0x61,
    +0x79, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x75, 0x76, 0x69, 0x6b, 0x20, 0x41, 0x6d, 0x65,
    +0x72, 0x69, 0x63, 0x61, 0x2f, 0x59, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6b, 0x6e, 0x69, 0x66, 0x65, 0x0, 0x41, 0x73, 0x69,
    +0x61, 0x2f, 0x52, 0x61, 0x6e, 0x67, 0x6f, 0x6f, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x75,
    +0x69, 0x61, 0x62, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x6d, 0x70, 0x6f, 0x5f, 0x47,
    +0x72, 0x61, 0x6e, 0x64, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, 0x61, 0x64, 0x75, 0x7a, 0x0, 0x45,
    +0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x48, 0x65, 0x6c, 0x73, 0x69, 0x6e, 0x6b, 0x69, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e,
    +0x74, 0x69, 0x63, 0x2f, 0x53, 0x74, 0x61, 0x6e, 0x6c, 0x65, 0x79, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f,
    +0x4e, 0x6f, 0x72, 0x66, 0x6f, 0x6c, 0x6b, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x31, 0x30, 0x0, 0x45,
    +0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x5a, 0x61, 0x67, 0x72, 0x65, 0x62, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61,
    +0x74, 0x6d, 0x61, 0x6e, 0x64, 0x75, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x6f, 0x66, 0x69, 0x61, 0x0,
    +0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x75, 0x73, 0x63, 0x61, 0x74, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4d,
    +0x61, 0x6c, 0x64, 0x69, 0x76, 0x65, 0x73, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x61, 0x64, 0x72, 0x69,
    +0x64, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x65, 0x75, 0x74, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63,
    +0x61, 0x2f, 0x43, 0x6f, 0x6e, 0x61, 0x6b, 0x72, 0x79, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x64, 0x65, 0x6e, 0x0,
    +0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x69, 0x6d, 0x66, 0x65, 0x72, 0x6f, 0x70, 0x6f, 0x6c, 0x0, 0x41, 0x66,
    +0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x62, 0x61, 0x62, 0x61, 0x6e, 0x65, 0x0, 0x41, 0x72, 0x63, 0x74, 0x69, 0x63, 0x2f,
    +0x4c, 0x6f, 0x6e, 0x67, 0x79, 0x65, 0x61, 0x72, 0x62, 0x79, 0x65, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61,
    +0x67, 0x68, 0x64, 0x61, 0x64, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4d, 0x69, 0x64, 0x77, 0x61, 0x79,
    +0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x75, 0x77, 0x61, 0x69, 0x74, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f,
    +0x46, 0x72, 0x65, 0x65, 0x74, 0x6f, 0x77, 0x6e, 0x0, 0x43, 0x53, 0x54, 0x36, 0x43, 0x44, 0x54, 0x0, 0x50, 0x61, 0x63,
    +0x69, 0x66, 0x69, 0x63, 0x2f, 0x52, 0x61, 0x72, 0x6f, 0x74, 0x6f, 0x6e, 0x67, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63,
    +0x61, 0x2f, 0x42, 0x72, 0x61, 0x7a, 0x7a, 0x61, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
    +0x61, 0x2f, 0x50, 0x75, 0x6e, 0x74, 0x61, 0x5f, 0x41, 0x72, 0x65, 0x6e, 0x61, 0x73, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47,
    +0x4d, 0x54, 0x2b, 0x31, 0x31, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x56, 0x61, 0x6e, 0x63, 0x6f, 0x75,
    +0x76, 0x65, 0x72, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x77, 0x73, 0x6f, 0x6e, 0x20, 0x41,
    +0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x57, 0x68, 0x69, 0x74, 0x65, 0x68, 0x6f, 0x72, 0x73, 0x65, 0x0, 0x41, 0x73,
    +0x69, 0x61, 0x2f, 0x59, 0x65, 0x72, 0x65, 0x76, 0x61, 0x6e, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x6f,
    +0x6e, 0x61, 0x63, 0x6f, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x75, 0x73, 0x61, 0x6b, 0x61, 0x0, 0x45,
    +0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4b, 0x69, 0x65, 0x76, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x55, 0x7a,
    +0x68, 0x67, 0x6f, 0x72, 0x6f, 0x64, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x5a, 0x61, 0x70, 0x6f, 0x72, 0x6f,
    +0x7a, 0x68, 0x79, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x73, 0x75, 0x6e, 0x63, 0x69, 0x6f,
    +0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x6d, 0x6d, 0x61, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
    +0x2f, 0x41, 0x72, 0x61, 0x67, 0x75, 0x61, 0x69, 0x6e, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x65, 0x68, 0x72,
    +0x61, 0x6e, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x76, 0x69, 0x73, 0x0,
    +0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x50, 0x72, 0x61, 0x67, 0x75, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
    +0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x5f, 0x6f, 0x66, 0x5f, 0x53, 0x70, 0x61, 0x69, 0x6e, 0x0, 0x41, 0x66, 0x72, 0x69,
    +0x63, 0x61, 0x2f, 0x47, 0x61, 0x62, 0x6f, 0x72, 0x6f, 0x6e, 0x65, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d,
    +0x35, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x75, 0x61, 0x79, 0x61, 0x71, 0x75, 0x69, 0x6c, 0x0,
    +0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x41, 0x74, 0x68, 0x65, 0x6e, 0x73, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e,
    +0x2f, 0x41, 0x6e, 0x74, 0x61, 0x6e, 0x61, 0x6e, 0x61, 0x72, 0x69, 0x76, 0x6f, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69,
    +0x63, 0x2f, 0x4a, 0x6f, 0x68, 0x6e, 0x73, 0x74, 0x6f, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a,
    +0x61, 0x6d, 0x61, 0x69, 0x63, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x43, 0x6f, 0x6c, 0x6f, 0x6d, 0x62, 0x6f, 0x0,
    +0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x65, 0x6c, 0x67, 0x72, 0x61, 0x64, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61,
    +0x2f, 0x41, 0x6c, 0x6d, 0x61, 0x74, 0x79, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x51, 0x6f, 0x73, 0x74, 0x61, 0x6e, 0x61,
    +0x79, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x33, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
    +0x2f, 0x43, 0x6f, 0x72, 0x61, 0x6c, 0x5f, 0x48, 0x61, 0x72, 0x62, 0x6f, 0x75, 0x72, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61,
    +0x6e, 0x2f, 0x43, 0x68, 0x61, 0x67, 0x6f, 0x73, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x48,
    +0x6f, 0x62, 0x61, 0x72, 0x74, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x43, 0x75, 0x72, 0x72,
    +0x69, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x75, 0x65, 0x72, 0x74, 0x6f, 0x5f, 0x52, 0x69,
    +0x63, 0x6f, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x4b, 0x69, 0x74, 0x74, 0x73, 0x0,
    +0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x5a, 0x75, 0x72, 0x69, 0x63, 0x68, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
    +0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x70, 0x6f, 0x6c, 0x69, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69,
    +0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x4d, 0x61, 0x72, 0x65, 0x6e, 0x67, 0x6f, 0x20, 0x41,
    +0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x56, 0x65, 0x76, 0x61, 0x79,
    +0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x6f, 0x6e, 0x61, 0x70, 0x65, 0x20, 0x50, 0x61, 0x63, 0x69,
    +0x66, 0x69, 0x63, 0x2f, 0x4b, 0x6f, 0x73, 0x72, 0x61, 0x65, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x47,
    +0x61, 0x6d, 0x62, 0x69, 0x65, 0x72, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x69, 0x61, 0x6d, 0x65, 0x79,
    +0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x65, 0x72, 0x6d, 0x6f, 0x73, 0x69, 0x6c, 0x6c, 0x6f, 0x0,
    +0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x67, 0x61, 0x64, 0x69, 0x73, 0x68, 0x75, 0x0, 0x45, 0x74, 0x63,
    +0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x37, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x42, 0x65, 0x72, 0x6d,
    +0x75, 0x64, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x72, 0x61, 0x72, 0x65, 0x0, 0x41, 0x73,
    +0x69, 0x61, 0x2f, 0x4d, 0x61, 0x63, 0x61, 0x75, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x6c, 0x61,
    +0x62, 0x6f, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x69, 0x75, 0x73, 0x0,
    +0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x54, 0x61, 0x6c, 0x6c, 0x69, 0x6e, 0x6e, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63,
    +0x61, 0x2f, 0x44, 0x61, 0x6b, 0x61, 0x72, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4f, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x73,
    +0x69, 0x61, 0x2f, 0x41, 0x71, 0x74, 0x61, 0x75, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x71, 0x74, 0x6f, 0x62, 0x65,
    +0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x74, 0x79, 0x72, 0x61, 0x75, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x51, 0x79,
    +0x7a, 0x79, 0x6c, 0x6f, 0x72, 0x64, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x72, 0x75, 0x6d, 0x71, 0x69, 0x0,
    +0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x52, 0x6f, 0x6d, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x49,
    +0x73, 0x6c, 0x65, 0x5f, 0x6f, 0x66, 0x5f, 0x4d, 0x61, 0x6e, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61,
    +0x72, 0x5f, 0x65, 0x73, 0x5f, 0x53, 0x61, 0x6c, 0x61, 0x61, 0x6d, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
    +0x54, 0x68, 0x75, 0x6c, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x6e, 0x6d, 0x61, 0x72,
    +0x6b, 0x73, 0x68, 0x61, 0x76, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x65, 0x67, 0x69, 0x6e,
    +0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x77, 0x69, 0x66, 0x74, 0x5f, 0x43, 0x75, 0x72, 0x72,
    +0x65, 0x6e, 0x74, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x62, 0x79,
    +0x73, 0x75, 0x6e, 0x64, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x73, 0x61, 0x62, 0x6c, 0x61, 0x6e,
    +0x63, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x72, 0x61, 0x6e, 0x64, 0x5f, 0x54, 0x75, 0x72,
    +0x6b, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x6e, 0x6a, 0x75, 0x6c, 0x0, 0x41, 0x66, 0x72, 0x69,
    +0x63, 0x61, 0x2f, 0x4e, 0x64, 0x6a, 0x61, 0x6d, 0x65, 0x6e, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4a, 0x65, 0x72,
    +0x75, 0x73, 0x61, 0x6c, 0x65, 0x6d, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x61,
    +0x6c, 0x6d, 0x65, 0x72, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x45, 0x75, 0x63, 0x6c, 0x61,
    +0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x75, 0x61, 0x0, 0x41, 0x73, 0x69,
    +0x61, 0x2f, 0x4d, 0x61, 0x6e, 0x69, 0x6c, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x53, 0x61, 0x69,
    +0x70, 0x61, 0x6e, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x69, 0x72, 0x6f, 0x0, 0x45, 0x75, 0x72,
    +0x6f, 0x70, 0x65, 0x2f, 0x42, 0x72, 0x75, 0x73, 0x73, 0x65, 0x6c, 0x73, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74,
    +0x69, 0x63, 0x61, 0x2f, 0x4d, 0x63, 0x4d, 0x75, 0x72, 0x64, 0x6f, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42,
    +0x75, 0x63, 0x68, 0x61, 0x72, 0x65, 0x73, 0x74, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x32, 0x0, 0x41,
    +0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x65, 0x77, 0x5f, 0x59, 0x6f, 0x72, 0x6b, 0x20, 0x41, 0x6d, 0x65, 0x72,
    +0x69, 0x63, 0x61, 0x2f, 0x44, 0x65, 0x74, 0x72, 0x6f, 0x69, 0x74, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
    +0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x50, 0x65, 0x74, 0x65, 0x72, 0x73, 0x62, 0x75, 0x72, 0x67, 0x20, 0x41,
    +0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x56, 0x69, 0x6e, 0x63, 0x65,
    +0x6e, 0x6e, 0x65, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61,
    +0x2f, 0x57, 0x69, 0x6e, 0x61, 0x6d, 0x61, 0x63, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x65, 0x6e,
    +0x74, 0x75, 0x63, 0x6b, 0x79, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x69, 0x63, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x41, 0x6d, 0x65,
    +0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x75, 0x69, 0x73, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0, 0x41, 0x66, 0x72, 0x69,
    +0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x6f, 0x2d, 0x4e, 0x6f, 0x76, 0x6f, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x49,
    +0x72, 0x6b, 0x75, 0x74, 0x73, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x6c, 0x61, 0x61, 0x6e, 0x62, 0x61, 0x61,
    +0x74, 0x61, 0x72, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x43, 0x68, 0x6f, 0x69, 0x62, 0x61, 0x6c, 0x73, 0x61, 0x6e, 0x0,
    +0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, 0x69, 0x65, 0x6e, 0x6e, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
    +0x61, 0x2f, 0x54, 0x6f, 0x72, 0x6f, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x71,
    +0x61, 0x6c, 0x75, 0x69, 0x74, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x72, 0x65,
    +0x61, 0x6c, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x69, 0x70, 0x69, 0x67, 0x6f, 0x6e, 0x20, 0x41,
    +0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x61, 0x6e, 0x67, 0x6e, 0x69, 0x72, 0x74, 0x75, 0x6e, 0x67, 0x20, 0x41,
    +0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x68, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x42, 0x61, 0x79, 0x0, 0x41,
    +0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x72, 0x61, 0x6c, 0x65, 0x6e, 0x64, 0x69, 0x6a, 0x6b, 0x0, 0x50, 0x61,
    +0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4e, 0x61, 0x75, 0x72, 0x75, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69,
    +0x63, 0x61, 0x2f, 0x44, 0x75, 0x6d, 0x6f, 0x6e, 0x74, 0x44, 0x55, 0x72, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0, 0x41, 0x73,
    +0x69, 0x61, 0x2f, 0x4d, 0x61, 0x67, 0x61, 0x64, 0x61, 0x6e, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4f, 0x73,
    +0x6c, 0x6f, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x39, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
    +0x2f, 0x47, 0x61, 0x6c, 0x61, 0x70, 0x61, 0x67, 0x6f, 0x73, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x75,
    +0x6a, 0x75, 0x6d, 0x62, 0x75, 0x72, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x6c, 0x69,
    +0x66, 0x61, 0x78, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x6c, 0x61, 0x63, 0x65, 0x5f, 0x42, 0x61,
    +0x79, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x6f, 0x6f, 0x73, 0x65, 0x5f, 0x42, 0x61, 0x79, 0x20,
    +0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x63, 0x74, 0x6f, 0x6e, 0x0, 0x45, 0x74, 0x63, 0x2f,
    +0x47, 0x4d, 0x54, 0x2d, 0x31, 0x31, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x72, 0x65, 0x6e, 0x61,
    +0x64, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4e, 0x6f, 0x75, 0x6d, 0x65, 0x61, 0x0, 0x41, 0x6d,
    +0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x6e, 0x63, 0x75, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
    +0x2f, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a,
    +0x75, 0x6e, 0x65, 0x61, 0x75, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x6d, 0x65, 0x20, 0x41,
    +0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x69, 0x74, 0x6b, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
    +0x2f, 0x59, 0x61, 0x6b, 0x75, 0x74, 0x61, 0x74, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x6f, 0x64,
    +0x74, 0x68, 0x61, 0x62, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x69, 0x73, 0x73, 0x61, 0x75, 0x0, 0x45,
    +0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x6e, 0x5f, 0x4d, 0x61, 0x72, 0x69, 0x6e, 0x6f, 0x0, 0x45, 0x75, 0x72,
    +0x6f, 0x70, 0x65, 0x2f, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, 0x73, 0x74, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
    +0x2f, 0x54, 0x65, 0x67, 0x75, 0x63, 0x69, 0x67, 0x61, 0x6c, 0x70, 0x61, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c,
    +0x69, 0x61, 0x2f, 0x4c, 0x6f, 0x72, 0x64, 0x5f, 0x48, 0x6f, 0x77, 0x65, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54,
    +0x2d, 0x33, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x69, 0x62, 0x72, 0x65, 0x76, 0x69, 0x6c, 0x6c, 0x65,
    +0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x56, 0x69, 0x6e, 0x63, 0x65, 0x6e, 0x74, 0x0,
    +0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x6f, 0x6e, 0x64, 0x6f, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
    +0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x65, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54,
    +0x2d, 0x31, 0x32, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, 0x61, 0x74, 0x69, 0x63, 0x61, 0x6e, 0x0, 0x41,
    +0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x52, 0x65, 0x79, 0x6b, 0x6a, 0x61, 0x76, 0x69, 0x6b, 0x0, 0x41, 0x6d,
    +0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x76, 0x61, 0x6e, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
    +0x2f, 0x4e, 0x61, 0x73, 0x73, 0x61, 0x75, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x53, 0x6f, 0x75,
    +0x74, 0x68, 0x5f, 0x47, 0x65, 0x6f, 0x72, 0x67, 0x69, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45,
    +0x6c, 0x5f, 0x53, 0x61, 0x6c, 0x76, 0x61, 0x64, 0x6f, 0x72, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43,
    +0x68, 0x69, 0x63, 0x61, 0x67, 0x6f, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61,
    +0x6e, 0x61, 0x2f, 0x4b, 0x6e, 0x6f, 0x78, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69,
    +0x61, 0x6e, 0x61, 0x2f, 0x54, 0x65, 0x6c, 0x6c, 0x5f, 0x43, 0x69, 0x74, 0x79, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
    +0x61, 0x2f, 0x4d, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x6e, 0x65, 0x65, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
    +0x4e, 0x6f, 0x72, 0x74, 0x68, 0x5f, 0x44, 0x61, 0x6b, 0x6f, 0x74, 0x61, 0x2f, 0x42, 0x65, 0x75, 0x6c, 0x61, 0x68, 0x20,
    +0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x5f, 0x44, 0x61, 0x6b, 0x6f, 0x74, 0x61,
    +0x2f, 0x43, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x72, 0x74,
    +0x68, 0x5f, 0x44, 0x61, 0x6b, 0x6f, 0x74, 0x61, 0x2f, 0x4e, 0x65, 0x77, 0x5f, 0x53, 0x61, 0x6c, 0x65, 0x6d, 0x0, 0x45,
    +0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x34, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x61, 0x6e,
    +0x61, 0x6d, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6f, 0x67, 0x6f, 0x74, 0x61, 0x0, 0x41,
    +0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x68, 0x75, 0x61, 0x68, 0x75, 0x61, 0x20, 0x41, 0x6d, 0x65,
    +0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x7a, 0x61, 0x74, 0x6c, 0x61, 0x6e, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69,
    +0x63, 0x2f, 0x46, 0x75, 0x6e, 0x61, 0x66, 0x75, 0x74, 0x69, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x47, 0x69,
    +0x62, 0x72, 0x61, 0x6c, 0x74, 0x61, 0x72, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4f, 0x6d, 0x73, 0x6b, 0x0, 0x41, 0x66,
    +0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x72, 0x69, 0x70, 0x6f, 0x6c, 0x69, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74,
    +0x69, 0x63, 0x61, 0x2f, 0x56, 0x6f, 0x73, 0x74, 0x6f, 0x6b, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41,
    +0x72, 0x75, 0x62, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x65, 0x69, 0x72, 0x75, 0x74, 0x0, 0x45, 0x74, 0x63,
    +0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x38, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x57, 0x69, 0x6e, 0x64, 0x68, 0x6f,
    +0x65, 0x6b, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x72, 0x61, 0x63, 0x61, 0x73, 0x0, 0x41,
    +0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x54, 0x68, 0x6f, 0x6d, 0x61, 0x73, 0x0, 0x45, 0x74, 0x63,
    +0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x31, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x6e, 0x74, 0x69, 0x67,
    +0x75, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x69, 0x6d, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f,
    +0x70, 0x65, 0x2f, 0x4d, 0x61, 0x72, 0x69, 0x65, 0x68, 0x61, 0x6d, 0x6e, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69,
    +0x63, 0x2f, 0x53, 0x74, 0x5f, 0x48, 0x65, 0x6c, 0x65, 0x6e, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f,
    +0x54, 0x72, 0x75, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x0,
    +0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x6f, 0x5f, 0x44, 0x6f, 0x6d, 0x69, 0x6e, 0x67,
    +0x6f, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6c, 0x61, 0x6e, 0x74, 0x79, 0x72, 0x65, 0x0, 0x41, 0x6d,
    +0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x5f, 0x43, 0x69, 0x74, 0x79, 0x20, 0x41, 0x6d,
    +0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x68, 0x69, 0x61, 0x5f, 0x42, 0x61, 0x6e, 0x64, 0x65, 0x72, 0x61, 0x73,
    +0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x72, 0x69, 0x64, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72,
    +0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x65, 0x79, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b,
    +0x75, 0x61, 0x6c, 0x61, 0x5f, 0x4c, 0x75, 0x6d, 0x70, 0x75, 0x72, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x75, 0x63,
    +0x68, 0x69, 0x6e, 0x67, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x46, 0x69, 0x6a, 0x69, 0x0, 0x41, 0x6d,
    +0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x68, 0x6f, 0x65, 0x6e, 0x69, 0x78, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54,
    +0x68, 0x69, 0x6d, 0x70, 0x68, 0x75, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x61, 0x6c, 0x74, 0x61, 0x0,
    +0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x6f, 0x73, 0x63, 0x6f, 0x77, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
    +0x2f, 0x4b, 0x69, 0x72, 0x6f, 0x76, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, 0x6f, 0x6c, 0x67, 0x6f, 0x67,
    +0x72, 0x61, 0x64, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x72, 0x74, 0x69, 0x6e, 0x69, 0x71,
    +0x75, 0x65, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x31, 0x32, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x59,
    +0x61, 0x6b, 0x75, 0x74, 0x73, 0x6b, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x68, 0x61, 0x6e, 0x64, 0x79, 0x67, 0x61,
    +0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x62, 0x75, 0x6c, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x20,
    +0x45, 0x74, 0x63, 0x2f, 0x55, 0x54, 0x43, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x74, 0x61,
    +0x6d, 0x6f, 0x72, 0x6f, 0x73, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x34, 0x0, 0x49, 0x6e, 0x64, 0x69,
    +0x61, 0x6e, 0x2f, 0x43, 0x68, 0x72, 0x69, 0x73, 0x74, 0x6d, 0x61, 0x73, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69,
    +0x63, 0x2f, 0x41, 0x7a, 0x6f, 0x72, 0x65, 0x73, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x0, 0x41,
    +0x73, 0x69, 0x61, 0x2f, 0x44, 0x68, 0x61, 0x6b, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x57, 0x69,
    +0x6e, 0x6e, 0x69, 0x70, 0x65, 0x67, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x61, 0x69, 0x6e, 0x79,
    +0x5f, 0x52, 0x69, 0x76, 0x65, 0x72, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x61, 0x6e, 0x6b, 0x69,
    +0x6e, 0x5f, 0x49, 0x6e, 0x6c, 0x65, 0x74, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x65, 0x73, 0x6f,
    +0x6c, 0x75, 0x74, 0x65, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x35, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66,
    +0x69, 0x63, 0x2f, 0x46, 0x61, 0x6b, 0x61, 0x6f, 0x66, 0x6f, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4e, 0x6f, 0x76, 0x6f,
    +0x73, 0x69, 0x62, 0x69, 0x72, 0x73, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x48, 0x65, 0x62, 0x72, 0x6f, 0x6e, 0x20,
    +0x41, 0x73, 0x69, 0x61, 0x2f, 0x47, 0x61, 0x7a, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x49, 0x73, 0x74,
    +0x61, 0x6e, 0x62, 0x75, 0x6c, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x64, 0x61, 0x6b, 0x0, 0x45,
    +0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x37, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x65, 0x6e,
    +0x76, 0x65, 0x72, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6f, 0x69, 0x73, 0x65, 0x0, 0x41, 0x66,
    +0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x64, 0x64, 0x69, 0x73, 0x5f, 0x41, 0x62, 0x61, 0x62, 0x61, 0x0, 0x45, 0x75, 0x72,
    +0x6f, 0x70, 0x65, 0x2f, 0x41, 0x6d, 0x73, 0x74, 0x65, 0x72, 0x64, 0x61, 0x6d, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
    +0x61, 0x2f, 0x4d, 0x61, 0x72, 0x69, 0x67, 0x6f, 0x74, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x69, 0x73,
    +0x62, 0x6f, 0x6e, 0x20, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x4d, 0x61, 0x64, 0x65, 0x69, 0x72, 0x61,
    +0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, 0x69, 0x6c, 0x6e, 0x69, 0x75, 0x73, 0x0, 0x45, 0x75, 0x72, 0x6f,
    +0x70, 0x65, 0x2f, 0x42, 0x65, 0x72, 0x6c, 0x69, 0x6e, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x75, 0x73,
    +0x69, 0x6e, 0x67, 0x65, 0x6e, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4d, 0x61, 0x72, 0x71, 0x75, 0x65,
    +0x73, 0x61, 0x73, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x72, 0x61, 0x73, 0x6e, 0x6f, 0x79, 0x61, 0x72, 0x73, 0x6b,
    +0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4e, 0x6f, 0x76, 0x6f, 0x6b, 0x75, 0x7a, 0x6e, 0x65, 0x74, 0x73, 0x6b, 0x0, 0x50,
    +0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4b, 0x69, 0x72, 0x69, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x0, 0x41, 0x6d,
    +0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x69, 0x71, 0x75, 0x65, 0x6c, 0x6f, 0x6e, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70,
    +0x65, 0x2f, 0x44, 0x75, 0x62, 0x6c, 0x69, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x52, 0x69, 0x79, 0x61, 0x64, 0x68,
    +0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x69, 0x61, 0x67, 0x6f, 0x0, 0x41, 0x73,
    +0x69, 0x61, 0x2f, 0x4b, 0x61, 0x6d, 0x63, 0x68, 0x61, 0x74, 0x6b, 0x61, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x6e,
    +0x61, 0x64, 0x79, 0x72, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x43, 0x6f, 0x6d, 0x6f, 0x72, 0x6f, 0x0, 0x41,
    +0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x75, 0x72, 0x61, 0x63, 0x61, 0x6f, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70,
    +0x65, 0x2f, 0x43, 0x68, 0x69, 0x73, 0x69, 0x6e, 0x61, 0x75, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42,
    +0x65, 0x6c, 0x69, 0x7a, 0x65, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a, 0x6f, 0x68, 0x61, 0x6e, 0x6e, 0x65,
    +0x73, 0x62, 0x75, 0x72, 0x67, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x56, 0x6c, 0x61, 0x64, 0x69, 0x76, 0x6f, 0x73, 0x74,
    +0x6f, 0x6b, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x73, 0x74, 0x2d, 0x4e, 0x65, 0x72, 0x61, 0x0, 0x45, 0x74, 0x63,
    +0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x32, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x61, 0x6d, 0x61, 0x73, 0x63, 0x75, 0x73,
    +0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x79, 0x65, 0x6e, 0x6e, 0x65, 0x0, 0x41, 0x66, 0x72,
    +0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x75, 0x61, 0x6b, 0x63, 0x68, 0x6f, 0x74, 0x74, 0x0, 0x45, 0x53, 0x54, 0x35, 0x45,
    +0x44, 0x54, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x68, 0x69, 0x61, 0x0, 0x50, 0x61, 0x63,
    +0x69, 0x66, 0x69, 0x63, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b,
    +0x33, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x41, 0x73, 0x74, 0x72, 0x61, 0x6b, 0x68, 0x61, 0x6e, 0x20, 0x45,
    +0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x55, 0x6c, 0x79, 0x61, 0x6e, 0x6f, 0x76, 0x73, 0x6b, 0x0, 0x41, 0x6d, 0x65, 0x72,
    +0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x6e, 0x61, 0x75, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42,
    +0x6f, 0x61, 0x5f, 0x56, 0x69, 0x73, 0x74, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72,
    +0x74, 0x6f, 0x5f, 0x56, 0x65, 0x6c, 0x68, 0x6f, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x69, 0x6e, 0x73,
    +0x6b, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x4c, 0x75, 0x63, 0x69, 0x61, 0x0, 0x41,
    +0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x75, 0x61, 0x6e, 0x64, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f,
    +0x4c, 0x61, 0x67, 0x6f, 0x73, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x41, 0x6e, 0x64, 0x6f, 0x72, 0x72, 0x61,
    +0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4b, 0x61, 0x6c, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x72, 0x61, 0x64, 0x0,
    +0x4d, 0x53, 0x54, 0x37, 0x4d, 0x44, 0x54, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x6e, 0x67, 0x75,
    +0x69, 0x6c, 0x6c, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x57, 0x61, 0x6c, 0x6c, 0x69, 0x73, 0x0,
    +0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x75, 0x62, 0x61, 0x69, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43,
    +0x61, 0x79, 0x6d, 0x61, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x6e, 0x67, 0x6b, 0x6f, 0x6b, 0x0, 0x50,
    +0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x47, 0x75, 0x61, 0x64, 0x61, 0x6c, 0x63, 0x61, 0x6e, 0x61, 0x6c, 0x0, 0x41,
    +0x73, 0x69, 0x61, 0x2f, 0x54, 0x62, 0x69, 0x6c, 0x69, 0x73, 0x69, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x50, 0x68, 0x6e,
    +0x6f, 0x6d, 0x5f, 0x50, 0x65, 0x6e, 0x68, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x73, 0x68, 0x6b, 0x65, 0x6e,
    +0x74, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x61, 0x6d, 0x61, 0x72, 0x6b, 0x61, 0x6e, 0x64, 0x0, 0x41, 0x73, 0x69,
    +0x61, 0x2f, 0x46, 0x61, 0x6d, 0x61, 0x67, 0x75, 0x73, 0x74, 0x61, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4e, 0x69, 0x63,
    +0x6f, 0x73, 0x69, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x75, 0x61, 0x64, 0x65, 0x6c, 0x6f,
    +0x75, 0x70, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x61, 0x69, 0x67, 0x6f, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61,
    +0x2f, 0x43, 0x68, 0x69, 0x74, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x72, 0x6f, 0x76,
    +0x69, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x6f, 0x72, 0x74, 0x6f, 0x6c, 0x61, 0x0, 0x41,
    +0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x69, 0x6e, 0x73, 0x68, 0x61, 0x73, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f,
    +0x53, 0x61, 0x6b, 0x68, 0x61, 0x6c, 0x69, 0x6e, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x57, 0x61, 0x6b,
    +0x65, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x63, 0x63, 0x72, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66,
    +0x69, 0x63, 0x2f, 0x41, 0x75, 0x63, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69,
    +0x61, 0x2f, 0x41, 0x64, 0x65, 0x6c, 0x61, 0x69, 0x64, 0x65, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61,
    +0x2f, 0x42, 0x72, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x48, 0x69, 0x6c, 0x6c, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
    +0x2f, 0x54, 0x61, 0x68, 0x69, 0x74, 0x69, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4f, 0x75, 0x61, 0x67, 0x61,
    +0x64, 0x6f, 0x75, 0x67, 0x6f, 0x75, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4b, 0x65, 0x72, 0x67, 0x75, 0x65,
    +0x6c, 0x65, 0x6e, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x38, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
    +0x2f, 0x54, 0x69, 0x72, 0x61, 0x6e, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x69, 0x70, 0x65, 0x69, 0x0,
    +0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x43, 0x6f, 0x70, 0x65, 0x6e, 0x68, 0x61, 0x67, 0x65, 0x6e, 0x0, 0x41, 0x66,
    +0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x61, 0x6d, 0x70, 0x61, 0x6c, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
    +0x2f, 0x42, 0x61, 0x72, 0x62, 0x61, 0x64, 0x6f, 0x73, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x6b, 0x75, 0x0,
    +0x41, 0x73, 0x69, 0x61, 0x2f, 0x48, 0x6f, 0x6e, 0x67, 0x5f, 0x4b, 0x6f, 0x6e, 0x67, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f,
    +0x4a, 0x61, 0x79, 0x61, 0x70, 0x75, 0x72, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x48, 0x6f, 0x6e,
    +0x6f, 0x6c, 0x75, 0x6c, 0x75, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x61, 0x69, 0x72, 0x6f, 0x62, 0x69,
    +0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x47, 0x75, 0x61, 0x6d, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61,
    +0x2f, 0x4a, 0x75, 0x62, 0x61, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x46, 0x61, 0x65, 0x72, 0x6f,
    +0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x72, 0x65, 0x64, 0x6e, 0x65, 0x6b, 0x6f, 0x6c, 0x79, 0x6d, 0x73, 0x6b,
    +0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4e, 0x69, 0x75, 0x65, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61,
    +0x2f, 0x41, 0x6c, 0x67, 0x69, 0x65, 0x72, 0x73, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x69, 0x6c, 0x69, 0x0, 0x41,
    +0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x46, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x65, 0x7a, 0x61, 0x20, 0x41, 0x6d, 0x65,
    +0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x65, 0x6c, 0x65, 0x6d, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d,
    +0x61, 0x63, 0x65, 0x69, 0x6f, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x65, 0x63, 0x69, 0x66, 0x65,
    +0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x61, 0x72, 0x65, 0x6d, 0x0, 0x45, 0x75,
    +0x72, 0x6f, 0x70, 0x65, 0x2f, 0x50, 0x6f, 0x64, 0x67, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63,
    +0x61, 0x2f, 0x44, 0x6f, 0x75, 0x61, 0x6c, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x56, 0x69, 0x65, 0x6e, 0x74, 0x69,
    +0x61, 0x6e, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x69, 0x6a, 0x75, 0x61, 0x6e, 0x61, 0x20,
    +0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x61, 0x5f, 0x49, 0x73, 0x61, 0x62, 0x65, 0x6c,
    +0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x6d, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f,
    +0x52, 0x69, 0x67, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6c, 0x61, 0x6e, 0x63, 0x2d, 0x53,
    +0x61, 0x62, 0x6c, 0x6f, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x75, 0x73, 0x68, 0x61, 0x6e, 0x62, 0x65, 0x0,
    +0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x4a, 0x6f, 0x68, 0x6e, 0x73, 0x0, 0x41, 0x73, 0x69,
    +0x61, 0x2f, 0x54, 0x6f, 0x6b, 0x79, 0x6f, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x36, 0x0, 0x45, 0x75,
    +0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x72, 0x61, 0x6a, 0x65, 0x76, 0x6f, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
    +0x2f, 0x42, 0x72, 0x61, 0x74, 0x69, 0x73, 0x6c, 0x61, 0x76, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
    +0x47, 0x75, 0x79, 0x61, 0x6e, 0x61, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x43, 0x61, 0x6e, 0x61,
    +0x72, 0x79, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x42, 0x6f, 0x75, 0x67, 0x61, 0x69, 0x6e, 0x76, 0x69,
    +0x6c, 0x6c, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x68, 0x72, 0x61, 0x69, 0x6e, 0x0, 0x41, 0x6d, 0x65,
    +0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x75, 0x61, 0x74, 0x65, 0x6d, 0x61, 0x6c, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69,
    +0x63, 0x61, 0x2f, 0x4c, 0x61, 0x5f, 0x50, 0x61, 0x7a, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x50, 0x79, 0x6f, 0x6e, 0x67,
    +0x79, 0x61, 0x6e, 0x67, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x61, 0x67, 0x6f, 0x5f, 0x50, 0x61,
    +0x67, 0x6f, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x52, 0x65, 0x75, 0x6e, 0x69, 0x6f, 0x6e, 0x0, 0x41, 0x66,
    +0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x73, 0x65, 0x72, 0x75, 0x0, 0x50, 0x53, 0x54, 0x38, 0x50, 0x44, 0x54, 0x0,
    +0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x39, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x75, 0x6e,
    +0x69, 0x73, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6f, 0x5f, 0x54, 0x6f, 0x6d, 0x65, 0x0, 0x45,
    +0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x72, 0x61, 0x74, 0x6f, 0x76, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61,
    +0x2f, 0x4b, 0x68, 0x61, 0x72, 0x74, 0x6f, 0x75, 0x6d, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4a, 0x65, 0x72,
    +0x73, 0x65, 0x79, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x63, 0x71, 0x75,
    +0x61, 0x72, 0x69, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4f, 0x6a, 0x69, 0x6e, 0x61, 0x67, 0x61,
    +0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x43, 0x61, 0x70, 0x65, 0x5f, 0x56, 0x65, 0x72, 0x64, 0x65,
    +0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x61, 0x6b, 0x61, 0x73, 0x73, 0x61, 0x72, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70,
    +0x65, 0x2f, 0x4c, 0x6a, 0x75, 0x62, 0x6c, 0x6a, 0x61, 0x6e, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x47,
    +0x75, 0x65, 0x72, 0x6e, 0x73, 0x65, 0x79, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x4d,
    +0x61, 0x77, 0x73, 0x6f, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x75, 0x65, 0x6e, 0x6f, 0x73,
    +0x5f, 0x41, 0x69, 0x72, 0x65, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e,
    +0x74, 0x69, 0x6e, 0x61, 0x2f, 0x4c, 0x61, 0x5f, 0x52, 0x69, 0x6f, 0x6a, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
    +0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x52, 0x69, 0x6f, 0x5f, 0x47, 0x61, 0x6c, 0x6c,
    +0x65, 0x67, 0x6f, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69,
    +0x6e, 0x61, 0x2f, 0x53, 0x61, 0x6c, 0x74, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67,
    +0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x5f, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x41, 0x6d, 0x65, 0x72,
    +0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x5f, 0x4c, 0x75,
    +0x69, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61,
    +0x2f, 0x54, 0x75, 0x63, 0x75, 0x6d, 0x61, 0x6e, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67,
    +0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x55, 0x73, 0x68, 0x75, 0x61, 0x69, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69,
    +0x63, 0x61, 0x2f, 0x43, 0x61, 0x74, 0x61, 0x6d, 0x61, 0x72, 0x63, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
    +0x2f, 0x43, 0x6f, 0x72, 0x64, 0x6f, 0x62, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a, 0x75, 0x6a,
    +0x75, 0x79, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x6e, 0x64, 0x6f, 0x7a, 0x61, 0x0, 0x50,
    +0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x41, 0x70, 0x69, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42,
    +0x61, 0x6e, 0x67, 0x75, 0x69, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x6f, 0x6d, 0x73, 0x6b, 0x0, 0x50, 0x61, 0x63,
    +0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x61, 0x6c, 0x61, 0x75, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61,
    +0x2f, 0x44, 0x61, 0x72, 0x77, 0x69, 0x6e, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x69, 0x74, 0x63,
    +0x61, 0x69, 0x72, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x72, 0x75, 0x6e, 0x65, 0x69, 0x0, 0x50, 0x61, 0x63,
    +0x69, 0x66, 0x69, 0x63, 0x2f, 0x54, 0x6f, 0x6e, 0x67, 0x61, 0x74, 0x61, 0x70, 0x75, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70,
    +0x65, 0x2f, 0x53, 0x61, 0x6d, 0x61, 0x72, 0x61, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x50,
    +0x65, 0x72, 0x74, 0x68, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x57, 0x61, 0x72, 0x73, 0x61, 0x77, 0x0, 0x49,
    +0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x43, 0x6f, 0x63, 0x6f, 0x73, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4d,
    +0x61, 0x68, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x73, 0x5f, 0x41, 0x6e, 0x67, 0x65,
    +0x6c, 0x65, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x74, 0x6c, 0x61, 0x6b, 0x61, 0x74,
    +0x6c, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x43, 0x61, 0x6c, 0x63, 0x75, 0x74, 0x74, 0x61, 0x0, 0x41, 0x66, 0x72,
    +0x69, 0x63, 0x61, 0x2f, 0x41, 0x62, 0x69, 0x64, 0x6a, 0x61, 0x6e, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b,
    +0x36, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x45, 0x66, 0x61, 0x74, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f,
    +0x70, 0x65, 0x2f, 0x4c, 0x75, 0x78, 0x65, 0x6d, 0x62, 0x6f, 0x75, 0x72, 0x67, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61,
    +0x2f, 0x42, 0x61, 0x6d, 0x61, 0x6b, 0x6f, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x69, 0x67, 0x61, 0x6c,
    +0x69, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x51, 0x61, 0x74, 0x61, 0x72, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61,
    +0x72, 0x61, 0x63, 0x68, 0x69, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x30, 0x0, 0x41, 0x66, 0x72,
    +0x69, 0x63, 0x61, 0x2f, 0x44, 0x6a, 0x69, 0x62, 0x6f, 0x75, 0x74, 0x69, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x59, 0x65,
    +0x6b, 0x61, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x62, 0x75, 0x72, 0x67, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
    +0x44, 0x61, 0x77, 0x73, 0x6f, 0x6e, 0x5f, 0x43, 0x72, 0x65, 0x65, 0x6b, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
    +0x2f, 0x43, 0x72, 0x65, 0x73, 0x74, 0x6f, 0x6e, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x46, 0x6f, 0x72,
    +0x74, 0x5f, 0x4e, 0x65, 0x6c, 0x73, 0x6f, 0x6e, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4d, 0x61, 0x79, 0x6f,
    +0x74, 0x74, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x6b, 0x6f, 0x70, 0x6a, 0x65, 0x0, 0x41, 0x73,
    +0x69, 0x61, 0x2f, 0x53, 0x65, 0x6f, 0x75, 0x6c, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x61, 0x72,
    +0x61, 0x6d, 0x61, 0x72, 0x69, 0x62, 0x6f, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x74, 0x6f, 0x63, 0x6b,
    +0x68, 0x6f, 0x6c, 0x6d, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x75, 0x62, 0x75, 0x6d, 0x62, 0x61, 0x73,
    +0x68, 0x69, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x61, 0x67, 0x65,
    +0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x75, 0x65, 0x6e, 0x6f, 0x73, 0x5f, 0x41, 0x69, 0x72, 0x65,
    +0x73, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x41, 0x73, 0x74, 0x72, 0x61, 0x6b, 0x68, 0x61, 0x6e, 0x0, 0x41,
    +0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x6c, 0x69, 0x66, 0x61, 0x78, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72,
    +0x61, 0x6c, 0x69, 0x61, 0x2f, 0x53, 0x79, 0x64, 0x6e, 0x65, 0x79, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
    +0x52, 0x65, 0x67, 0x69, 0x6e, 0x61, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x41, 0x64, 0x65,
    +0x6c, 0x61, 0x69, 0x64, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x6c, 0x6d, 0x61, 0x74, 0x79, 0x0, 0x41, 0x6d,
    +0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x75, 0x69, 0x61, 0x62, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
    +0x2f, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x5f, 0x43, 0x69, 0x74, 0x79, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
    +0x2f, 0x43, 0x68, 0x69, 0x63, 0x61, 0x67, 0x6f, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x42,
    +0x72, 0x69, 0x73, 0x62, 0x61, 0x6e, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x65, 0x77, 0x5f,
    +0x59, 0x6f, 0x72, 0x6b, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4b, 0x69, 0x65, 0x76, 0x0, 0x41, 0x6d, 0x65,
    +0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x68, 0x75, 0x61, 0x68, 0x75, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69,
    +0x63, 0x61, 0x2f, 0x44, 0x65, 0x6e, 0x76, 0x65, 0x72, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x72, 0x61, 0x73, 0x6e,
    +0x6f, 0x79, 0x61, 0x72, 0x73, 0x6b, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x73, 0x5f, 0x41,
    +0x6e, 0x67, 0x65, 0x6c, 0x65, 0x73, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x69, 0x6a, 0x75, 0x61,
    +0x6e, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x6d, 0x63, 0x68, 0x61, 0x74, 0x6b, 0x61, 0x0, 0x45, 0x75,
    +0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x6f, 0x73, 0x63, 0x6f, 0x77, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69,
    +0x61, 0x2f, 0x48, 0x6f, 0x62, 0x61, 0x72, 0x74, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x6c, 0x61, 0x61, 0x6e, 0x62,
    +0x61, 0x61, 0x74, 0x61, 0x72, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e,
    +0x61, 0x70, 0x6f, 0x6c, 0x69, 0x73, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f,
    +0x56, 0x6c, 0x61, 0x64, 0x69, 0x76, 0x6f, 0x73, 0x74, 0x6f, 0x6b, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42,
    +0x65, 0x72, 0x6c, 0x69, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x73, 0x68, 0x6b, 0x65, 0x6e, 0x74, 0x0,
    +0x41, 0x73, 0x69, 0x61, 0x2f, 0x48, 0x65, 0x62, 0x72, 0x6f, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x59, 0x61, 0x6b,
    +0x75, 0x74, 0x73, 0x6b, 0x0, 0x55, 0x54, 0x43, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x31, 0x34, 0x3a, 0x30, 0x30, 0x0, 0x55,
    +0x54, 0x43, 0x2d, 0x31, 0x33, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x31, 0x32, 0x3a, 0x30, 0x30, 0x0, 0x55,
    +0x54, 0x43, 0x2d, 0x31, 0x31, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x31, 0x30, 0x3a, 0x30, 0x30, 0x0, 0x55,
    +0x54, 0x43, 0x2d, 0x30, 0x39, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x38, 0x3a, 0x30, 0x30, 0x0, 0x55,
    +0x54, 0x43, 0x2d, 0x30, 0x37, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x36, 0x3a, 0x30, 0x30, 0x0, 0x55,
    +0x54, 0x43, 0x2d, 0x30, 0x35, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x34, 0x3a, 0x33, 0x30, 0x0, 0x55,
    +0x54, 0x43, 0x2d, 0x30, 0x34, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x33, 0x3a, 0x33, 0x30, 0x0, 0x55,
    +0x54, 0x43, 0x2d, 0x30, 0x33, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x32, 0x3a, 0x30, 0x30, 0x0, 0x55,
    +0x54, 0x43, 0x2d, 0x30, 0x31, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x0, 0x55,
    +0x54, 0x43, 0x2b, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x31, 0x3a, 0x30, 0x30, 0x0, 0x55,
    +0x54, 0x43, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x33, 0x3a, 0x30, 0x30, 0x0, 0x55,
    +0x54, 0x43, 0x2b, 0x30, 0x33, 0x3a, 0x33, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x34, 0x3a, 0x30, 0x30, 0x0, 0x55,
    +0x54, 0x43, 0x2b, 0x30, 0x34, 0x3a, 0x33, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x35, 0x3a, 0x30, 0x30, 0x0, 0x55,
    +0x54, 0x43, 0x2b, 0x30, 0x35, 0x3a, 0x33, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x35, 0x3a, 0x34, 0x35, 0x0, 0x55,
    +0x54, 0x43, 0x2b, 0x30, 0x36, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x36, 0x3a, 0x33, 0x30, 0x0, 0x55,
    +0x54, 0x43, 0x2b, 0x30, 0x37, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x38, 0x3a, 0x30, 0x30, 0x0, 0x55,
    +0x54, 0x43, 0x2b, 0x30, 0x38, 0x3a, 0x33, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x39, 0x3a, 0x30, 0x30, 0x0, 0x55,
    +0x54, 0x43, 0x2b, 0x30, 0x39, 0x3a, 0x33, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x30, 0x3a, 0x30, 0x30, 0x0, 0x55,
    +0x54, 0x43, 0x2b, 0x31, 0x31, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x32, 0x3a, 0x30, 0x30, 0x0, 0x55,
    +0x54, 0x43, 0x2b, 0x31, 0x33, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x34, 0x3a, 0x30, 0x30, 0x0
    +};
    +// GENERATED PART ENDS HERE
    +
    +QT_END_NAMESPACE
    +
    +#endif // QTIMEZONEPRIVATE_DATA_P_H
    diff --git a/src/corelib/time/qtimezoneprivate_icu.cpp b/src/corelib/time/qtimezoneprivate_icu.cpp
    new file mode 100644
    index 0000000000..5570ce7571
    --- /dev/null
    +++ b/src/corelib/time/qtimezoneprivate_icu.cpp
    @@ -0,0 +1,508 @@
    +/****************************************************************************
    +**
    +** Copyright (C) 2013 John Layt 
    +** Contact: https://www.qt.io/licensing/
    +**
    +** This file is part of the QtCore module of the Qt Toolkit.
    +**
    +** $QT_BEGIN_LICENSE:LGPL$
    +** Commercial License Usage
    +** Licensees holding valid commercial Qt licenses may use this file in
    +** accordance with the commercial license agreement provided with the
    +** Software or, alternatively, in accordance with the terms contained in
    +** a written agreement between you and The Qt Company. For licensing terms
    +** and conditions see https://www.qt.io/terms-conditions. For further
    +** information use the contact form at https://www.qt.io/contact-us.
    +**
    +** GNU Lesser General Public License Usage
    +** Alternatively, this file may be used under the terms of the GNU Lesser
    +** General Public License version 3 as published by the Free Software
    +** Foundation and appearing in the file LICENSE.LGPL3 included in the
    +** packaging of this file. Please review the following information to
    +** ensure the GNU Lesser General Public License version 3 requirements
    +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
    +**
    +** GNU General Public License Usage
    +** Alternatively, this file may be used under the terms of the GNU
    +** General Public License version 2.0 or (at your option) the GNU General
    +** Public license version 3 or any later version approved by the KDE Free
    +** Qt Foundation. The licenses are as published by the Free Software
    +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
    +** included in the packaging of this file. Please review the following
    +** information to ensure the GNU General Public License requirements will
    +** be met: https://www.gnu.org/licenses/gpl-2.0.html and
    +** https://www.gnu.org/licenses/gpl-3.0.html.
    +**
    +** $QT_END_LICENSE$
    +**
    +****************************************************************************/
    +
    +#include "qtimezone.h"
    +#include "qtimezoneprivate_p.h"
    +
    +#include 
    +
    +#include 
    +#include 
    +
    +#include 
    +
    +QT_BEGIN_NAMESPACE
    +
    +/*
    +    Private
    +
    +    ICU implementation
    +*/
    +
    +// ICU utilities
    +
    +// Convert TimeType and NameType into ICU UCalendarDisplayNameType
    +static UCalendarDisplayNameType ucalDisplayNameType(QTimeZone::TimeType timeType, QTimeZone::NameType nameType)
    +{
    +    // TODO ICU C UCalendarDisplayNameType does not support full set of C++ TimeZone::EDisplayType
    +    switch (nameType) {
    +    case QTimeZone::ShortName :
    +    case QTimeZone::OffsetName :
    +        if (timeType == QTimeZone::DaylightTime)
    +            return UCAL_SHORT_DST;
    +        // Includes GenericTime
    +        return UCAL_SHORT_STANDARD;
    +    case QTimeZone::DefaultName :
    +    case QTimeZone::LongName :
    +        if (timeType == QTimeZone::DaylightTime)
    +            return UCAL_DST;
    +        // Includes GenericTime
    +        return UCAL_STANDARD;
    +    }
    +    return UCAL_STANDARD;
    +}
    +
    +// Qt wrapper around ucal_getDefaultTimeZone()
    +static QByteArray ucalDefaultTimeZoneId()
    +{
    +    int32_t size = 30;
    +    QString result(size, Qt::Uninitialized);
    +    UErrorCode status = U_ZERO_ERROR;
    +
    +    // size = ucal_getDefaultTimeZone(result, resultLength, status)
    +    size = ucal_getDefaultTimeZone(reinterpret_cast(result.data()), size, &status);
    +
    +    // If overflow, then resize and retry
    +    if (status == U_BUFFER_OVERFLOW_ERROR) {
    +        result.resize(size);
    +        status = U_ZERO_ERROR;
    +        size = ucal_getDefaultTimeZone(reinterpret_cast(result.data()), size, &status);
    +    }
    +
    +    // If successful on first or second go, resize and return
    +    if (U_SUCCESS(status)) {
    +        result.resize(size);
    +        return std::move(result).toUtf8();
    +    }
    +
    +    return QByteArray();
    +}
    +
    +// Qt wrapper around ucal_getTimeZoneDisplayName()
    +static QString ucalTimeZoneDisplayName(UCalendar *ucal, QTimeZone::TimeType timeType,
    +                                       QTimeZone::NameType nameType,
    +                                       const QString &localeCode)
    +{
    +    int32_t size = 50;
    +    QString result(size, Qt::Uninitialized);
    +    UErrorCode status = U_ZERO_ERROR;
    +
    +    // size = ucal_getTimeZoneDisplayName(cal, type, locale, result, resultLength, status)
    +    size = ucal_getTimeZoneDisplayName(ucal,
    +                                       ucalDisplayNameType(timeType, nameType),
    +                                       localeCode.toUtf8(),
    +                                       reinterpret_cast(result.data()),
    +                                       size,
    +                                       &status);
    +
    +    // If overflow, then resize and retry
    +    if (status == U_BUFFER_OVERFLOW_ERROR) {
    +        result.resize(size);
    +        status = U_ZERO_ERROR;
    +        size = ucal_getTimeZoneDisplayName(ucal,
    +                                           ucalDisplayNameType(timeType, nameType),
    +                                           localeCode.toUtf8(),
    +                                           reinterpret_cast(result.data()),
    +                                           size,
    +                                           &status);
    +    }
    +
    +    // If successful on first or second go, resize and return
    +    if (U_SUCCESS(status)) {
    +        result.resize(size);
    +        return result;
    +    }
    +
    +    return QString();
    +}
    +
    +// Qt wrapper around ucal_get() for offsets
    +static bool ucalOffsetsAtTime(UCalendar *m_ucal, qint64 atMSecsSinceEpoch,
    +                              int *utcOffset, int *dstOffset)
    +{
    +    *utcOffset = 0;
    +    *dstOffset = 0;
    +
    +    // Clone the ucal so we don't change the shared object
    +    UErrorCode status = U_ZERO_ERROR;
    +    UCalendar *ucal = ucal_clone(m_ucal, &status);
    +    if (!U_SUCCESS(status))
    +        return false;
    +
    +    // Set the date to find the offset for
    +    status = U_ZERO_ERROR;
    +    ucal_setMillis(ucal, atMSecsSinceEpoch, &status);
    +
    +    int32_t utc = 0;
    +    if (U_SUCCESS(status)) {
    +        status = U_ZERO_ERROR;
    +        // Returns msecs
    +        utc = ucal_get(ucal, UCAL_ZONE_OFFSET, &status) / 1000;
    +    }
    +
    +    int32_t dst = 0;
    +    if (U_SUCCESS(status)) {
    +        status = U_ZERO_ERROR;
    +        // Returns msecs
    +        dst = ucal_get(ucal, UCAL_DST_OFFSET, &status) / 1000;
    +    }
    +
    +    ucal_close(ucal);
    +    if (U_SUCCESS(status)) {
    +        *utcOffset = utc;
    +        *dstOffset = dst;
    +        return true;
    +    }
    +    return false;
    +}
    +
    +// ICU Draft api in v50, should be stable in ICU v51. Available in C++ api from ICU v3.8
    +#if U_ICU_VERSION_MAJOR_NUM == 50
    +// Qt wrapper around qt_ucal_getTimeZoneTransitionDate & ucal_get
    +static QTimeZonePrivate::Data ucalTimeZoneTransition(UCalendar *m_ucal,
    +                                                     UTimeZoneTransitionType type,
    +                                                     qint64 atMSecsSinceEpoch)
    +{
    +    QTimeZonePrivate::Data tran = QTimeZonePrivate::invalidData();
    +
    +    // Clone the ucal so we don't change the shared object
    +    UErrorCode status = U_ZERO_ERROR;
    +    UCalendar *ucal = ucal_clone(m_ucal, &status);
    +    if (!U_SUCCESS(status))
    +        return tran;
    +
    +    // Set the date to find the transition for
    +    status = U_ZERO_ERROR;
    +    ucal_setMillis(ucal, atMSecsSinceEpoch, &status);
    +
    +    // Find the transition time
    +    UDate tranMSecs = 0;
    +    status = U_ZERO_ERROR;
    +    bool ok = ucal_getTimeZoneTransitionDate(ucal, type, &tranMSecs, &status);
    +
    +    // Set the transition time to find the offsets for
    +    if (U_SUCCESS(status) && ok) {
    +        status = U_ZERO_ERROR;
    +        ucal_setMillis(ucal, tranMSecs, &status);
    +    }
    +
    +    int32_t utc = 0;
    +    if (U_SUCCESS(status) && ok) {
    +        status = U_ZERO_ERROR;
    +        utc = ucal_get(ucal, UCAL_ZONE_OFFSET, &status) / 1000;
    +    }
    +
    +    int32_t dst = 0;
    +    if (U_SUCCESS(status) && ok) {
    +        status = U_ZERO_ERROR;
    +        dst = ucal_get(ucal, UCAL_DST_OFFSET, &status) / 1000;
    +    }
    +
    +    ucal_close(ucal);
    +    if (!U_SUCCESS(status) || !ok)
    +        return tran;
    +    tran.atMSecsSinceEpoch = tranMSecs;
    +    tran.offsetFromUtc = utc + dst;
    +    tran.standardTimeOffset = utc;
    +    tran.daylightTimeOffset = dst;
    +    // TODO No ICU API, use short name instead
    +    if (dst == 0)
    +        tran.abbreviation = ucalTimeZoneDisplayName(m_ucal, QTimeZone::StandardTime,
    +                                                    QTimeZone::ShortName, QLocale().name());
    +    else
    +        tran.abbreviation = ucalTimeZoneDisplayName(m_ucal, QTimeZone::DaylightTime,
    +                                                    QTimeZone::ShortName, QLocale().name());
    +    return tran;
    +}
    +#endif // U_ICU_VERSION_SHORT
    +
    +// Convert a uenum to a QList
    +static QList uenumToIdList(UEnumeration *uenum)
    +{
    +    QList list;
    +    int32_t size = 0;
    +    UErrorCode status = U_ZERO_ERROR;
    +    // TODO Perhaps use uenum_unext instead?
    +    QByteArray result = uenum_next(uenum, &size, &status);
    +    while (U_SUCCESS(status) && !result.isEmpty()) {
    +        list << result;
    +        status = U_ZERO_ERROR;
    +        result = uenum_next(uenum, &size, &status);
    +    }
    +    std::sort(list.begin(), list.end());
    +    list.erase(std::unique(list.begin(), list.end()), list.end());
    +    return list;
    +}
    +
    +// Qt wrapper around ucal_getDSTSavings()
    +static int ucalDaylightOffset(const QByteArray &id)
    +{
    +    UErrorCode status = U_ZERO_ERROR;
    +    const int32_t dstMSecs = ucal_getDSTSavings(reinterpret_cast(id.data()), &status);
    +    if (U_SUCCESS(status))
    +        return (dstMSecs / 1000);
    +    else
    +        return 0;
    +}
    +
    +// Create the system default time zone
    +QIcuTimeZonePrivate::QIcuTimeZonePrivate()
    +    : m_ucal(0)
    +{
    +    // TODO No ICU C API to obtain sysem tz, assume default hasn't been changed
    +    init(ucalDefaultTimeZoneId());
    +}
    +
    +// Create a named time zone
    +QIcuTimeZonePrivate::QIcuTimeZonePrivate(const QByteArray &ianaId)
    +    : m_ucal(0)
    +{
    +    // Need to check validity here as ICu will create a GMT tz if name is invalid
    +    if (availableTimeZoneIds().contains(ianaId))
    +        init(ianaId);
    +}
    +
    +QIcuTimeZonePrivate::QIcuTimeZonePrivate(const QIcuTimeZonePrivate &other)
    +    : QTimeZonePrivate(other), m_ucal(0)
    +{
    +    // Clone the ucal so we don't close the shared object
    +    UErrorCode status = U_ZERO_ERROR;
    +    m_ucal = ucal_clone(other.m_ucal, &status);
    +    if (!U_SUCCESS(status)) {
    +        m_id.clear();
    +        m_ucal = 0;
    +    }
    +}
    +
    +QIcuTimeZonePrivate::~QIcuTimeZonePrivate()
    +{
    +    ucal_close(m_ucal);
    +}
    +
    +QIcuTimeZonePrivate *QIcuTimeZonePrivate::clone() const
    +{
    +    return new QIcuTimeZonePrivate(*this);
    +}
    +
    +void QIcuTimeZonePrivate::init(const QByteArray &ianaId)
    +{
    +    m_id = ianaId;
    +
    +    const QString id = QString::fromUtf8(m_id);
    +    UErrorCode status = U_ZERO_ERROR;
    +    //TODO Use UCAL_GREGORIAN for now to match QLocale, change to UCAL_DEFAULT once full ICU support
    +    m_ucal = ucal_open(reinterpret_cast(id.data()), id.size(),
    +                       QLocale().name().toUtf8(), UCAL_GREGORIAN, &status);
    +
    +    if (!U_SUCCESS(status)) {
    +        m_id.clear();
    +        m_ucal = 0;
    +    }
    +}
    +
    +QString QIcuTimeZonePrivate::displayName(QTimeZone::TimeType timeType,
    +                                         QTimeZone::NameType nameType,
    +                                         const QLocale &locale) const
    +{
    +    // Return standard offset format name as ICU C api doesn't support it yet
    +    if (nameType == QTimeZone::OffsetName) {
    +        const Data nowData = data(QDateTime::currentMSecsSinceEpoch());
    +        // We can't use transitions reliably to find out right dst offset
    +        // Instead use dst offset api to try get it if needed
    +        if (timeType == QTimeZone::DaylightTime)
    +            return isoOffsetFormat(nowData.standardTimeOffset + ucalDaylightOffset(m_id));
    +        else
    +            return isoOffsetFormat(nowData.standardTimeOffset);
    +    }
    +    return ucalTimeZoneDisplayName(m_ucal, timeType, nameType, locale.name());
    +}
    +
    +QString QIcuTimeZonePrivate::abbreviation(qint64 atMSecsSinceEpoch) const
    +{
    +    // TODO No ICU API, use short name instead
    +    if (isDaylightTime(atMSecsSinceEpoch))
    +        return displayName(QTimeZone::DaylightTime, QTimeZone::ShortName, QString());
    +    else
    +        return displayName(QTimeZone::StandardTime, QTimeZone::ShortName, QString());
    +}
    +
    +int QIcuTimeZonePrivate::offsetFromUtc(qint64 atMSecsSinceEpoch) const
    +{
    +    int stdOffset = 0;
    +    int dstOffset = 0;
    +    ucalOffsetsAtTime(m_ucal, atMSecsSinceEpoch, &stdOffset, & dstOffset);
    +    return stdOffset + dstOffset;
    +}
    +
    +int QIcuTimeZonePrivate::standardTimeOffset(qint64 atMSecsSinceEpoch) const
    +{
    +    int stdOffset = 0;
    +    int dstOffset = 0;
    +    ucalOffsetsAtTime(m_ucal, atMSecsSinceEpoch, &stdOffset, & dstOffset);
    +    return stdOffset;
    +}
    +
    +int QIcuTimeZonePrivate::daylightTimeOffset(qint64 atMSecsSinceEpoch) const
    +{
    +    int stdOffset = 0;
    +    int dstOffset = 0;
    +    ucalOffsetsAtTime(m_ucal, atMSecsSinceEpoch, &stdOffset, & dstOffset);
    +    return dstOffset;
    +}
    +
    +bool QIcuTimeZonePrivate::hasDaylightTime() const
    +{
    +    // TODO No direct ICU C api, work-around below not reliable?  Find a better way?
    +    return (ucalDaylightOffset(m_id) != 0);
    +}
    +
    +bool QIcuTimeZonePrivate::isDaylightTime(qint64 atMSecsSinceEpoch) const
    +{
    +    // Clone the ucal so we don't change the shared object
    +    UErrorCode status = U_ZERO_ERROR;
    +    UCalendar *ucal = ucal_clone(m_ucal, &status);
    +    if (!U_SUCCESS(status))
    +        return false;
    +
    +    // Set the date to find the offset for
    +    status = U_ZERO_ERROR;
    +    ucal_setMillis(ucal, atMSecsSinceEpoch, &status);
    +
    +    bool result = false;
    +    if (U_SUCCESS(status)) {
    +        status = U_ZERO_ERROR;
    +        result = ucal_inDaylightTime(ucal, &status);
    +    }
    +
    +    ucal_close(ucal);
    +    return result;
    +}
    +
    +QTimeZonePrivate::Data QIcuTimeZonePrivate::data(qint64 forMSecsSinceEpoch) const
    +{
    +    // Available in ICU C++ api, and draft C api in v50
    +    // TODO When v51 released see if api is stable
    +    QTimeZonePrivate::Data data = invalidData();
    +#if U_ICU_VERSION_MAJOR_NUM == 50
    +    data = ucalTimeZoneTransition(m_ucal, UCAL_TZ_TRANSITION_PREVIOUS_INCLUSIVE,
    +                                  forMSecsSinceEpoch);
    +#else
    +    ucalOffsetsAtTime(m_ucal, forMSecsSinceEpoch, &data.standardTimeOffset,
    +                      &data.daylightTimeOffset);
    +    data.offsetFromUtc = data.standardTimeOffset + data.daylightTimeOffset;
    +    data.abbreviation = abbreviation(forMSecsSinceEpoch);
    +#endif // U_ICU_VERSION_MAJOR_NUM == 50
    +    data.atMSecsSinceEpoch = forMSecsSinceEpoch;
    +    return data;
    +}
    +
    +bool QIcuTimeZonePrivate::hasTransitions() const
    +{
    +    // Available in ICU C++ api, and draft C api in v50
    +    // TODO When v51 released see if api is stable
    +#if U_ICU_VERSION_MAJOR_NUM == 50
    +    return true;
    +#else
    +    return false;
    +#endif // U_ICU_VERSION_MAJOR_NUM == 50
    +}
    +
    +QTimeZonePrivate::Data QIcuTimeZonePrivate::nextTransition(qint64 afterMSecsSinceEpoch) const
    +{
    +    // Available in ICU C++ api, and draft C api in v50
    +    // TODO When v51 released see if api is stable
    +#if U_ICU_VERSION_MAJOR_NUM == 50
    +    return ucalTimeZoneTransition(m_ucal, UCAL_TZ_TRANSITION_NEXT, afterMSecsSinceEpoch);
    +#else
    +    Q_UNUSED(afterMSecsSinceEpoch)
    +    return invalidData();
    +#endif // U_ICU_VERSION_MAJOR_NUM == 50
    +}
    +
    +QTimeZonePrivate::Data QIcuTimeZonePrivate::previousTransition(qint64 beforeMSecsSinceEpoch) const
    +{
    +    // Available in ICU C++ api, and draft C api in v50
    +    // TODO When v51 released see if api is stable
    +#if U_ICU_VERSION_MAJOR_NUM == 50
    +    return ucalTimeZoneTransition(m_ucal, UCAL_TZ_TRANSITION_PREVIOUS, beforeMSecsSinceEpoch);
    +#else
    +    Q_UNUSED(beforeMSecsSinceEpoch)
    +    return invalidData();
    +#endif // U_ICU_VERSION_MAJOR_NUM == 50
    +}
    +
    +QByteArray QIcuTimeZonePrivate::systemTimeZoneId() const
    +{
    +    // No ICU C API to obtain sysem tz
    +    // TODO Assume default hasn't been changed and is the latests system
    +    return ucalDefaultTimeZoneId();
    +}
    +
    +QList QIcuTimeZonePrivate::availableTimeZoneIds() const
    +{
    +    UErrorCode status = U_ZERO_ERROR;
    +    UEnumeration *uenum = ucal_openTimeZones(&status);
    +    QList result;
    +    if (U_SUCCESS(status))
    +        result = uenumToIdList(uenum);
    +    uenum_close(uenum);
    +    return result;
    +}
    +
    +QList QIcuTimeZonePrivate::availableTimeZoneIds(QLocale::Country country) const
    +{
    +    const QLatin1String regionCode = QLocalePrivate::countryToCode(country);
    +    const QByteArray regionCodeUtf8 = QString(regionCode).toUtf8();
    +    UErrorCode status = U_ZERO_ERROR;
    +    UEnumeration *uenum = ucal_openCountryTimeZones(regionCodeUtf8.data(), &status);
    +    QList result;
    +    if (U_SUCCESS(status))
    +        result = uenumToIdList(uenum);
    +    uenum_close(uenum);
    +    return result;
    +}
    +
    +QList QIcuTimeZonePrivate::availableTimeZoneIds(int offsetFromUtc) const
    +{
    +// TODO Available directly in C++ api but not C api, from 4.8 onwards new filter method works
    +#if U_ICU_VERSION_MAJOR_NUM >= 49 || (U_ICU_VERSION_MAJOR_NUM == 4 && U_ICU_VERSION_MINOR_NUM == 8)
    +    UErrorCode status = U_ZERO_ERROR;
    +    UEnumeration *uenum = ucal_openTimeZoneIDEnumeration(UCAL_ZONE_TYPE_ANY, 0,
    +                                                         &offsetFromUtc, &status);
    +    QList result;
    +    if (U_SUCCESS(status))
    +        result = uenumToIdList(uenum);
    +    uenum_close(uenum);
    +    return result;
    +#else
    +    return QTimeZonePrivate::availableTimeZoneIds(offsetFromUtc);
    +#endif
    +}
    +
    +QT_END_NAMESPACE
    diff --git a/src/corelib/time/qtimezoneprivate_mac.mm b/src/corelib/time/qtimezoneprivate_mac.mm
    new file mode 100644
    index 0000000000..d3c4fbe5da
    --- /dev/null
    +++ b/src/corelib/time/qtimezoneprivate_mac.mm
    @@ -0,0 +1,333 @@
    +/****************************************************************************
    +**
    +** Copyright (C) 2013 John Layt 
    +** Contact: https://www.qt.io/licensing/
    +**
    +** This file is part of the QtCore module of the Qt Toolkit.
    +**
    +** $QT_BEGIN_LICENSE:LGPL$
    +** Commercial License Usage
    +** Licensees holding valid commercial Qt licenses may use this file in
    +** accordance with the commercial license agreement provided with the
    +** Software or, alternatively, in accordance with the terms contained in
    +** a written agreement between you and The Qt Company. For licensing terms
    +** and conditions see https://www.qt.io/terms-conditions. For further
    +** information use the contact form at https://www.qt.io/contact-us.
    +**
    +** GNU Lesser General Public License Usage
    +** Alternatively, this file may be used under the terms of the GNU Lesser
    +** General Public License version 3 as published by the Free Software
    +** Foundation and appearing in the file LICENSE.LGPL3 included in the
    +** packaging of this file. Please review the following information to
    +** ensure the GNU Lesser General Public License version 3 requirements
    +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
    +**
    +** GNU General Public License Usage
    +** Alternatively, this file may be used under the terms of the GNU
    +** General Public License version 2.0 or (at your option) the GNU General
    +** Public license version 3 or any later version approved by the KDE Free
    +** Qt Foundation. The licenses are as published by the Free Software
    +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
    +** included in the packaging of this file. Please review the following
    +** information to ensure the GNU General Public License requirements will
    +** be met: https://www.gnu.org/licenses/gpl-2.0.html and
    +** https://www.gnu.org/licenses/gpl-3.0.html.
    +**
    +** $QT_END_LICENSE$
    +**
    +****************************************************************************/
    +
    +#include "qtimezone.h"
    +#include "qtimezoneprivate_p.h"
    +
    +#include "private/qcore_mac_p.h"
    +#include "qstringlist.h"
    +
    +#include 
    +
    +#include 
    +
    +#include 
    +
    +QT_BEGIN_NAMESPACE
    +
    +/*
    +    Private
    +
    +    OS X system implementation
    +*/
    +
    +// Create the system default time zone
    +QMacTimeZonePrivate::QMacTimeZonePrivate()
    +    : m_nstz(0)
    +{
    +    init(systemTimeZoneId());
    +}
    +
    +// Create a named time zone
    +QMacTimeZonePrivate::QMacTimeZonePrivate(const QByteArray &ianaId)
    +    : m_nstz(0)
    +{
    +    init(ianaId);
    +}
    +
    +QMacTimeZonePrivate::QMacTimeZonePrivate(const QMacTimeZonePrivate &other)
    +    : QTimeZonePrivate(other), m_nstz(0)
    +{
    +    m_nstz = [other.m_nstz copy];
    +}
    +
    +QMacTimeZonePrivate::~QMacTimeZonePrivate()
    +{
    +    [m_nstz release];
    +}
    +
    +QMacTimeZonePrivate *QMacTimeZonePrivate::clone() const
    +{
    +    return new QMacTimeZonePrivate(*this);
    +}
    +
    +void QMacTimeZonePrivate::init(const QByteArray &ianaId)
    +{
    +    if (availableTimeZoneIds().contains(ianaId)) {
    +        m_nstz = [[NSTimeZone timeZoneWithName:QString::fromUtf8(ianaId).toNSString()] retain];
    +        if (m_nstz)
    +            m_id = ianaId;
    +    }
    +}
    +
    +QString QMacTimeZonePrivate::comment() const
    +{
    +    return QString::fromNSString([m_nstz description]);
    +}
    +
    +QString QMacTimeZonePrivate::displayName(QTimeZone::TimeType timeType,
    +                                         QTimeZone::NameType nameType,
    +                                         const QLocale &locale) const
    +{
    +    // TODO Mac doesn't support OffsetName yet so use standard offset name
    +    if (nameType == QTimeZone::OffsetName) {
    +        const Data nowData = data(QDateTime::currentMSecsSinceEpoch());
    +        // TODO Cheat for now, assume if has dst the offset if 1 hour
    +        if (timeType == QTimeZone::DaylightTime && hasDaylightTime())
    +            return isoOffsetFormat(nowData.standardTimeOffset + 3600);
    +        else
    +            return isoOffsetFormat(nowData.standardTimeOffset);
    +    }
    +
    +    NSTimeZoneNameStyle style = NSTimeZoneNameStyleStandard;
    +
    +    switch (nameType) {
    +    case QTimeZone::ShortName :
    +        if (timeType == QTimeZone::DaylightTime)
    +            style = NSTimeZoneNameStyleShortDaylightSaving;
    +        else if (timeType == QTimeZone::GenericTime)
    +            style = NSTimeZoneNameStyleShortGeneric;
    +        else
    +            style = NSTimeZoneNameStyleShortStandard;
    +        break;
    +    case QTimeZone::DefaultName :
    +    case QTimeZone::LongName :
    +        if (timeType == QTimeZone::DaylightTime)
    +            style = NSTimeZoneNameStyleDaylightSaving;
    +        else if (timeType == QTimeZone::GenericTime)
    +            style = NSTimeZoneNameStyleGeneric;
    +        else
    +            style = NSTimeZoneNameStyleStandard;
    +        break;
    +    case QTimeZone::OffsetName :
    +        // Unreachable
    +        break;
    +    }
    +
    +    NSString *macLocaleCode = locale.name().toNSString();
    +    NSLocale *macLocale = [[NSLocale alloc] initWithLocaleIdentifier:macLocaleCode];
    +    const QString result = QString::fromNSString([m_nstz localizedName:style locale:macLocale]);
    +    [macLocale release];
    +    return result;
    +}
    +
    +QString QMacTimeZonePrivate::abbreviation(qint64 atMSecsSinceEpoch) const
    +{
    +    const NSTimeInterval seconds = atMSecsSinceEpoch / 1000.0;
    +    return QString::fromNSString([m_nstz abbreviationForDate:[NSDate dateWithTimeIntervalSince1970:seconds]]);
    +}
    +
    +int QMacTimeZonePrivate::offsetFromUtc(qint64 atMSecsSinceEpoch) const
    +{
    +    const NSTimeInterval seconds = atMSecsSinceEpoch / 1000.0;
    +    return [m_nstz secondsFromGMTForDate:[NSDate dateWithTimeIntervalSince1970:seconds]];
    +}
    +
    +int QMacTimeZonePrivate::standardTimeOffset(qint64 atMSecsSinceEpoch) const
    +{
    +    return offsetFromUtc(atMSecsSinceEpoch) - daylightTimeOffset(atMSecsSinceEpoch);
    +}
    +
    +int QMacTimeZonePrivate::daylightTimeOffset(qint64 atMSecsSinceEpoch) const
    +{
    +    const NSTimeInterval seconds = atMSecsSinceEpoch / 1000.0;
    +    return [m_nstz daylightSavingTimeOffsetForDate:[NSDate dateWithTimeIntervalSince1970:seconds]];
    +}
    +
    +bool QMacTimeZonePrivate::hasDaylightTime() const
    +{
    +    // TODO No Mac API, assume if has transitions
    +    return hasTransitions();
    +}
    +
    +bool QMacTimeZonePrivate::isDaylightTime(qint64 atMSecsSinceEpoch) const
    +{
    +    const NSTimeInterval seconds = atMSecsSinceEpoch / 1000.0;
    +    return [m_nstz isDaylightSavingTimeForDate:[NSDate dateWithTimeIntervalSince1970:seconds]];
    +}
    +
    +QTimeZonePrivate::Data QMacTimeZonePrivate::data(qint64 forMSecsSinceEpoch) const
    +{
    +    const NSTimeInterval seconds = forMSecsSinceEpoch / 1000.0;
    +    NSDate *date = [NSDate dateWithTimeIntervalSince1970:seconds];
    +    Data data;
    +    data.atMSecsSinceEpoch = forMSecsSinceEpoch;
    +    data.offsetFromUtc = [m_nstz secondsFromGMTForDate:date];
    +    data.daylightTimeOffset = [m_nstz daylightSavingTimeOffsetForDate:date];
    +    data.standardTimeOffset = data.offsetFromUtc - data.daylightTimeOffset;
    +    data.abbreviation = QString::fromNSString([m_nstz abbreviationForDate:date]);
    +    return data;
    +}
    +
    +bool QMacTimeZonePrivate::hasTransitions() const
    +{
    +    // TODO No direct Mac API, so return if has next after 1970, i.e. since start of tz
    +    // TODO Not sure what is returned in event of no transitions, assume will be before requested date
    +    NSDate *epoch = [NSDate dateWithTimeIntervalSince1970:0];
    +    const NSDate *date = [m_nstz nextDaylightSavingTimeTransitionAfterDate:epoch];
    +    const bool result = ([date timeIntervalSince1970] > [epoch timeIntervalSince1970]);
    +    return result;
    +}
    +
    +QTimeZonePrivate::Data QMacTimeZonePrivate::nextTransition(qint64 afterMSecsSinceEpoch) const
    +{
    +    QTimeZonePrivate::Data tran;
    +    const NSTimeInterval seconds = afterMSecsSinceEpoch / 1000.0;
    +    NSDate *nextDate = [NSDate dateWithTimeIntervalSince1970:seconds];
    +    nextDate = [m_nstz nextDaylightSavingTimeTransitionAfterDate:nextDate];
    +    const NSTimeInterval nextSecs = [nextDate timeIntervalSince1970];
    +    if (nextDate == nil || nextSecs <= seconds) {
    +        [nextDate release];
    +        return invalidData();
    +    }
    +    tran.atMSecsSinceEpoch = nextSecs * 1000;
    +    tran.offsetFromUtc = [m_nstz secondsFromGMTForDate:nextDate];
    +    tran.daylightTimeOffset = [m_nstz daylightSavingTimeOffsetForDate:nextDate];
    +    tran.standardTimeOffset = tran.offsetFromUtc - tran.daylightTimeOffset;
    +    tran.abbreviation = QString::fromNSString([m_nstz abbreviationForDate:nextDate]);
    +    return tran;
    +}
    +
    +QTimeZonePrivate::Data QMacTimeZonePrivate::previousTransition(qint64 beforeMSecsSinceEpoch) const
    +{
    +    // The native API only lets us search forward, so we need to find an early-enough start:
    +    const NSTimeInterval lowerBound = std::numeric_limits::lowest();
    +    const qint64 endSecs = beforeMSecsSinceEpoch / 1000;
    +    const int year = 366 * 24 * 3600; // a (long) year, in seconds
    +    NSTimeInterval prevSecs = endSecs; // sentinel for later check
    +    NSTimeInterval nextSecs = prevSecs - year;
    +    NSTimeInterval tranSecs = lowerBound; // time at a transition; may be > endSecs
    +
    +    NSDate *nextDate = [NSDate dateWithTimeIntervalSince1970:nextSecs];
    +    nextDate = [m_nstz nextDaylightSavingTimeTransitionAfterDate:nextDate];
    +    if (nextDate != nil
    +        && (tranSecs = [nextDate timeIntervalSince1970]) < endSecs) {
    +        // There's a transition within the last year before endSecs:
    +        nextSecs = tranSecs;
    +    } else {
    +        // Need to start our search earlier:
    +        nextDate = [NSDate dateWithTimeIntervalSince1970:lowerBound];
    +        nextDate = [m_nstz nextDaylightSavingTimeTransitionAfterDate:nextDate];
    +        if (nextDate != nil) {
    +            NSTimeInterval lateSecs = nextSecs;
    +            nextSecs = [nextDate timeIntervalSince1970];
    +            Q_ASSERT(nextSecs <= endSecs - year || nextSecs == tranSecs);
    +            /*
    +              We're looking at the first ever transition for our zone, at
    +              nextSecs (and our zone *does* have at least one transition).  If
    +              it's later than endSecs - year, then we must have found it on the
    +              initial check and therefore set tranSecs to the same transition
    +              time (which, we can infer here, is >= endSecs).  In this case, we
    +              won't enter the binary-chop loop, below.
    +
    +              In the loop, nextSecs < lateSecs < endSecs: we have a transition
    +              at nextSecs and there is no transition between lateSecs and
    +              endSecs.  The loop narrows the interval between nextSecs and
    +              lateSecs by looking for a transition after their mid-point; if it
    +              finds one < endSecs, nextSecs moves to this transition; otherwise,
    +              lateSecs moves to the mid-point.  This soon enough narrows the gap
    +              to within a year, after which walking forward one transition at a
    +              time (the "Wind through" loop, below) is good enough.
    +            */
    +
    +            // Binary chop to within a year of last transition before endSecs:
    +            while (nextSecs + year < lateSecs) {
    +                // Careful about overflow, not fussy about rounding errors:
    +                NSTimeInterval middle = nextSecs / 2 + lateSecs / 2;
    +                NSDate *split = [NSDate dateWithTimeIntervalSince1970:middle];
    +                split = [m_nstz nextDaylightSavingTimeTransitionAfterDate:split];
    +                if (split != nil
    +                    && (tranSecs = [split timeIntervalSince1970]) < endSecs) {
    +                    nextDate = split;
    +                    nextSecs = tranSecs;
    +                } else {
    +                    lateSecs = middle;
    +                }
    +            }
    +            Q_ASSERT(nextDate != nil);
    +            // ... and nextSecs < endSecs unless first transition ever was >= endSecs.
    +        } // else: we have no data - prevSecs is still endSecs, nextDate is still nil
    +    }
    +    // Either nextDate is nil or nextSecs is at its transition.
    +
    +    // Wind through remaining transitions (spanning at most a year), one at a time:
    +    while (nextDate != nil && nextSecs < endSecs) {
    +        prevSecs = nextSecs;
    +        nextDate = [m_nstz nextDaylightSavingTimeTransitionAfterDate:nextDate];
    +        nextSecs = [nextDate timeIntervalSince1970];
    +        if (nextSecs <= prevSecs) // presumably no later data available
    +            break;
    +    }
    +    if (prevSecs < endSecs) // i.e. we did make it into that while loop
    +        return data(qint64(prevSecs * 1e3));
    +
    +    // No transition data; or first transition later than requested time.
    +    return invalidData();
    +}
    +
    +QByteArray QMacTimeZonePrivate::systemTimeZoneId() const
    +{
    +    // Reset the cached system tz then return the name
    +    [NSTimeZone resetSystemTimeZone];
    +    return QString::fromNSString([[NSTimeZone systemTimeZone] name]).toUtf8();
    +}
    +
    +QList QMacTimeZonePrivate::availableTimeZoneIds() const
    +{
    +    NSEnumerator *enumerator = [[NSTimeZone knownTimeZoneNames] objectEnumerator];
    +    QByteArray tzid = QString::fromNSString([enumerator nextObject]).toUtf8();
    +
    +    QList list;
    +    while (!tzid.isEmpty()) {
    +        list << tzid;
    +        tzid = QString::fromNSString([enumerator nextObject]).toUtf8();
    +    }
    +
    +    std::sort(list.begin(), list.end());
    +    list.erase(std::unique(list.begin(), list.end()), list.end());
    +
    +    return list;
    +}
    +
    +NSTimeZone *QMacTimeZonePrivate::nsTimeZone() const
    +{
    +    return m_nstz;
    +}
    +
    +QT_END_NAMESPACE
    diff --git a/src/corelib/time/qtimezoneprivate_p.h b/src/corelib/time/qtimezoneprivate_p.h
    new file mode 100644
    index 0000000000..5f6491ef81
    --- /dev/null
    +++ b/src/corelib/time/qtimezoneprivate_p.h
    @@ -0,0 +1,493 @@
    +/****************************************************************************
    +**
    +** Copyright (C) 2013 John Layt 
    +** Contact: https://www.qt.io/licensing/
    +**
    +** This file is part of the QtCore module of the Qt Toolkit.
    +**
    +** $QT_BEGIN_LICENSE:LGPL$
    +** Commercial License Usage
    +** Licensees holding valid commercial Qt licenses may use this file in
    +** accordance with the commercial license agreement provided with the
    +** Software or, alternatively, in accordance with the terms contained in
    +** a written agreement between you and The Qt Company. For licensing terms
    +** and conditions see https://www.qt.io/terms-conditions. For further
    +** information use the contact form at https://www.qt.io/contact-us.
    +**
    +** GNU Lesser General Public License Usage
    +** Alternatively, this file may be used under the terms of the GNU Lesser
    +** General Public License version 3 as published by the Free Software
    +** Foundation and appearing in the file LICENSE.LGPL3 included in the
    +** packaging of this file. Please review the following information to
    +** ensure the GNU Lesser General Public License version 3 requirements
    +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
    +**
    +** GNU General Public License Usage
    +** Alternatively, this file may be used under the terms of the GNU
    +** General Public License version 2.0 or (at your option) the GNU General
    +** Public license version 3 or any later version approved by the KDE Free
    +** Qt Foundation. The licenses are as published by the Free Software
    +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
    +** included in the packaging of this file. Please review the following
    +** information to ensure the GNU General Public License requirements will
    +** be met: https://www.gnu.org/licenses/gpl-2.0.html and
    +** https://www.gnu.org/licenses/gpl-3.0.html.
    +**
    +** $QT_END_LICENSE$
    +**
    +****************************************************************************/
    +
    +
    +#ifndef QTIMEZONEPRIVATE_P_H
    +#define QTIMEZONEPRIVATE_P_H
    +
    +//
    +//  W A R N I N G
    +//  -------------
    +//
    +// This file is not part of the Qt API.  It exists for the convenience
    +// of internal files.  This header file may change from version to version
    +// without notice, or even be removed.
    +//
    +// We mean it.
    +//
    +
    +#include "qtimezone.h"
    +#include "private/qlocale_p.h"
    +#include "qvector.h"
    +
    +#if QT_CONFIG(icu)
    +#include 
    +#endif
    +
    +#ifdef Q_OS_DARWIN
    +Q_FORWARD_DECLARE_OBJC_CLASS(NSTimeZone);
    +#endif // Q_OS_DARWIN
    +
    +#ifdef Q_OS_WIN
    +#include 
    +#endif // Q_OS_WIN
    +
    +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
    +#include 
    +#endif
    +
    +QT_BEGIN_NAMESPACE
    +
    +class Q_AUTOTEST_EXPORT QTimeZonePrivate : public QSharedData
    +{
    +public:
    +    //Version of QTimeZone::OffsetData struct using msecs for efficiency
    +    struct Data {
    +        QString abbreviation;
    +        qint64 atMSecsSinceEpoch;
    +        int offsetFromUtc;
    +        int standardTimeOffset;
    +        int daylightTimeOffset;
    +    };
    +    typedef QVector DataList;
    +
    +    // Create null time zone
    +    QTimeZonePrivate();
    +    QTimeZonePrivate(const QTimeZonePrivate &other);
    +    virtual ~QTimeZonePrivate();
    +
    +    virtual QTimeZonePrivate *clone() const;
    +
    +    bool operator==(const QTimeZonePrivate &other) const;
    +    bool operator!=(const QTimeZonePrivate &other) const;
    +
    +    bool isValid() const;
    +
    +    QByteArray id() const;
    +    virtual QLocale::Country country() const;
    +    virtual QString comment() const;
    +
    +    virtual QString displayName(qint64 atMSecsSinceEpoch,
    +                                QTimeZone::NameType nameType,
    +                                const QLocale &locale) const;
    +    virtual QString displayName(QTimeZone::TimeType timeType,
    +                                QTimeZone::NameType nameType,
    +                                const QLocale &locale) const;
    +    virtual QString abbreviation(qint64 atMSecsSinceEpoch) const;
    +
    +    virtual int offsetFromUtc(qint64 atMSecsSinceEpoch) const;
    +    virtual int standardTimeOffset(qint64 atMSecsSinceEpoch) const;
    +    virtual int daylightTimeOffset(qint64 atMSecsSinceEpoch) const;
    +
    +    virtual bool hasDaylightTime() const;
    +    virtual bool isDaylightTime(qint64 atMSecsSinceEpoch) const;
    +
    +    virtual Data data(qint64 forMSecsSinceEpoch) const;
    +    Data dataForLocalTime(qint64 forLocalMSecs, int hint) const;
    +
    +    virtual bool hasTransitions() const;
    +    virtual Data nextTransition(qint64 afterMSecsSinceEpoch) const;
    +    virtual Data previousTransition(qint64 beforeMSecsSinceEpoch) const;
    +    DataList transitions(qint64 fromMSecsSinceEpoch, qint64 toMSecsSinceEpoch) const;
    +
    +    virtual QByteArray systemTimeZoneId() const;
    +
    +    virtual bool isTimeZoneIdAvailable(const QByteArray &ianaId) const;
    +    virtual QList availableTimeZoneIds() const;
    +    virtual QList availableTimeZoneIds(QLocale::Country country) const;
    +    virtual QList availableTimeZoneIds(int utcOffset) const;
    +
    +    virtual void serialize(QDataStream &ds) const;
    +
    +    // Static Utility Methods
    +    static inline qint64 maxMSecs() { return std::numeric_limits::max(); }
    +    static inline qint64 minMSecs() { return std::numeric_limits::min() + 1; }
    +    static inline qint64 invalidMSecs() { return std::numeric_limits::min(); }
    +    static inline qint64 invalidSeconds() { return std::numeric_limits::min(); }
    +    static Data invalidData();
    +    static QTimeZone::OffsetData invalidOffsetData();
    +    static QTimeZone::OffsetData toOffsetData(const Data &data);
    +    static bool isValidId(const QByteArray &ianaId);
    +    static QString isoOffsetFormat(int offsetFromUtc);
    +
    +    static QByteArray ianaIdToWindowsId(const QByteArray &ianaId);
    +    static QByteArray windowsIdToDefaultIanaId(const QByteArray &windowsId);
    +    static QByteArray windowsIdToDefaultIanaId(const QByteArray &windowsId,
    +                                                QLocale::Country country);
    +    static QList windowsIdToIanaIds(const QByteArray &windowsId);
    +    static QList windowsIdToIanaIds(const QByteArray &windowsId,
    +                                                 QLocale::Country country);
    +
    +    // returns "UTC" QString and QByteArray
    +    Q_REQUIRED_RESULT static inline QString utcQString()
    +    {
    +        return QStringLiteral("UTC");
    +    }
    +
    +    Q_REQUIRED_RESULT static inline QByteArray utcQByteArray()
    +    {
    +        return QByteArrayLiteral("UTC");
    +    }
    +
    +protected:
    +    QByteArray m_id;
    +};
    +Q_DECLARE_TYPEINFO(QTimeZonePrivate::Data, Q_MOVABLE_TYPE);
    +
    +template<> QTimeZonePrivate *QSharedDataPointer::clone();
    +
    +class Q_AUTOTEST_EXPORT QUtcTimeZonePrivate final : public QTimeZonePrivate
    +{
    +public:
    +    // Create default UTC time zone
    +    QUtcTimeZonePrivate();
    +    // Create named time zone
    +    QUtcTimeZonePrivate(const QByteArray &utcId);
    +    // Create offset from UTC
    +    QUtcTimeZonePrivate(int offsetSeconds);
    +    // Create custom offset from UTC
    +    QUtcTimeZonePrivate(const QByteArray &zoneId, int offsetSeconds, const QString &name,
    +                        const QString &abbreviation, QLocale::Country country,
    +                        const QString &comment);
    +    QUtcTimeZonePrivate(const QUtcTimeZonePrivate &other);
    +    virtual ~QUtcTimeZonePrivate();
    +
    +    QUtcTimeZonePrivate *clone() const override;
    +
    +    Data data(qint64 forMSecsSinceEpoch) const override;
    +
    +    QLocale::Country country() const override;
    +    QString comment() const override;
    +
    +    QString displayName(QTimeZone::TimeType timeType,
    +                        QTimeZone::NameType nameType,
    +                        const QLocale &locale) const override;
    +    QString abbreviation(qint64 atMSecsSinceEpoch) const override;
    +
    +    int standardTimeOffset(qint64 atMSecsSinceEpoch) const override;
    +    int daylightTimeOffset(qint64 atMSecsSinceEpoch) const override;
    +
    +    QByteArray systemTimeZoneId() const override;
    +
    +    bool isTimeZoneIdAvailable(const QByteArray &ianaId) const override;
    +    QList availableTimeZoneIds() const override;
    +    QList availableTimeZoneIds(QLocale::Country country) const override;
    +    QList availableTimeZoneIds(int utcOffset) const override;
    +
    +    void serialize(QDataStream &ds) const override;
    +
    +private:
    +    void init(const QByteArray &zoneId);
    +    void init(const QByteArray &zoneId, int offsetSeconds, const QString &name,
    +              const QString &abbreviation, QLocale::Country country,
    +              const QString &comment);
    +
    +    QString m_name;
    +    QString m_abbreviation;
    +    QString m_comment;
    +    QLocale::Country m_country;
    +    int m_offsetFromUtc;
    +};
    +
    +#if QT_CONFIG(icu)
    +class Q_AUTOTEST_EXPORT QIcuTimeZonePrivate final : public QTimeZonePrivate
    +{
    +public:
    +    // Create default time zone
    +    QIcuTimeZonePrivate();
    +    // Create named time zone
    +    QIcuTimeZonePrivate(const QByteArray &ianaId);
    +    QIcuTimeZonePrivate(const QIcuTimeZonePrivate &other);
    +    ~QIcuTimeZonePrivate();
    +
    +    QIcuTimeZonePrivate *clone() const override;
    +
    +    QString displayName(QTimeZone::TimeType timeType, QTimeZone::NameType nameType,
    +                        const QLocale &locale) const override;
    +    QString abbreviation(qint64 atMSecsSinceEpoch) const override;
    +
    +    int offsetFromUtc(qint64 atMSecsSinceEpoch) const override;
    +    int standardTimeOffset(qint64 atMSecsSinceEpoch) const override;
    +    int daylightTimeOffset(qint64 atMSecsSinceEpoch) const override;
    +
    +    bool hasDaylightTime() const override;
    +    bool isDaylightTime(qint64 atMSecsSinceEpoch) const override;
    +
    +    Data data(qint64 forMSecsSinceEpoch) const override;
    +
    +    bool hasTransitions() const override;
    +    Data nextTransition(qint64 afterMSecsSinceEpoch) const override;
    +    Data previousTransition(qint64 beforeMSecsSinceEpoch) const override;
    +
    +    QByteArray systemTimeZoneId() const override;
    +
    +    QList availableTimeZoneIds() const override;
    +    QList availableTimeZoneIds(QLocale::Country country) const override;
    +    QList availableTimeZoneIds(int offsetFromUtc) const override;
    +
    +private:
    +    void init(const QByteArray &ianaId);
    +
    +    UCalendar *m_ucal;
    +};
    +#endif
    +
    +#if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_EMBEDDED))
    +struct QTzTransitionTime
    +{
    +    qint64 atMSecsSinceEpoch;
    +    quint8 ruleIndex;
    +};
    +Q_DECLARE_TYPEINFO(QTzTransitionTime, Q_PRIMITIVE_TYPE);
    +struct QTzTransitionRule
    +{
    +    int stdOffset;
    +    int dstOffset;
    +    quint8 abbreviationIndex;
    +};
    +Q_DECLARE_TYPEINFO(QTzTransitionRule, Q_PRIMITIVE_TYPE);
    +Q_DECL_CONSTEXPR inline bool operator==(const QTzTransitionRule &lhs, const QTzTransitionRule &rhs) noexcept
    +{ return lhs.stdOffset == rhs.stdOffset && lhs.dstOffset == rhs.dstOffset && lhs.abbreviationIndex == rhs.abbreviationIndex; }
    +Q_DECL_CONSTEXPR inline bool operator!=(const QTzTransitionRule &lhs, const QTzTransitionRule &rhs) noexcept
    +{ return !operator==(lhs, rhs); }
    +
    +class Q_AUTOTEST_EXPORT QTzTimeZonePrivate final : public QTimeZonePrivate
    +{
    +    QTzTimeZonePrivate(const QTzTimeZonePrivate &) = default;
    +public:
    +    // Create default time zone
    +    QTzTimeZonePrivate();
    +    // Create named time zone
    +    QTzTimeZonePrivate(const QByteArray &ianaId);
    +    ~QTzTimeZonePrivate();
    +
    +    QTzTimeZonePrivate *clone() const override;
    +
    +    QLocale::Country country() const override;
    +    QString comment() const override;
    +
    +    QString displayName(qint64 atMSecsSinceEpoch,
    +                        QTimeZone::NameType nameType,
    +                        const QLocale &locale) const override;
    +    QString displayName(QTimeZone::TimeType timeType,
    +                        QTimeZone::NameType nameType,
    +                        const QLocale &locale) const override;
    +    QString abbreviation(qint64 atMSecsSinceEpoch) const override;
    +
    +    int offsetFromUtc(qint64 atMSecsSinceEpoch) const override;
    +    int standardTimeOffset(qint64 atMSecsSinceEpoch) const override;
    +    int daylightTimeOffset(qint64 atMSecsSinceEpoch) const override;
    +
    +    bool hasDaylightTime() const override;
    +    bool isDaylightTime(qint64 atMSecsSinceEpoch) const override;
    +
    +    Data data(qint64 forMSecsSinceEpoch) const override;
    +
    +    bool hasTransitions() const override;
    +    Data nextTransition(qint64 afterMSecsSinceEpoch) const override;
    +    Data previousTransition(qint64 beforeMSecsSinceEpoch) const override;
    +
    +    QByteArray systemTimeZoneId() const override;
    +
    +    bool isTimeZoneIdAvailable(const QByteArray &ianaId) const override;
    +    QList availableTimeZoneIds() const override;
    +    QList availableTimeZoneIds(QLocale::Country country) const override;
    +
    +private:
    +    void init(const QByteArray &ianaId);
    +    QVector getPosixTransitions(qint64 msNear) const;
    +
    +    Data dataForTzTransition(QTzTransitionTime tran) const;
    +    QVector m_tranTimes;
    +    QVector m_tranRules;
    +    QList m_abbreviations;
    +#if QT_CONFIG(icu)
    +    mutable QSharedDataPointer m_icu;
    +#endif
    +    QByteArray m_posixRule;
    +};
    +#endif // Q_OS_UNIX
    +
    +#ifdef Q_OS_MAC
    +class Q_AUTOTEST_EXPORT QMacTimeZonePrivate final : public QTimeZonePrivate
    +{
    +public:
    +    // Create default time zone
    +    QMacTimeZonePrivate();
    +    // Create named time zone
    +    QMacTimeZonePrivate(const QByteArray &ianaId);
    +    QMacTimeZonePrivate(const QMacTimeZonePrivate &other);
    +    ~QMacTimeZonePrivate();
    +
    +    QMacTimeZonePrivate *clone() const override;
    +
    +    QString comment() const override;
    +
    +    QString displayName(QTimeZone::TimeType timeType, QTimeZone::NameType nameType,
    +                        const QLocale &locale) const override;
    +    QString abbreviation(qint64 atMSecsSinceEpoch) const override;
    +
    +    int offsetFromUtc(qint64 atMSecsSinceEpoch) const override;
    +    int standardTimeOffset(qint64 atMSecsSinceEpoch) const override;
    +    int daylightTimeOffset(qint64 atMSecsSinceEpoch) const override;
    +
    +    bool hasDaylightTime() const override;
    +    bool isDaylightTime(qint64 atMSecsSinceEpoch) const override;
    +
    +    Data data(qint64 forMSecsSinceEpoch) const override;
    +
    +    bool hasTransitions() const override;
    +    Data nextTransition(qint64 afterMSecsSinceEpoch) const override;
    +    Data previousTransition(qint64 beforeMSecsSinceEpoch) const override;
    +
    +    QByteArray systemTimeZoneId() const override;
    +
    +    QList availableTimeZoneIds() const override;
    +
    +    NSTimeZone *nsTimeZone() const;
    +
    +private:
    +    void init(const QByteArray &zoneId);
    +
    +    NSTimeZone *m_nstz;
    +};
    +#endif // Q_OS_MAC
    +
    +#ifdef Q_OS_WIN
    +class Q_AUTOTEST_EXPORT QWinTimeZonePrivate final : public QTimeZonePrivate
    +{
    +public:
    +    struct QWinTransitionRule {
    +        int startYear;
    +        int standardTimeBias;
    +        int daylightTimeBias;
    +        SYSTEMTIME standardTimeRule;
    +        SYSTEMTIME daylightTimeRule;
    +    };
    +
    +    // Create default time zone
    +    QWinTimeZonePrivate();
    +    // Create named time zone
    +    QWinTimeZonePrivate(const QByteArray &ianaId);
    +    QWinTimeZonePrivate(const QWinTimeZonePrivate &other);
    +    ~QWinTimeZonePrivate();
    +
    +    QWinTimeZonePrivate *clone() const override;
    +
    +    QString comment() const override;
    +
    +    QString displayName(QTimeZone::TimeType timeType, QTimeZone::NameType nameType,
    +                        const QLocale &locale) const override;
    +    QString abbreviation(qint64 atMSecsSinceEpoch) const override;
    +
    +    int offsetFromUtc(qint64 atMSecsSinceEpoch) const override;
    +    int standardTimeOffset(qint64 atMSecsSinceEpoch) const override;
    +    int daylightTimeOffset(qint64 atMSecsSinceEpoch) const override;
    +
    +    bool hasDaylightTime() const override;
    +    bool isDaylightTime(qint64 atMSecsSinceEpoch) const override;
    +
    +    Data data(qint64 forMSecsSinceEpoch) const override;
    +
    +    bool hasTransitions() const override;
    +    Data nextTransition(qint64 afterMSecsSinceEpoch) const override;
    +    Data previousTransition(qint64 beforeMSecsSinceEpoch) const override;
    +
    +    QByteArray systemTimeZoneId() const override;
    +
    +    QList availableTimeZoneIds() const override;
    +
    +private:
    +    void init(const QByteArray &ianaId);
    +    QTimeZonePrivate::Data ruleToData(const QWinTransitionRule &rule, qint64 atMSecsSinceEpoch,
    +                                      QTimeZone::TimeType type, bool fakeDst = false) const;
    +
    +    QByteArray m_windowsId;
    +    QString m_displayName;
    +    QString m_standardName;
    +    QString m_daylightName;
    +    QList m_tranRules;
    +};
    +#endif // Q_OS_WIN
    +
    +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
    +class QAndroidTimeZonePrivate final : public QTimeZonePrivate
    +{
    +public:
    +    // Create default time zone
    +    QAndroidTimeZonePrivate();
    +    // Create named time zone
    +    QAndroidTimeZonePrivate(const QByteArray &ianaId);
    +    QAndroidTimeZonePrivate(const QAndroidTimeZonePrivate &other);
    +    ~QAndroidTimeZonePrivate();
    +
    +    QAndroidTimeZonePrivate *clone() const override;
    +
    +    QString displayName(QTimeZone::TimeType timeType, QTimeZone::NameType nameType,
    +                        const QLocale &locale) const override;
    +    QString abbreviation(qint64 atMSecsSinceEpoch) const override;
    +
    +    int offsetFromUtc(qint64 atMSecsSinceEpoch) const override;
    +    int standardTimeOffset(qint64 atMSecsSinceEpoch) const override;
    +    int daylightTimeOffset(qint64 atMSecsSinceEpoch) const override;
    +
    +    bool hasDaylightTime() const override;
    +    bool isDaylightTime(qint64 atMSecsSinceEpoch) const override;
    +
    +    Data data(qint64 forMSecsSinceEpoch) const override;
    +
    +    bool hasTransitions() const override;
    +    Data nextTransition(qint64 afterMSecsSinceEpoch) const override;
    +    Data previousTransition(qint64 beforeMSecsSinceEpoch) const override;
    +
    +    QByteArray systemTimeZoneId() const override;
    +
    +    QList availableTimeZoneIds() const override;
    +
    +private:
    +    void init(const QByteArray &zoneId);
    +
    +    QJNIObjectPrivate androidTimeZone;
    +
    +};
    +#endif // Q_OS_ANDROID
    +
    +QT_END_NAMESPACE
    +
    +#endif // QTIMEZONEPRIVATE_P_H
    diff --git a/src/corelib/time/qtimezoneprivate_tz.cpp b/src/corelib/time/qtimezoneprivate_tz.cpp
    new file mode 100644
    index 0000000000..2c845b1bce
    --- /dev/null
    +++ b/src/corelib/time/qtimezoneprivate_tz.cpp
    @@ -0,0 +1,1154 @@
    +/****************************************************************************
    +**
    +** Copyright (C) 2013 John Layt 
    +** Contact: https://www.qt.io/licensing/
    +**
    +** This file is part of the QtCore module of the Qt Toolkit.
    +**
    +** $QT_BEGIN_LICENSE:LGPL$
    +** Commercial License Usage
    +** Licensees holding valid commercial Qt licenses may use this file in
    +** accordance with the commercial license agreement provided with the
    +** Software or, alternatively, in accordance with the terms contained in
    +** a written agreement between you and The Qt Company. For licensing terms
    +** and conditions see https://www.qt.io/terms-conditions. For further
    +** information use the contact form at https://www.qt.io/contact-us.
    +**
    +** GNU Lesser General Public License Usage
    +** Alternatively, this file may be used under the terms of the GNU Lesser
    +** General Public License version 3 as published by the Free Software
    +** Foundation and appearing in the file LICENSE.LGPL3 included in the
    +** packaging of this file. Please review the following information to
    +** ensure the GNU Lesser General Public License version 3 requirements
    +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
    +**
    +** GNU General Public License Usage
    +** Alternatively, this file may be used under the terms of the GNU
    +** General Public License version 2.0 or (at your option) the GNU General
    +** Public license version 3 or any later version approved by the KDE Free
    +** Qt Foundation. The licenses are as published by the Free Software
    +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
    +** included in the packaging of this file. Please review the following
    +** information to ensure the GNU General Public License requirements will
    +** be met: https://www.gnu.org/licenses/gpl-2.0.html and
    +** https://www.gnu.org/licenses/gpl-3.0.html.
    +**
    +** $QT_END_LICENSE$
    +**
    +****************************************************************************/
    +
    +#include "qtimezone.h"
    +#include "qtimezoneprivate_p.h"
    +#include "qdatetime_p.h" // ### Qt 5.14: remove once YearRange is on QDateTime
    +#include "private/qlocale_tools_p.h"
    +
    +#include 
    +#include 
    +#include 
    +#include 
    +
    +#include 
    +
    +#include 
    +
    +QT_BEGIN_NAMESPACE
    +
    +/*
    +    Private
    +
    +    tz file implementation
    +*/
    +
    +struct QTzTimeZone {
    +    QLocale::Country country;
    +    QByteArray comment;
    +};
    +
    +// Define as a type as Q_GLOBAL_STATIC doesn't like it
    +typedef QHash QTzTimeZoneHash;
    +
    +// Parse zone.tab table, assume lists all installed zones, if not will need to read directories
    +static QTzTimeZoneHash loadTzTimeZones()
    +{
    +    QString path = QStringLiteral("/usr/share/zoneinfo/zone.tab");
    +    if (!QFile::exists(path))
    +        path = QStringLiteral("/usr/lib/zoneinfo/zone.tab");
    +
    +    QFile tzif(path);
    +    if (!tzif.open(QIODevice::ReadOnly))
    +        return QTzTimeZoneHash();
    +
    +    QTzTimeZoneHash zonesHash;
    +    // TODO QTextStream inefficient, replace later
    +    QTextStream ts(&tzif);
    +    while (!ts.atEnd()) {
    +        const QString line = ts.readLine();
    +        // Comment lines are prefixed with a #
    +        if (!line.isEmpty() && line.at(0) != '#') {
    +            // Data rows are tab-separated columns Region, Coordinates, ID, Optional Comments
    +            const auto parts = line.splitRef(QLatin1Char('\t'));
    +            QTzTimeZone zone;
    +            zone.country = QLocalePrivate::codeToCountry(parts.at(0));
    +            if (parts.size() > 3)
    +                zone.comment = parts.at(3).toUtf8();
    +            zonesHash.insert(parts.at(2).toUtf8(), zone);
    +        }
    +    }
    +    return zonesHash;
    +}
    +
    +// Hash of available system tz files as loaded by loadTzTimeZones()
    +Q_GLOBAL_STATIC_WITH_ARGS(const QTzTimeZoneHash, tzZones, (loadTzTimeZones()));
    +
    +/*
    +    The following is copied and modified from tzfile.h which is in the public domain.
    +    Copied as no compatibility guarantee and is never system installed.
    +    See https://github.com/eggert/tz/blob/master/tzfile.h
    +*/
    +
    +#define TZ_MAGIC      "TZif"
    +#define TZ_MAX_TIMES  1200
    +#define TZ_MAX_TYPES   256  // Limited by what (unsigned char)'s can hold
    +#define TZ_MAX_CHARS    50  // Maximum number of abbreviation characters
    +#define TZ_MAX_LEAPS    50  // Maximum number of leap second corrections
    +
    +struct QTzHeader {
    +    char       tzh_magic[4];        // TZ_MAGIC
    +    char       tzh_version;         // '\0' or '2' as of 2005
    +    char       tzh_reserved[15];    // reserved--must be zero
    +    quint32    tzh_ttisgmtcnt;      // number of trans. time flags
    +    quint32    tzh_ttisstdcnt;      // number of trans. time flags
    +    quint32    tzh_leapcnt;         // number of leap seconds
    +    quint32    tzh_timecnt;         // number of transition times
    +    quint32    tzh_typecnt;         // number of local time types
    +    quint32    tzh_charcnt;         // number of abbr. chars
    +};
    +
    +struct QTzTransition {
    +    qint64 tz_time;     // Transition time
    +    quint8 tz_typeind;  // Type Index
    +};
    +Q_DECLARE_TYPEINFO(QTzTransition, Q_PRIMITIVE_TYPE);
    +
    +struct QTzType {
    +    int tz_gmtoff;  // UTC offset in seconds
    +    bool   tz_isdst;   // Is DST
    +    quint8 tz_abbrind; // abbreviation list index
    +};
    +Q_DECLARE_TYPEINFO(QTzType, Q_PRIMITIVE_TYPE);
    +
    +
    +// TZ File parsing
    +
    +static QTzHeader parseTzHeader(QDataStream &ds, bool *ok)
    +{
    +    QTzHeader hdr;
    +    quint8 ch;
    +    *ok = false;
    +
    +    // Parse Magic, 4 bytes
    +    ds.readRawData(hdr.tzh_magic, 4);
    +
    +    if (memcmp(hdr.tzh_magic, TZ_MAGIC, 4) != 0 || ds.status() != QDataStream::Ok)
    +        return hdr;
    +
    +    // Parse Version, 1 byte, before 2005 was '\0', since 2005 a '2', since 2013 a '3'
    +    ds >> ch;
    +    hdr.tzh_version = ch;
    +    if (ds.status() != QDataStream::Ok
    +        || (hdr.tzh_version != '2' && hdr.tzh_version != '\0' && hdr.tzh_version != '3')) {
    +        return hdr;
    +    }
    +
    +    // Parse reserved space, 15 bytes
    +    ds.readRawData(hdr.tzh_reserved, 15);
    +    if (ds.status() != QDataStream::Ok)
    +        return hdr;
    +
    +    // Parse rest of header, 6 x 4-byte transition counts
    +    ds >> hdr.tzh_ttisgmtcnt >> hdr.tzh_ttisstdcnt >> hdr.tzh_leapcnt >> hdr.tzh_timecnt
    +       >> hdr.tzh_typecnt >> hdr.tzh_charcnt;
    +
    +    // Check defined maximums
    +    if (ds.status() != QDataStream::Ok
    +        || hdr.tzh_timecnt > TZ_MAX_TIMES
    +        || hdr.tzh_typecnt > TZ_MAX_TYPES
    +        || hdr.tzh_charcnt > TZ_MAX_CHARS
    +        || hdr.tzh_leapcnt > TZ_MAX_LEAPS
    +        || hdr.tzh_ttisgmtcnt > hdr.tzh_typecnt
    +        || hdr.tzh_ttisstdcnt > hdr.tzh_typecnt) {
    +        return hdr;
    +    }
    +
    +    *ok = true;
    +    return hdr;
    +}
    +
    +static QVector parseTzTransitions(QDataStream &ds, int tzh_timecnt, bool longTran)
    +{
    +    QVector transitions(tzh_timecnt);
    +
    +    if (longTran) {
    +        // Parse tzh_timecnt x 8-byte transition times
    +        for (int i = 0; i < tzh_timecnt && ds.status() == QDataStream::Ok; ++i) {
    +            ds >> transitions[i].tz_time;
    +            if (ds.status() != QDataStream::Ok)
    +                transitions.resize(i);
    +        }
    +    } else {
    +        // Parse tzh_timecnt x 4-byte transition times
    +        qint32 val;
    +        for (int i = 0; i < tzh_timecnt && ds.status() == QDataStream::Ok; ++i) {
    +            ds >> val;
    +            transitions[i].tz_time = val;
    +            if (ds.status() != QDataStream::Ok)
    +                transitions.resize(i);
    +        }
    +    }
    +
    +    // Parse tzh_timecnt x 1-byte transition type index
    +    for (int i = 0; i < tzh_timecnt && ds.status() == QDataStream::Ok; ++i) {
    +        quint8 typeind;
    +        ds >> typeind;
    +        if (ds.status() == QDataStream::Ok)
    +            transitions[i].tz_typeind = typeind;
    +    }
    +
    +    return transitions;
    +}
    +
    +static QVector parseTzTypes(QDataStream &ds, int tzh_typecnt)
    +{
    +    QVector types(tzh_typecnt);
    +
    +    // Parse tzh_typecnt x transition types
    +    for (int i = 0; i < tzh_typecnt && ds.status() == QDataStream::Ok; ++i) {
    +        QTzType &type = types[i];
    +        // Parse UTC Offset, 4 bytes
    +        ds >> type.tz_gmtoff;
    +        // Parse Is DST flag, 1 byte
    +        if (ds.status() == QDataStream::Ok)
    +            ds >> type.tz_isdst;
    +        // Parse Abbreviation Array Index, 1 byte
    +        if (ds.status() == QDataStream::Ok)
    +            ds >> type.tz_abbrind;
    +        if (ds.status() != QDataStream::Ok)
    +            types.resize(i);
    +    }
    +
    +    return types;
    +}
    +
    +static QMap parseTzAbbreviations(QDataStream &ds, int tzh_charcnt, const QVector &types)
    +{
    +    // Parse the abbreviation list which is tzh_charcnt long with '\0' separated strings. The
    +    // QTzType.tz_abbrind index points to the first char of the abbreviation in the array, not the
    +    // occurrence in the list. It can also point to a partial string so we need to use the actual typeList
    +    // index values when parsing.  By using a map with tz_abbrind as ordered key we get both index
    +    // methods in one data structure and can convert the types afterwards.
    +    QMap map;
    +    quint8 ch;
    +    QByteArray input;
    +    // First parse the full abbrev string
    +    for (int i = 0; i < tzh_charcnt && ds.status() == QDataStream::Ok; ++i) {
    +        ds >> ch;
    +        if (ds.status() == QDataStream::Ok)
    +            input.append(char(ch));
    +        else
    +            return map;
    +    }
    +    // Then extract all the substrings pointed to by types
    +    for (const QTzType &type : types) {
    +        QByteArray abbrev;
    +        for (int i = type.tz_abbrind; input.at(i) != '\0'; ++i)
    +            abbrev.append(input.at(i));
    +        // Have reached end of an abbreviation, so add to map
    +        map[type.tz_abbrind] = abbrev;
    +    }
    +    return map;
    +}
    +
    +static void parseTzLeapSeconds(QDataStream &ds, int tzh_leapcnt, bool longTran)
    +{
    +    // Parse tzh_leapcnt x pairs of leap seconds
    +    // We don't use leap seconds, so only read and don't store
    +    qint32 val;
    +    if (longTran) {
    +        // v2 file format, each entry is 12 bytes long
    +        qint64 time;
    +        for (int i = 0; i < tzh_leapcnt && ds.status() == QDataStream::Ok; ++i) {
    +            // Parse Leap Occurrence Time, 8 bytes
    +            ds >> time;
    +            // Parse Leap Seconds To Apply, 4 bytes
    +            if (ds.status() == QDataStream::Ok)
    +                ds >> val;
    +        }
    +    } else {
    +        // v0 file format, each entry is 8 bytes long
    +        for (int i = 0; i < tzh_leapcnt && ds.status() == QDataStream::Ok; ++i) {
    +            // Parse Leap Occurrence Time, 4 bytes
    +            ds >> val;
    +            // Parse Leap Seconds To Apply, 4 bytes
    +            if (ds.status() == QDataStream::Ok)
    +                ds >> val;
    +        }
    +    }
    +}
    +
    +static QVector parseTzIndicators(QDataStream &ds, const QVector &types, int tzh_ttisstdcnt, int tzh_ttisgmtcnt)
    +{
    +    QVector result = types;
    +    bool temp;
    +    /*
    +      Scan and discard indicators.
    +
    +      These indicators are only of use (by the date program) when "handling
    +      POSIX-style time zone environment variables".  The flags here say whether
    +      the *specification* of the zone gave the time in UTC, local standard time
    +      or local wall time; but whatever was specified has been digested for us,
    +      already, by the zone-info compiler (zic), so that the tz_time values read
    +      from the file (by parseTzTransitions) are all in UTC.
    +     */
    +
    +    // Scan tzh_ttisstdcnt x 1-byte standard/wall indicators
    +    for (int i = 0; i < tzh_ttisstdcnt && ds.status() == QDataStream::Ok; ++i)
    +        ds >> temp;
    +
    +    // Scan tzh_ttisgmtcnt x 1-byte UTC/local indicators
    +    for (int i = 0; i < tzh_ttisgmtcnt && ds.status() == QDataStream::Ok; ++i)
    +        ds >> temp;
    +
    +    return result;
    +}
    +
    +static QByteArray parseTzPosixRule(QDataStream &ds)
    +{
    +    // Parse POSIX rule, variable length '\n' enclosed
    +    QByteArray rule;
    +
    +    quint8 ch;
    +    ds >> ch;
    +    if (ch != '\n' || ds.status() != QDataStream::Ok)
    +        return rule;
    +    ds >> ch;
    +    while (ch != '\n' && ds.status() == QDataStream::Ok) {
    +        rule.append((char)ch);
    +        ds >> ch;
    +    }
    +
    +    return rule;
    +}
    +
    +static QDate calculateDowDate(int year, int month, int dayOfWeek, int week)
    +{
    +    QDate date(year, month, 1);
    +    int startDow = date.dayOfWeek();
    +    if (startDow <= dayOfWeek)
    +        date = date.addDays(dayOfWeek - startDow - 7);
    +    else
    +        date = date.addDays(dayOfWeek - startDow);
    +    date = date.addDays(week * 7);
    +    while (date.month() != month)
    +        date = date.addDays(-7);
    +    return date;
    +}
    +
    +static QDate calculatePosixDate(const QByteArray &dateRule, int year)
    +{
    +    // Can start with M, J, or a digit
    +    if (dateRule.at(0) == 'M') {
    +        // nth week in month format "Mmonth.week.dow"
    +        QList dateParts = dateRule.split('.');
    +        int month = dateParts.at(0).mid(1).toInt();
    +        int week = dateParts.at(1).toInt();
    +        int dow = dateParts.at(2).toInt();
    +        if (dow == 0)
    +            ++dow;
    +        return calculateDowDate(year, month, dow, week);
    +    } else if (dateRule.at(0) == 'J') {
    +        // Day of Year ignores Feb 29
    +        int doy = dateRule.mid(1).toInt();
    +        QDate date = QDate(year, 1, 1).addDays(doy - 1);
    +        if (QDate::isLeapYear(date.year()))
    +            date = date.addDays(-1);
    +        return date;
    +    } else {
    +        // Day of Year includes Feb 29
    +        int doy = dateRule.toInt();
    +        return QDate(year, 1, 1).addDays(doy - 1);
    +    }
    +}
    +
    +// returns the time in seconds, INT_MIN if we failed to parse
    +static int parsePosixTime(const char *begin, const char *end)
    +{
    +    // Format "hh[:mm[:ss]]"
    +    int hour, min = 0, sec = 0;
    +
    +    // Note that the calls to qstrtoll do *not* check the end pointer, which
    +    // means they proceed until they find a non-digit. We check that we're
    +    // still in range at the end, but we may have read from past end. It's the
    +    // caller's responsibility to ensure that begin is part of a
    +    // null-terminated string.
    +
    +    bool ok = false;
    +    hour = qstrtoll(begin, &begin, 10, &ok);
    +    if (!ok || hour < 0)
    +        return INT_MIN;
    +    if (begin < end && *begin == ':') {
    +        // minutes
    +        ++begin;
    +        min = qstrtoll(begin, &begin, 10, &ok);
    +        if (!ok || min < 0)
    +            return INT_MIN;
    +
    +        if (begin < end && *begin == ':') {
    +            // seconds
    +            ++begin;
    +            sec = qstrtoll(begin, &begin, 10, &ok);
    +            if (!ok || sec < 0)
    +                return INT_MIN;
    +        }
    +    }
    +
    +    // we must have consumed everything
    +    if (begin != end)
    +        return INT_MIN;
    +
    +    return (hour * 60 + min) * 60 + sec;
    +}
    +
    +static QTime parsePosixTransitionTime(const QByteArray &timeRule)
    +{
    +    // Format "hh[:mm[:ss]]"
    +    int value = parsePosixTime(timeRule.constBegin(), timeRule.constEnd());
    +    if (value == INT_MIN) {
    +        // if we failed to parse, return 02:00
    +        return QTime(2, 0, 0);
    +    }
    +    return QTime::fromMSecsSinceStartOfDay(value * 1000);
    +}
    +
    +static int parsePosixOffset(const char *begin, const char *end)
    +{
    +    // Format "[+|-]hh[:mm[:ss]]"
    +    // note that the sign is inverted because POSIX counts in hours West of GMT
    +    bool negate = true;
    +    if (*begin == '+') {
    +        ++begin;
    +    } else if (*begin == '-') {
    +        negate = false;
    +        ++begin;
    +    }
    +
    +    int value = parsePosixTime(begin, end);
    +    if (value == INT_MIN)
    +        return value;
    +    return negate ? -value : value;
    +}
    +
    +static inline bool asciiIsLetter(char ch)
    +{
    +    ch |= 0x20; // lowercases if it is a letter, otherwise just corrupts ch
    +    return ch >= 'a' && ch <= 'z';
    +}
    +
    +namespace {
    +
    +struct PosixZone
    +{
    +    enum {
    +        InvalidOffset = INT_MIN,
    +    };
    +
    +    QString name;
    +    int offset;
    +
    +    static PosixZone invalid() { return {QString(), InvalidOffset}; }
    +    static PosixZone parse(const char *&pos, const char *end);
    +
    +    bool hasValidOffset() const noexcept { return offset != InvalidOffset; }
    +};
    +
    +} // unnamed namespace
    +
    +// Returns the zone name, the offset (in seconds) and advances \a begin to
    +// where the parsing ended. Returns a zone of INT_MIN in case an offset
    +// couldn't be read.
    +PosixZone PosixZone::parse(const char *&pos, const char *end)
    +{
    +    static const char offsetChars[] = "0123456789:";
    +
    +    const char *nameBegin = pos;
    +    const char *nameEnd;
    +    Q_ASSERT(pos < end);
    +
    +    if (*pos == '<') {
    +        nameBegin = pos + 1;    // skip the '<'
    +        nameEnd = nameBegin;
    +        while (nameEnd < end && *nameEnd != '>') {
    +            // POSIX says only alphanumeric, but we allow anything
    +            ++nameEnd;
    +        }
    +        pos = nameEnd + 1;      // skip the '>'
    +    } else {
    +        nameBegin = pos;
    +        nameEnd = nameBegin;
    +        while (nameEnd < end && asciiIsLetter(*nameEnd))
    +            ++nameEnd;
    +        pos = nameEnd;
    +    }
    +    if (nameEnd - nameBegin < 3)
    +        return invalid();  // name must be at least 3 characters long
    +
    +    // zone offset, form [+-]hh:mm:ss
    +    const char *zoneBegin = pos;
    +    const char *zoneEnd = pos;
    +    if (zoneEnd < end && (zoneEnd[0] == '+' || zoneEnd[0] == '-'))
    +        ++zoneEnd;
    +    while (zoneEnd < end) {
    +        if (strchr(offsetChars, char(*zoneEnd)) == NULL)
    +            break;
    +        ++zoneEnd;
    +    }
    +
    +    QString name = QString::fromUtf8(nameBegin, nameEnd - nameBegin);
    +    const int offset = zoneEnd > zoneBegin ? parsePosixOffset(zoneBegin, zoneEnd) : InvalidOffset;
    +    pos = zoneEnd;
    +    // UTC+hh:mm:ss or GMT+hh:mm:ss should be read as offsets from UTC, not as a
    +    // POSIX rule naming a zone as UTC or GMT and specifying a non-zero offset.
    +    if (offset != 0 && (name == QLatin1String("UTC") || name == QLatin1String("GMT")))
    +        return invalid();
    +    return {std::move(name), offset};
    +}
    +
    +static QVector calculatePosixTransitions(const QByteArray &posixRule,
    +                                                                 int startYear, int endYear,
    +                                                                 qint64 lastTranMSecs)
    +{
    +    QVector result;
    +
    +    // POSIX Format is like "TZ=CST6CDT,M3.2.0/2:00:00,M11.1.0/2:00:00"
    +    // i.e. "std offset dst [offset],start[/time],end[/time]"
    +    // See the section about TZ at
    +    // http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html
    +    QList parts = posixRule.split(',');
    +
    +    PosixZone stdZone, dstZone = PosixZone::invalid();
    +    {
    +        const QByteArray &zoneinfo = parts.at(0);
    +        const char *begin = zoneinfo.constBegin();
    +
    +        stdZone = PosixZone::parse(begin, zoneinfo.constEnd());
    +        if (!stdZone.hasValidOffset()) {
    +            stdZone.offset = 0;     // reset to UTC if we failed to parse
    +        } else if (begin < zoneinfo.constEnd()) {
    +            dstZone = PosixZone::parse(begin, zoneinfo.constEnd());
    +            if (!dstZone.hasValidOffset()) {
    +                // if the dst offset isn't provided, it is 1 hour ahead of the standard offset
    +                dstZone.offset = stdZone.offset + (60 * 60);
    +            }
    +        }
    +    }
    +
    +    // If only the name part then no transitions
    +    if (parts.count() == 1) {
    +        QTimeZonePrivate::Data data;
    +        data.atMSecsSinceEpoch = lastTranMSecs;
    +        data.offsetFromUtc = stdZone.offset;
    +        data.standardTimeOffset = stdZone.offset;
    +        data.daylightTimeOffset = 0;
    +        data.abbreviation = stdZone.name;
    +        result << data;
    +        return result;
    +    }
    +
    +
    +    // Get the std to dst transtion details
    +    QList dstParts = parts.at(1).split('/');
    +    QByteArray dstDateRule = dstParts.at(0);
    +    QTime dstTime;
    +    if (dstParts.count() > 1)
    +        dstTime = parsePosixTransitionTime(dstParts.at(1));
    +    else
    +        dstTime = QTime(2, 0, 0);
    +
    +    // Get the dst to std transtion details
    +    QList stdParts = parts.at(2).split('/');
    +    QByteArray stdDateRule = stdParts.at(0);
    +    QTime stdTime;
    +    if (stdParts.count() > 1)
    +        stdTime = parsePosixTransitionTime(stdParts.at(1));
    +    else
    +        stdTime = QTime(2, 0, 0);
    +
    +    // Limit year to the range QDateTime can represent:
    +    const int minYear = int(QDateTimePrivate::YearRange::First);
    +    const int maxYear = int(QDateTimePrivate::YearRange::Last);
    +    startYear = qBound(minYear, startYear, maxYear);
    +    endYear = qBound(minYear, endYear, maxYear);
    +    Q_ASSERT(startYear <= endYear);
    +
    +    for (int year = startYear; year <= endYear; ++year) {
    +        QTimeZonePrivate::Data dstData;
    +        QDateTime dst(calculatePosixDate(dstDateRule, year), dstTime, Qt::UTC);
    +        dstData.atMSecsSinceEpoch = dst.toMSecsSinceEpoch() - (stdZone.offset * 1000);
    +        dstData.offsetFromUtc = dstZone.offset;
    +        dstData.standardTimeOffset = stdZone.offset;
    +        dstData.daylightTimeOffset = dstZone.offset - stdZone.offset;
    +        dstData.abbreviation = dstZone.name;
    +        QTimeZonePrivate::Data stdData;
    +        QDateTime std(calculatePosixDate(stdDateRule, year), stdTime, Qt::UTC);
    +        stdData.atMSecsSinceEpoch = std.toMSecsSinceEpoch() - (dstZone.offset * 1000);
    +        stdData.offsetFromUtc = stdZone.offset;
    +        stdData.standardTimeOffset = stdZone.offset;
    +        stdData.daylightTimeOffset = 0;
    +        stdData.abbreviation = stdZone.name;
    +        // Part of maxYear will overflow (likewise for minYear, below):
    +        if (year == maxYear && (dstData.atMSecsSinceEpoch < 0 || stdData.atMSecsSinceEpoch < 0)) {
    +            if (dstData.atMSecsSinceEpoch > 0) {
    +                result << dstData;
    +            } else if (stdData.atMSecsSinceEpoch > 0) {
    +                result << stdData;
    +            }
    +        } else if (year < 1970) { // We ignore DST before the epoch.
    +            if (year > minYear || stdData.atMSecsSinceEpoch != QTimeZonePrivate::invalidMSecs())
    +                result << stdData;
    +        } else if (dst < std) {
    +            result << dstData << stdData;
    +        } else {
    +            result << stdData << dstData;
    +        }
    +    }
    +    return result;
    +}
    +
    +// Create the system default time zone
    +QTzTimeZonePrivate::QTzTimeZonePrivate()
    +{
    +    init(systemTimeZoneId());
    +}
    +
    +// Create a named time zone
    +QTzTimeZonePrivate::QTzTimeZonePrivate(const QByteArray &ianaId)
    +{
    +    init(ianaId);
    +}
    +
    +QTzTimeZonePrivate::~QTzTimeZonePrivate()
    +{
    +}
    +
    +QTzTimeZonePrivate *QTzTimeZonePrivate::clone() const
    +{
    +    return new QTzTimeZonePrivate(*this);
    +}
    +
    +void QTzTimeZonePrivate::init(const QByteArray &ianaId)
    +{
    +    QFile tzif;
    +    if (ianaId.isEmpty()) {
    +        // Open system tz
    +        tzif.setFileName(QStringLiteral("/etc/localtime"));
    +        if (!tzif.open(QIODevice::ReadOnly))
    +            return;
    +    } else {
    +        // Open named tz, try modern path first, if fails try legacy path
    +        tzif.setFileName(QLatin1String("/usr/share/zoneinfo/") + QString::fromLocal8Bit(ianaId));
    +        if (!tzif.open(QIODevice::ReadOnly)) {
    +            tzif.setFileName(QLatin1String("/usr/lib/zoneinfo/") + QString::fromLocal8Bit(ianaId));
    +            if (!tzif.open(QIODevice::ReadOnly)) {
    +                // ianaId may be a POSIX rule, taken from $TZ or /etc/TZ
    +                const QByteArray zoneInfo = ianaId.split(',').at(0);
    +                const char *begin = zoneInfo.constBegin();
    +                if (PosixZone::parse(begin, zoneInfo.constEnd()).hasValidOffset()
    +                    && (begin == zoneInfo.constEnd()
    +                        || PosixZone::parse(begin, zoneInfo.constEnd()).hasValidOffset())) {
    +                    m_id = m_posixRule = ianaId;
    +                }
    +                return;
    +            }
    +        }
    +    }
    +
    +    QDataStream ds(&tzif);
    +
    +    // Parse the old version block of data
    +    bool ok = false;
    +    QTzHeader hdr = parseTzHeader(ds, &ok);
    +    if (!ok || ds.status() != QDataStream::Ok)
    +        return;
    +    QVector tranList = parseTzTransitions(ds, hdr.tzh_timecnt, false);
    +    if (ds.status() != QDataStream::Ok)
    +        return;
    +    QVector typeList = parseTzTypes(ds, hdr.tzh_typecnt);
    +    if (ds.status() != QDataStream::Ok)
    +        return;
    +    QMap abbrevMap = parseTzAbbreviations(ds, hdr.tzh_charcnt, typeList);
    +    if (ds.status() != QDataStream::Ok)
    +        return;
    +    parseTzLeapSeconds(ds, hdr.tzh_leapcnt, false);
    +    if (ds.status() != QDataStream::Ok)
    +        return;
    +    typeList = parseTzIndicators(ds, typeList, hdr.tzh_ttisstdcnt, hdr.tzh_ttisgmtcnt);
    +    if (ds.status() != QDataStream::Ok)
    +        return;
    +
    +    // If version 2 then parse the second block of data
    +    if (hdr.tzh_version == '2' || hdr.tzh_version == '3') {
    +        ok = false;
    +        QTzHeader hdr2 = parseTzHeader(ds, &ok);
    +        if (!ok || ds.status() != QDataStream::Ok)
    +            return;
    +        tranList = parseTzTransitions(ds, hdr2.tzh_timecnt, true);
    +        if (ds.status() != QDataStream::Ok)
    +            return;
    +        typeList = parseTzTypes(ds, hdr2.tzh_typecnt);
    +        if (ds.status() != QDataStream::Ok)
    +            return;
    +        abbrevMap = parseTzAbbreviations(ds, hdr2.tzh_charcnt, typeList);
    +        if (ds.status() != QDataStream::Ok)
    +            return;
    +        parseTzLeapSeconds(ds, hdr2.tzh_leapcnt, true);
    +        if (ds.status() != QDataStream::Ok)
    +            return;
    +        typeList = parseTzIndicators(ds, typeList, hdr2.tzh_ttisstdcnt, hdr2.tzh_ttisgmtcnt);
    +        if (ds.status() != QDataStream::Ok)
    +            return;
    +        m_posixRule = parseTzPosixRule(ds);
    +        if (ds.status() != QDataStream::Ok)
    +            return;
    +    }
    +
    +    // Translate the TZ file into internal format
    +
    +    // Translate the array index based tz_abbrind into list index
    +    const int size = abbrevMap.size();
    +    m_abbreviations.clear();
    +    m_abbreviations.reserve(size);
    +    QVector abbrindList;
    +    abbrindList.reserve(size);
    +    for (auto it = abbrevMap.cbegin(), end = abbrevMap.cend(); it != end; ++it) {
    +        m_abbreviations.append(it.value());
    +        abbrindList.append(it.key());
    +    }
    +    for (int i = 0; i < typeList.size(); ++i)
    +        typeList[i].tz_abbrind = abbrindList.indexOf(typeList.at(i).tz_abbrind);
    +
    +    // Offsets are stored as total offset, want to know separate UTC and DST offsets
    +    // so find the first non-dst transition to use as base UTC Offset
    +    int utcOffset = 0;
    +    for (const QTzTransition &tran : qAsConst(tranList)) {
    +        if (!typeList.at(tran.tz_typeind).tz_isdst) {
    +            utcOffset = typeList.at(tran.tz_typeind).tz_gmtoff;
    +            break;
    +        }
    +    }
    +
    +    // Now for each transition time calculate and store our rule:
    +    const int tranCount = tranList.count();;
    +    m_tranTimes.reserve(tranCount);
    +    // The DST offset when in effect: usually stable, usually an hour:
    +    int lastDstOff = 3600;
    +    for (int i = 0; i < tranCount; i++) {
    +        const QTzTransition &tz_tran = tranList.at(i);
    +        QTzTransitionTime tran;
    +        QTzTransitionRule rule;
    +        const QTzType tz_type = typeList.at(tz_tran.tz_typeind);
    +
    +        // Calculate the associated Rule
    +        if (!tz_type.tz_isdst) {
    +            utcOffset = tz_type.tz_gmtoff;
    +        } else if (Q_UNLIKELY(tz_type.tz_gmtoff != utcOffset + lastDstOff)) {
    +            /*
    +              This might be a genuine change in DST offset, but could also be
    +              DST starting at the same time as the standard offset changed.  See
    +              if DST's end gives a more plausible utcOffset (i.e. one closer to
    +              the last we saw, or a simple whole hour):
    +            */
    +            // Standard offset inferred from net offset and expected DST offset:
    +            const int inferStd = tz_type.tz_gmtoff - lastDstOff; // != utcOffset
    +            for (int j = i + 1; j < tranCount; j++) {
    +                const QTzType new_type = typeList.at(tranList.at(j).tz_typeind);
    +                if (!new_type.tz_isdst) {
    +                    const int newUtc = new_type.tz_gmtoff;
    +                    if (newUtc == utcOffset) {
    +                        // DST-end can't help us, avoid lots of messy checks.
    +                    // else: See if the end matches the familiar DST offset:
    +                    } else if (newUtc == inferStd) {
    +                        utcOffset = newUtc;
    +                    // else: let either end shift us to one hour as DST offset:
    +                    } else if (tz_type.tz_gmtoff - 3600 == utcOffset) {
    +                        // Start does it
    +                    } else if (tz_type.tz_gmtoff - 3600 == newUtc) {
    +                        utcOffset = newUtc; // End does it
    +                    // else: prefer whichever end gives DST offset closer to
    +                    // last, but consider any offset > 0 "closer" than any <= 0:
    +                    } else if (newUtc < tz_type.tz_gmtoff
    +                               ? (utcOffset >= tz_type.tz_gmtoff
    +                                  || qAbs(newUtc - inferStd) < qAbs(utcOffset - inferStd))
    +                               : (utcOffset >= tz_type.tz_gmtoff
    +                                  && qAbs(newUtc - inferStd) < qAbs(utcOffset - inferStd))) {
    +                        utcOffset = newUtc;
    +                    }
    +                    break;
    +                }
    +            }
    +            lastDstOff = tz_type.tz_gmtoff - utcOffset;
    +        }
    +        rule.stdOffset = utcOffset;
    +        rule.dstOffset = tz_type.tz_gmtoff - utcOffset;
    +        rule.abbreviationIndex = tz_type.tz_abbrind;
    +
    +        // If the rule already exist then use that, otherwise add it
    +        int ruleIndex = m_tranRules.indexOf(rule);
    +        if (ruleIndex == -1) {
    +            m_tranRules.append(rule);
    +            tran.ruleIndex = m_tranRules.size() - 1;
    +        } else {
    +            tran.ruleIndex = ruleIndex;
    +        }
    +
    +        tran.atMSecsSinceEpoch = tz_tran.tz_time * 1000;
    +        m_tranTimes.append(tran);
    +    }
    +    if (m_tranTimes.isEmpty() && m_posixRule.isEmpty())
    +        return; // Invalid after all !
    +
    +    if (ianaId.isEmpty())
    +        m_id = systemTimeZoneId();
    +    else
    +        m_id = ianaId;
    +}
    +
    +QLocale::Country QTzTimeZonePrivate::country() const
    +{
    +    return tzZones->value(m_id).country;
    +}
    +
    +QString QTzTimeZonePrivate::comment() const
    +{
    +    return QString::fromUtf8(tzZones->value(m_id).comment);
    +}
    +
    +QString QTzTimeZonePrivate::displayName(qint64 atMSecsSinceEpoch,
    +                                        QTimeZone::NameType nameType,
    +                                        const QLocale &locale) const
    +{
    +#if QT_CONFIG(icu)
    +    if (!m_icu)
    +        m_icu = new QIcuTimeZonePrivate(m_id);
    +    // TODO small risk may not match if tran times differ due to outdated files
    +    // TODO Some valid TZ names are not valid ICU names, use translation table?
    +    if (m_icu->isValid())
    +        return m_icu->displayName(atMSecsSinceEpoch, nameType, locale);
    +#else
    +    Q_UNUSED(nameType)
    +    Q_UNUSED(locale)
    +#endif
    +    return abbreviation(atMSecsSinceEpoch);
    +}
    +
    +QString QTzTimeZonePrivate::displayName(QTimeZone::TimeType timeType,
    +                                        QTimeZone::NameType nameType,
    +                                        const QLocale &locale) const
    +{
    +#if QT_CONFIG(icu)
    +    if (!m_icu)
    +        m_icu = new QIcuTimeZonePrivate(m_id);
    +    // TODO small risk may not match if tran times differ due to outdated files
    +    // TODO Some valid TZ names are not valid ICU names, use translation table?
    +    if (m_icu->isValid())
    +        return m_icu->displayName(timeType, nameType, locale);
    +#else
    +    Q_UNUSED(timeType)
    +    Q_UNUSED(nameType)
    +    Q_UNUSED(locale)
    +#endif
    +    // If no ICU available then have to use abbreviations instead
    +    // Abbreviations don't have GenericTime
    +    if (timeType == QTimeZone::GenericTime)
    +        timeType = QTimeZone::StandardTime;
    +
    +    // Get current tran, if valid and is what we want, then use it
    +    const qint64 currentMSecs = QDateTime::currentMSecsSinceEpoch();
    +    QTimeZonePrivate::Data tran = data(currentMSecs);
    +    if (tran.atMSecsSinceEpoch != invalidMSecs()
    +        && ((timeType == QTimeZone::DaylightTime && tran.daylightTimeOffset != 0)
    +        || (timeType == QTimeZone::StandardTime && tran.daylightTimeOffset == 0))) {
    +        return tran.abbreviation;
    +    }
    +
    +    // Otherwise get next tran and if valid and is what we want, then use it
    +    tran = nextTransition(currentMSecs);
    +    if (tran.atMSecsSinceEpoch != invalidMSecs()
    +        && ((timeType == QTimeZone::DaylightTime && tran.daylightTimeOffset != 0)
    +        || (timeType == QTimeZone::StandardTime && tran.daylightTimeOffset == 0))) {
    +        return tran.abbreviation;
    +    }
    +
    +    // Otherwise get prev tran and if valid and is what we want, then use it
    +    tran = previousTransition(currentMSecs);
    +    if (tran.atMSecsSinceEpoch != invalidMSecs())
    +        tran = previousTransition(tran.atMSecsSinceEpoch);
    +    if (tran.atMSecsSinceEpoch != invalidMSecs()
    +        && ((timeType == QTimeZone::DaylightTime && tran.daylightTimeOffset != 0)
    +        || (timeType == QTimeZone::StandardTime && tran.daylightTimeOffset == 0))) {
    +        return tran.abbreviation;
    +    }
    +
    +    // Otherwise is strange sequence, so work backwards through trans looking for first match, if any
    +    auto it = std::partition_point(m_tranTimes.cbegin(), m_tranTimes.cend(),
    +                                   [currentMSecs](const QTzTransitionTime &at) {
    +                                       return at.atMSecsSinceEpoch <= currentMSecs;
    +                                   });
    +
    +    while (it != m_tranTimes.cbegin()) {
    +        --it;
    +        tran = dataForTzTransition(*it);
    +        int offset = tran.daylightTimeOffset;
    +        if ((timeType == QTimeZone::DaylightTime) != (offset == 0))
    +            return tran.abbreviation;
    +    }
    +
    +    // Otherwise if no match use current data
    +    return data(currentMSecs).abbreviation;
    +}
    +
    +QString QTzTimeZonePrivate::abbreviation(qint64 atMSecsSinceEpoch) const
    +{
    +    return data(atMSecsSinceEpoch).abbreviation;
    +}
    +
    +int QTzTimeZonePrivate::offsetFromUtc(qint64 atMSecsSinceEpoch) const
    +{
    +    const QTimeZonePrivate::Data tran = data(atMSecsSinceEpoch);
    +    return tran.offsetFromUtc; // == tran.standardTimeOffset + tran.daylightTimeOffset
    +}
    +
    +int QTzTimeZonePrivate::standardTimeOffset(qint64 atMSecsSinceEpoch) const
    +{
    +    return data(atMSecsSinceEpoch).standardTimeOffset;
    +}
    +
    +int QTzTimeZonePrivate::daylightTimeOffset(qint64 atMSecsSinceEpoch) const
    +{
    +    return data(atMSecsSinceEpoch).daylightTimeOffset;
    +}
    +
    +bool QTzTimeZonePrivate::hasDaylightTime() const
    +{
    +    // TODO Perhaps cache as frequently accessed?
    +    for (const QTzTransitionRule &rule : m_tranRules) {
    +        if (rule.dstOffset != 0)
    +            return true;
    +    }
    +    return false;
    +}
    +
    +bool QTzTimeZonePrivate::isDaylightTime(qint64 atMSecsSinceEpoch) const
    +{
    +    return (daylightTimeOffset(atMSecsSinceEpoch) != 0);
    +}
    +
    +QTimeZonePrivate::Data QTzTimeZonePrivate::dataForTzTransition(QTzTransitionTime tran) const
    +{
    +    QTimeZonePrivate::Data data;
    +    data.atMSecsSinceEpoch = tran.atMSecsSinceEpoch;
    +    QTzTransitionRule rule = m_tranRules.at(tran.ruleIndex);
    +    data.standardTimeOffset = rule.stdOffset;
    +    data.daylightTimeOffset = rule.dstOffset;
    +    data.offsetFromUtc = rule.stdOffset + rule.dstOffset;
    +    data.abbreviation = QString::fromUtf8(m_abbreviations.at(rule.abbreviationIndex));
    +    return data;
    +}
    +
    +QVector QTzTimeZonePrivate::getPosixTransitions(qint64 msNear) const
    +{
    +    const int year = QDateTime::fromMSecsSinceEpoch(msNear, Qt::UTC).date().year();
    +    // The Data::atMSecsSinceEpoch of the single entry if zone is constant:
    +    qint64 atTime = m_tranTimes.isEmpty() ? msNear : m_tranTimes.last().atMSecsSinceEpoch;
    +    return calculatePosixTransitions(m_posixRule, year - 1, year + 1, atTime);
    +}
    +
    +QTimeZonePrivate::Data QTzTimeZonePrivate::data(qint64 forMSecsSinceEpoch) const
    +{
    +    // If the required time is after the last transition (or there were none)
    +    // and we have a POSIX rule, then use it:
    +    if (!m_posixRule.isEmpty()
    +        && (m_tranTimes.isEmpty() || m_tranTimes.last().atMSecsSinceEpoch < forMSecsSinceEpoch)) {
    +        QVector posixTrans = getPosixTransitions(forMSecsSinceEpoch);
    +        auto it = std::partition_point(posixTrans.cbegin(), posixTrans.cend(),
    +                                       [forMSecsSinceEpoch] (const QTimeZonePrivate::Data &at) {
    +                                           return at.atMSecsSinceEpoch <= forMSecsSinceEpoch;
    +                                       });
    +        // Use most recent, if any in the past; or the first if we have no other rules:
    +        if (it > posixTrans.cbegin() || (m_tranTimes.isEmpty() && it < posixTrans.cend())) {
    +            QTimeZonePrivate::Data data = *(it > posixTrans.cbegin() ? it - 1 : it);
    +            data.atMSecsSinceEpoch = forMSecsSinceEpoch;
    +            return data;
    +        }
    +    }
    +    if (m_tranTimes.isEmpty()) // Only possible if !isValid()
    +        return invalidData();
    +
    +    // Otherwise, use the rule for the most recent or first transition:
    +    auto last = std::partition_point(m_tranTimes.cbegin(), m_tranTimes.cend(),
    +                                     [forMSecsSinceEpoch] (const QTzTransitionTime &at) {
    +                                         return at.atMSecsSinceEpoch <= forMSecsSinceEpoch;
    +                                     });
    +    if (last > m_tranTimes.cbegin())
    +        --last;
    +    Data data = dataForTzTransition(*last);
    +    data.atMSecsSinceEpoch = forMSecsSinceEpoch;
    +    return data;
    +}
    +
    +bool QTzTimeZonePrivate::hasTransitions() const
    +{
    +    return true;
    +}
    +
    +QTimeZonePrivate::Data QTzTimeZonePrivate::nextTransition(qint64 afterMSecsSinceEpoch) const
    +{
    +    // If the required time is after the last transition (or there were none)
    +    // and we have a POSIX rule, then use it:
    +    if (!m_posixRule.isEmpty()
    +        && (m_tranTimes.isEmpty() || m_tranTimes.last().atMSecsSinceEpoch < afterMSecsSinceEpoch)) {
    +        QVector posixTrans = getPosixTransitions(afterMSecsSinceEpoch);
    +        auto it = std::partition_point(posixTrans.cbegin(), posixTrans.cend(),
    +                                       [afterMSecsSinceEpoch] (const QTimeZonePrivate::Data &at) {
    +                                           return at.atMSecsSinceEpoch <= afterMSecsSinceEpoch;
    +                                       });
    +
    +        return it == posixTrans.cend() ? invalidData() : *it;
    +    }
    +
    +    // Otherwise, if we can find a valid tran, use its rule:
    +    auto last = std::partition_point(m_tranTimes.cbegin(), m_tranTimes.cend(),
    +                                     [afterMSecsSinceEpoch] (const QTzTransitionTime &at) {
    +                                         return at.atMSecsSinceEpoch <= afterMSecsSinceEpoch;
    +                                     });
    +    return last != m_tranTimes.cend() ? dataForTzTransition(*last) : invalidData();
    +}
    +
    +QTimeZonePrivate::Data QTzTimeZonePrivate::previousTransition(qint64 beforeMSecsSinceEpoch) const
    +{
    +    // If the required time is after the last transition (or there were none)
    +    // and we have a POSIX rule, then use it:
    +    if (!m_posixRule.isEmpty()
    +        && (m_tranTimes.isEmpty() || m_tranTimes.last().atMSecsSinceEpoch < beforeMSecsSinceEpoch)) {
    +        QVector posixTrans = getPosixTransitions(beforeMSecsSinceEpoch);
    +        auto it = std::partition_point(posixTrans.cbegin(), posixTrans.cend(),
    +                                       [beforeMSecsSinceEpoch] (const QTimeZonePrivate::Data &at) {
    +                                           return at.atMSecsSinceEpoch < beforeMSecsSinceEpoch;
    +                                       });
    +        if (it > posixTrans.cbegin())
    +            return *--it;
    +        // It fell between the last transition (if any) and the first of the POSIX rule:
    +        return m_tranTimes.isEmpty() ? invalidData() : dataForTzTransition(m_tranTimes.last());
    +    }
    +
    +    // Otherwise if we can find a valid tran then use its rule
    +    auto last = std::partition_point(m_tranTimes.cbegin(), m_tranTimes.cend(),
    +                                     [beforeMSecsSinceEpoch] (const QTzTransitionTime &at) {
    +                                         return at.atMSecsSinceEpoch < beforeMSecsSinceEpoch;
    +                                     });
    +    return last > m_tranTimes.cbegin() ? dataForTzTransition(*--last) : invalidData();
    +}
    +
    +// TODO Could cache the value and monitor the required files for any changes
    +QByteArray QTzTimeZonePrivate::systemTimeZoneId() const
    +{
    +    // Check TZ env var first, if not populated try find it
    +    QByteArray ianaId = qgetenv("TZ");
    +    if (!ianaId.isEmpty() && ianaId.at(0) == ':')
    +        ianaId = ianaId.mid(1);
    +
    +    // The TZ value can be ":/etc/localtime" which libc considers
    +    // to be a "default timezone", in which case it will be read
    +    // by one of the blocks below, so unset it here so it is not
    +    // considered as a valid/found ianaId
    +    if (ianaId == "/etc/localtime")
    +        ianaId.clear();
    +
    +    // On most distros /etc/localtime is a symlink to a real file so extract name from the path
    +    if (ianaId.isEmpty()) {
    +        const QString path = QFile::symLinkTarget(QStringLiteral("/etc/localtime"));
    +        if (!path.isEmpty()) {
    +            // /etc/localtime is a symlink to the current TZ file, so extract from path
    +            int index = path.indexOf(QLatin1String("/zoneinfo/"));
    +            if (index != -1)
    +                ianaId = path.mid(index + 10).toUtf8();
    +        }
    +    }
    +
    +    // On Debian Etch up to Jessie, /etc/localtime is a regular file while the actual name is in /etc/timezone
    +    if (ianaId.isEmpty()) {
    +        QFile tzif(QStringLiteral("/etc/timezone"));
    +        if (tzif.open(QIODevice::ReadOnly)) {
    +            // TODO QTextStream inefficient, replace later
    +            QTextStream ts(&tzif);
    +            if (!ts.atEnd())
    +                ianaId = ts.readLine().toUtf8();
    +        }
    +    }
    +
    +    // On some Red Hat distros /etc/localtime is real file with name held in /etc/sysconfig/clock
    +    // in a line like ZONE="Europe/Oslo" or TIMEZONE="Europe/Oslo"
    +    if (ianaId.isEmpty()) {
    +        QFile tzif(QStringLiteral("/etc/sysconfig/clock"));
    +        if (tzif.open(QIODevice::ReadOnly)) {
    +            // TODO QTextStream inefficient, replace later
    +            QTextStream ts(&tzif);
    +            QString line;
    +            while (ianaId.isEmpty() && !ts.atEnd() && ts.status() == QTextStream::Ok) {
    +                line = ts.readLine();
    +                if (line.startsWith(QLatin1String("ZONE="))) {
    +                    ianaId = line.mid(6, line.size() - 7).toUtf8();
    +                } else if (line.startsWith(QLatin1String("TIMEZONE="))) {
    +                    ianaId = line.mid(10, line.size() - 11).toUtf8();
    +                }
    +            }
    +        }
    +    }
    +
    +    // Some systems (e.g. uClibc) have a default value for $TZ in /etc/TZ:
    +    if (ianaId.isEmpty()) {
    +        QFile zone(QStringLiteral("/etc/TZ"));
    +        if (zone.open(QIODevice::ReadOnly))
    +            ianaId = zone.readAll().trimmed();
    +    }
    +
    +    // Give up for now and return UTC
    +    if (ianaId.isEmpty())
    +        ianaId = utcQByteArray();
    +
    +    return ianaId;
    +}
    +
    +bool QTzTimeZonePrivate::isTimeZoneIdAvailable(const QByteArray &ianaId) const
    +{
    +    return tzZones->contains(ianaId);
    +}
    +
    +QList QTzTimeZonePrivate::availableTimeZoneIds() const
    +{
    +    QList result = tzZones->keys();
    +    std::sort(result.begin(), result.end());
    +    return result;
    +}
    +
    +QList QTzTimeZonePrivate::availableTimeZoneIds(QLocale::Country country) const
    +{
    +    // TODO AnyCountry
    +    QList result;
    +    for (auto it = tzZones->cbegin(), end = tzZones->cend(); it != end; ++it) {
    +        if (it.value().country == country)
    +            result << it.key();
    +    }
    +    std::sort(result.begin(), result.end());
    +    return result;
    +}
    +
    +QT_END_NAMESPACE
    diff --git a/src/corelib/time/qtimezoneprivate_win.cpp b/src/corelib/time/qtimezoneprivate_win.cpp
    new file mode 100644
    index 0000000000..1bf2366748
    --- /dev/null
    +++ b/src/corelib/time/qtimezoneprivate_win.cpp
    @@ -0,0 +1,927 @@
    +/****************************************************************************
    +**
    +** Copyright (C) 2013 John Layt 
    +** Contact: https://www.qt.io/licensing/
    +**
    +** This file is part of the QtCore module of the Qt Toolkit.
    +**
    +** $QT_BEGIN_LICENSE:LGPL$
    +** Commercial License Usage
    +** Licensees holding valid commercial Qt licenses may use this file in
    +** accordance with the commercial license agreement provided with the
    +** Software or, alternatively, in accordance with the terms contained in
    +** a written agreement between you and The Qt Company. For licensing terms
    +** and conditions see https://www.qt.io/terms-conditions. For further
    +** information use the contact form at https://www.qt.io/contact-us.
    +**
    +** GNU Lesser General Public License Usage
    +** Alternatively, this file may be used under the terms of the GNU Lesser
    +** General Public License version 3 as published by the Free Software
    +** Foundation and appearing in the file LICENSE.LGPL3 included in the
    +** packaging of this file. Please review the following information to
    +** ensure the GNU Lesser General Public License version 3 requirements
    +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
    +**
    +** GNU General Public License Usage
    +** Alternatively, this file may be used under the terms of the GNU
    +** General Public License version 2.0 or (at your option) the GNU General
    +** Public license version 3 or any later version approved by the KDE Free
    +** Qt Foundation. The licenses are as published by the Free Software
    +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
    +** included in the packaging of this file. Please review the following
    +** information to ensure the GNU General Public License requirements will
    +** be met: https://www.gnu.org/licenses/gpl-2.0.html and
    +** https://www.gnu.org/licenses/gpl-3.0.html.
    +**
    +** $QT_END_LICENSE$
    +**
    +****************************************************************************/
    +
    +#include "qtimezone.h"
    +#include "qtimezoneprivate_p.h"
    +
    +#include "qdatetime.h"
    +
    +#include "qdebug.h"
    +
    +#include 
    +
    +QT_BEGIN_NAMESPACE
    +
    +#ifndef Q_OS_WINRT
    +// The registry-based timezone backend is not available on WinRT, which falls back to equivalent APIs.
    +#define QT_USE_REGISTRY_TIMEZONE 1
    +#endif
    +
    +/*
    +    Private
    +
    +    Windows system implementation
    +*/
    +
    +#define MAX_KEY_LENGTH 255
    +#define FILETIME_UNIX_EPOCH Q_UINT64_C(116444736000000000)
    +
    +// MSDN home page for Time support
    +// http://msdn.microsoft.com/en-us/library/windows/desktop/ms724962%28v=vs.85%29.aspx
    +
    +// For Windows XP and later refer to MSDN docs on TIME_ZONE_INFORMATION structure
    +// http://msdn.microsoft.com/en-gb/library/windows/desktop/ms725481%28v=vs.85%29.aspx
    +
    +// Vista introduced support for historic data, see MSDN docs on DYNAMIC_TIME_ZONE_INFORMATION
    +// http://msdn.microsoft.com/en-gb/library/windows/desktop/ms724253%28v=vs.85%29.aspx
    +#ifdef QT_USE_REGISTRY_TIMEZONE
    +static const char tzRegPath[] = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones";
    +static const char currTzRegPath[] = "SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation";
    +#endif
    +
    +enum {
    +    MIN_YEAR = -292275056,
    +    MAX_YEAR = 292278994,
    +    MSECS_PER_DAY = 86400000,
    +    TIME_T_MAX = 2145916799,  // int maximum 2037-12-31T23:59:59 UTC
    +    JULIAN_DAY_FOR_EPOCH = 2440588 // result of julianDayFromDate(1970, 1, 1)
    +};
    +
    +// Copied from MSDN, see above for link
    +typedef struct _REG_TZI_FORMAT
    +{
    +    LONG Bias;
    +    LONG StandardBias;
    +    LONG DaylightBias;
    +    SYSTEMTIME StandardDate;
    +    SYSTEMTIME DaylightDate;
    +} REG_TZI_FORMAT;
    +
    +namespace {
    +
    +// Fast and reliable conversion from msecs to date for all values
    +// Adapted from QDateTime msecsToDate
    +QDate msecsToDate(qint64 msecs)
    +{
    +    qint64 jd = JULIAN_DAY_FOR_EPOCH;
    +
    +    if (qAbs(msecs) >= MSECS_PER_DAY) {
    +        jd += (msecs / MSECS_PER_DAY);
    +        msecs %= MSECS_PER_DAY;
    +    }
    +
    +    if (msecs < 0) {
    +        qint64 ds = MSECS_PER_DAY - msecs - 1;
    +        jd -= ds / MSECS_PER_DAY;
    +    }
    +
    +    return QDate::fromJulianDay(jd);
    +}
    +
    +bool equalSystemtime(const SYSTEMTIME &t1, const SYSTEMTIME &t2)
    +{
    +    return (t1.wYear == t2.wYear
    +            && t1.wMonth == t2.wMonth
    +            && t1.wDay == t2.wDay
    +            && t1.wDayOfWeek == t2.wDayOfWeek
    +            && t1.wHour == t2.wHour
    +            && t1.wMinute == t2.wMinute
    +            && t1.wSecond == t2.wSecond
    +            && t1.wMilliseconds == t2.wMilliseconds);
    +}
    +
    +bool equalTzi(const TIME_ZONE_INFORMATION &tzi1, const TIME_ZONE_INFORMATION &tzi2)
    +{
    +    return(tzi1.Bias == tzi2.Bias
    +           && tzi1.StandardBias == tzi2.StandardBias
    +           && equalSystemtime(tzi1.StandardDate, tzi2.StandardDate)
    +           && wcscmp(tzi1.StandardName, tzi2.StandardName) == 0
    +           && tzi1.DaylightBias == tzi2.DaylightBias
    +           && equalSystemtime(tzi1.DaylightDate, tzi2.DaylightDate)
    +           && wcscmp(tzi1.DaylightName, tzi2.DaylightName) == 0);
    +}
    +
    +#ifdef QT_USE_REGISTRY_TIMEZONE
    +bool openRegistryKey(const QString &keyPath, HKEY *key)
    +{
    +    return RegOpenKeyEx(HKEY_LOCAL_MACHINE, reinterpret_cast(keyPath.utf16()),
    +                        0, KEY_READ, key) == ERROR_SUCCESS;
    +}
    +
    +QString readRegistryString(const HKEY &key, const wchar_t *value)
    +{
    +    wchar_t buffer[MAX_PATH] = {0};
    +    DWORD size = sizeof(wchar_t) * MAX_PATH;
    +    RegQueryValueEx(key, value, nullptr, nullptr, reinterpret_cast(buffer), &size);
    +    return QString::fromWCharArray(buffer);
    +}
    +
    +int readRegistryValue(const HKEY &key, const wchar_t *value)
    +{
    +    DWORD buffer;
    +    DWORD size = sizeof(buffer);
    +    RegQueryValueEx(key, value, nullptr, nullptr, reinterpret_cast(&buffer), &size);
    +    return buffer;
    +}
    +
    +QWinTimeZonePrivate::QWinTransitionRule readRegistryRule(const HKEY &key,
    +                                                         const wchar_t *value, bool *ok)
    +{
    +    *ok = false;
    +    QWinTimeZonePrivate::QWinTransitionRule rule;
    +    REG_TZI_FORMAT tzi;
    +    DWORD tziSize = sizeof(tzi);
    +    if (RegQueryValueEx(key, value, nullptr, nullptr, reinterpret_cast(&tzi), &tziSize)
    +        == ERROR_SUCCESS) {
    +        rule.startYear = 0;
    +        rule.standardTimeBias = tzi.Bias + tzi.StandardBias;
    +        rule.daylightTimeBias = tzi.Bias + tzi.DaylightBias - rule.standardTimeBias;
    +        rule.standardTimeRule = tzi.StandardDate;
    +        rule.daylightTimeRule = tzi.DaylightDate;
    +        *ok = true;
    +    }
    +    return rule;
    +}
    +
    +TIME_ZONE_INFORMATION getRegistryTzi(const QByteArray &windowsId, bool *ok)
    +{
    +    *ok = false;
    +    TIME_ZONE_INFORMATION tzi;
    +    REG_TZI_FORMAT regTzi;
    +    DWORD regTziSize = sizeof(regTzi);
    +    HKEY key = NULL;
    +    const QString tziKeyPath = QString::fromUtf8(tzRegPath) + QLatin1Char('\\')
    +                               + QString::fromUtf8(windowsId);
    +
    +    if (openRegistryKey(tziKeyPath, &key)) {
    +
    +        DWORD size = sizeof(tzi.DaylightName);
    +        RegQueryValueEx(key, L"Dlt", nullptr, nullptr, reinterpret_cast(tzi.DaylightName), &size);
    +
    +        size = sizeof(tzi.StandardName);
    +        RegQueryValueEx(key, L"Std", nullptr, nullptr, reinterpret_cast(tzi.StandardName), &size);
    +
    +        if (RegQueryValueEx(key, L"TZI", nullptr, nullptr, reinterpret_cast(®Tzi), ®TziSize)
    +            == ERROR_SUCCESS) {
    +            tzi.Bias = regTzi.Bias;
    +            tzi.StandardBias = regTzi.StandardBias;
    +            tzi.DaylightBias = regTzi.DaylightBias;
    +            tzi.StandardDate = regTzi.StandardDate;
    +            tzi.DaylightDate = regTzi.DaylightDate;
    +            *ok = true;
    +        }
    +
    +        RegCloseKey(key);
    +    }
    +
    +    return tzi;
    +}
    +#else // QT_USE_REGISTRY_TIMEZONE
    +struct QWinDynamicTimeZone
    +{
    +    QString standardName;
    +    QString daylightName;
    +    QString timezoneName;
    +    qint32 bias;
    +    bool daylightTime;
    +};
    +
    +typedef QHash QWinRTTimeZoneHash;
    +
    +Q_GLOBAL_STATIC(QWinRTTimeZoneHash, gTimeZones)
    +
    +void enumerateTimeZones()
    +{
    +    DYNAMIC_TIME_ZONE_INFORMATION dtzInfo;
    +    quint32 index = 0;
    +    QString prevTimeZoneKeyName;
    +    while (SUCCEEDED(EnumDynamicTimeZoneInformation(index++, &dtzInfo))) {
    +        QWinDynamicTimeZone item;
    +        item.timezoneName = QString::fromWCharArray(dtzInfo.TimeZoneKeyName);
    +        // As soon as key name repeats, break. Some systems continue to always
    +        // return the last item independent of index being out of range
    +        if (item.timezoneName == prevTimeZoneKeyName)
    +            break;
    +        item.standardName = QString::fromWCharArray(dtzInfo.StandardName);
    +        item.daylightName = QString::fromWCharArray(dtzInfo.DaylightName);
    +        item.daylightTime = !dtzInfo.DynamicDaylightTimeDisabled;
    +        item.bias = dtzInfo.Bias;
    +        gTimeZones->insert(item.timezoneName.toUtf8(), item);
    +        prevTimeZoneKeyName = item.timezoneName;
    +    }
    +}
    +
    +DYNAMIC_TIME_ZONE_INFORMATION dynamicInfoForId(const QByteArray &windowsId)
    +{
    +    DYNAMIC_TIME_ZONE_INFORMATION dtzInfo;
    +    quint32 index = 0;
    +    QString prevTimeZoneKeyName;
    +    while (SUCCEEDED(EnumDynamicTimeZoneInformation(index++, &dtzInfo))) {
    +        const QString timeZoneName = QString::fromWCharArray(dtzInfo.TimeZoneKeyName);
    +        if (timeZoneName == QLatin1String(windowsId))
    +            break;
    +        if (timeZoneName == prevTimeZoneKeyName)
    +            break;
    +        prevTimeZoneKeyName = timeZoneName;
    +    }
    +    return dtzInfo;
    +}
    +
    +QWinTimeZonePrivate::QWinTransitionRule
    +readDynamicRule(DYNAMIC_TIME_ZONE_INFORMATION &dtzi, int year, bool *ok)
    +{
    +    TIME_ZONE_INFORMATION tzi;
    +    QWinTimeZonePrivate::QWinTransitionRule rule;
    +    *ok = GetTimeZoneInformationForYear(year, &dtzi, &tzi);
    +    if (*ok) {
    +        rule.startYear = 0;
    +        rule.standardTimeBias = tzi.Bias + tzi.StandardBias;
    +        rule.daylightTimeBias = tzi.Bias + tzi.DaylightBias - rule.standardTimeBias;
    +        rule.standardTimeRule = tzi.StandardDate;
    +        rule.daylightTimeRule = tzi.DaylightDate;
    +    }
    +    return rule;
    +}
    +#endif // QT_USE_REGISTRY_TIMEZONE
    +
    +bool isSameRule(const QWinTimeZonePrivate::QWinTransitionRule &last,
    +                       const QWinTimeZonePrivate::QWinTransitionRule &rule)
    +{
    +    // In particular, when this is true and either wYear is 0, so is the other;
    +    // so if one rule is recurrent and they're equal, so is the other.  If
    +    // either rule *isn't* recurrent, it has non-0 wYear which shall be
    +    // different from the other's.  Note that we don't compare .startYear, since
    +    // that will always be different.
    +    return equalSystemtime(last.standardTimeRule, rule.standardTimeRule)
    +        && equalSystemtime(last.daylightTimeRule, rule.daylightTimeRule)
    +        && last.standardTimeBias == rule.standardTimeBias
    +        && last.daylightTimeBias == rule.daylightTimeBias;
    +}
    +
    +QList availableWindowsIds()
    +{
    +#ifdef QT_USE_REGISTRY_TIMEZONE
    +    // TODO Consider caching results in a global static, very unlikely to change.
    +    QList list;
    +    HKEY key = NULL;
    +    if (openRegistryKey(QString::fromUtf8(tzRegPath), &key)) {
    +        DWORD idCount = 0;
    +        if (RegQueryInfoKey(key, 0, 0, 0, &idCount, 0, 0, 0, 0, 0, 0, 0) == ERROR_SUCCESS
    +            && idCount > 0) {
    +            for (DWORD i = 0; i < idCount; ++i) {
    +                DWORD maxLen = MAX_KEY_LENGTH;
    +                TCHAR buffer[MAX_KEY_LENGTH];
    +                if (RegEnumKeyEx(key, i, buffer, &maxLen, 0, 0, 0, 0) == ERROR_SUCCESS)
    +                    list.append(QString::fromWCharArray(buffer).toUtf8());
    +            }
    +        }
    +        RegCloseKey(key);
    +    }
    +    return list;
    +#else // QT_USE_REGISTRY_TIMEZONE
    +    if (gTimeZones->isEmpty())
    +        enumerateTimeZones();
    +    return gTimeZones->keys();
    +#endif // QT_USE_REGISTRY_TIMEZONE
    +}
    +
    +QByteArray windowsSystemZoneId()
    +{
    +#ifdef QT_USE_REGISTRY_TIMEZONE
    +    // On Vista and later is held in the value TimeZoneKeyName in key currTzRegPath
    +    QString id;
    +    HKEY key = NULL;
    +    QString tziKeyPath = QString::fromUtf8(currTzRegPath);
    +    if (openRegistryKey(tziKeyPath, &key)) {
    +        id = readRegistryString(key, L"TimeZoneKeyName");
    +        RegCloseKey(key);
    +        if (!id.isEmpty())
    +            return std::move(id).toUtf8();
    +    }
    +
    +    // On XP we have to iterate over the zones until we find a match on
    +    // names/offsets with the current data
    +    TIME_ZONE_INFORMATION sysTzi;
    +    GetTimeZoneInformation(&sysTzi);
    +    bool ok = false;
    +    const auto winIds = availableWindowsIds();
    +    for (const QByteArray &winId : winIds) {
    +        if (equalTzi(getRegistryTzi(winId, &ok), sysTzi))
    +            return winId;
    +    }
    +#else // QT_USE_REGISTRY_TIMEZONE
    +    DYNAMIC_TIME_ZONE_INFORMATION dtzi;
    +    if (SUCCEEDED(GetDynamicTimeZoneInformation(&dtzi)))
    +        return QString::fromWCharArray(dtzi.TimeZoneKeyName).toLocal8Bit();
    +#endif // QT_USE_REGISTRY_TIMEZONE
    +
    +    // If we can't determine the current ID use UTC
    +    return QTimeZonePrivate::utcQByteArray();
    +}
    +
    +QDate calculateTransitionLocalDate(const SYSTEMTIME &rule, int year)
    +{
    +    // If month is 0 then there is no date
    +    if (rule.wMonth == 0)
    +        return QDate();
    +
    +    // Interpret SYSTEMTIME according to the slightly quirky rules in:
    +    // https://msdn.microsoft.com/en-us/library/windows/desktop/ms725481(v=vs.85).aspx
    +
    +    // If the year is set, the rule gives an absolute date:
    +    if (rule.wYear)
    +        return QDate(rule.wYear, rule.wMonth, rule.wDay);
    +
    +    // Otherwise, the rule date is annual and relative:
    +    const int dayOfWeek = rule.wDayOfWeek == 0 ? 7 : rule.wDayOfWeek;
    +    QDate date(year, rule.wMonth, 1);
    +    // How many days before was last dayOfWeek before target month ?
    +    int adjust = dayOfWeek - date.dayOfWeek(); // -6 <= adjust < 7
    +    if (adjust >= 0) // Ensure -7 <= adjust < 0:
    +        adjust -= 7;
    +    // Normally, wDay is day-within-month; but here it is 1 for the first
    +    // of the given dayOfWeek in the month, through 4 for the fourth or ...
    +    adjust += (rule.wDay < 1 ? 1 : rule.wDay > 4 ? 5 : rule.wDay) * 7;
    +    date = date.addDays(adjust);
    +    // ... 5 for the last; so back up by weeks to get within the month:
    +    if (date.month() != rule.wMonth) {
    +        Q_ASSERT(rule.wDay > 4);
    +        // (Note that, with adjust < 0, date <= 28th of our target month
    +        // is guaranteed when wDay <= 4, or after our first -7 here.)
    +        date = date.addDays(-7);
    +        Q_ASSERT(date.month() == rule.wMonth);
    +    }
    +    return date;
    +}
    +
    +// Converts a date/time value into msecs
    +inline qint64 timeToMSecs(const QDate &date, const QTime &time)
    +{
    +    return ((date.toJulianDay() - JULIAN_DAY_FOR_EPOCH) * MSECS_PER_DAY)
    +           + time.msecsSinceStartOfDay();
    +}
    +
    +qint64 calculateTransitionForYear(const SYSTEMTIME &rule, int year, int bias)
    +{
    +    // TODO Consider caching the calculated values - i.e. replace SYSTEMTIME in
    +    // WinTransitionRule; do this in init() once and store the results.
    +    const QDate date = calculateTransitionLocalDate(rule, year);
    +    const QTime time = QTime(rule.wHour, rule.wMinute, rule.wSecond);
    +    if (date.isValid() && time.isValid())
    +        return timeToMSecs(date, time) + bias * 60000;
    +    return QTimeZonePrivate::invalidMSecs();
    +}
    +
    +struct TransitionTimePair
    +{
    +    // Transition times after the epoch, in ms:
    +    qint64 std, dst;
    +    // If either is invalidMSecs(), which shall then be < the other, there is no
    +    // DST and the other describes a change in actual standard offset.
    +
    +    TransitionTimePair(const QWinTimeZonePrivate::QWinTransitionRule &rule,
    +                       int year, int oldYearOffset)
    +        // The local time in Daylight Time of the switch to Standard Time
    +        : std(calculateTransitionForYear(rule.standardTimeRule, year,
    +                                         rule.standardTimeBias + rule.daylightTimeBias)),
    +          // The local time in Standard Time of the switch to Daylight Time
    +          dst(calculateTransitionForYear(rule.daylightTimeRule, year, rule.standardTimeBias))
    +    {
    +        /*
    +          Check for potential "fake DST", used by MS's APIs because the
    +          TIME_ZONE_INFORMATION spec either expresses no transitions in the
    +          year, or expresses a transition of each kind, even if standard time
    +          did change in a year with no DST.  We've seen year-start fake-DST
    +          (whose offset matches prior standard offset, in which the previous
    +          year ended); and conjecture that similar might be used at a year-end.
    +          (This might be used for a southern-hemisphere zone, where the start of
    +          the year usually is in DST, when applicable.)  Note that, here, wDay
    +          identifies an instance of a given day-of-week in the month, with 5
    +          meaning last.
    +
    +          Either the alleged standardTimeRule or the alleged daylightTimeRule
    +          may be faked; either way, the transition is actually a change to the
    +          current standard offset; but the unfaked half of the rule contains the
    +          useful bias data, so we have to go along with its lies.
    +
    +          Example: Russia/Moscow
    +          Format: -bias +( -stdBias, stdDate | -dstBias, dstDate ) notes
    +          Last year of DST, 2010: 180 +( 0, 0-10-5 3:0 | 60, 0-3-5 2:0 ) normal DST
    +          Zone change in 2011: 180 +( 0, 0-1-1 0:0 | 60 0-3-5 2:0 ) fake DST at transition
    +          Fixed standard in 2012: 240 +( 0, 0-0-0 0:0 | 60, 0-0-0 0:0 ) standard time years
    +          Zone change in 2014: 180 +( 0, 0-10-5 2:0 | 60, 0-1-1 0:0 ) fake DST at year-start
    +          The last of these is missing on Win7 VMs (too old to know about it).
    +        */
    +        if (rule.daylightTimeRule.wMonth == 1 && rule.daylightTimeRule.wDay == 1) {
    +            // Fake "DST transition" at start of year producing the same offset as
    +            // previous year ended in.
    +            if (rule.standardTimeBias + rule.daylightTimeBias == oldYearOffset)
    +                dst = QTimeZonePrivate::invalidMSecs();
    +        } else if (rule.daylightTimeRule.wMonth == 12 && rule.daylightTimeRule.wDay > 3) {
    +            // Similar, conjectured, for end of year, not changing offset.
    +            if (rule.daylightTimeBias == 0)
    +                dst = QTimeZonePrivate::invalidMSecs();
    +        }
    +        if (rule.standardTimeRule.wMonth == 1 && rule.standardTimeRule.wDay == 1) {
    +            // Fake "transition out of DST" at start of year producing the same
    +            // offset as previous year ended in.
    +            if (rule.standardTimeBias == oldYearOffset)
    +                std = QTimeZonePrivate::invalidMSecs();
    +        } else if (rule.standardTimeRule.wMonth == 12 && rule.standardTimeRule.wDay > 3) {
    +            // Similar, conjectured, for end of year, not changing offset.
    +            if (rule.daylightTimeBias == 0)
    +                std = QTimeZonePrivate::invalidMSecs();
    +        }
    +    }
    +
    +    bool fakesDst() const
    +    {
    +        return std == QTimeZonePrivate::invalidMSecs()
    +            || dst == QTimeZonePrivate::invalidMSecs();
    +    }
    +};
    +
    +int yearEndOffset(const QWinTimeZonePrivate::QWinTransitionRule &rule, int year)
    +{
    +    int offset = rule.standardTimeBias;
    +    // Only needed to help another TransitionTimePair work out year + 1's start
    +    // offset; and the oldYearOffset we use only affects an alleged transition
    +    // at the *start* of this year, so it doesn't matter if we guess wrong here:
    +    TransitionTimePair pair(rule, year, offset);
    +    if (pair.dst > pair.std)
    +        offset += rule.daylightTimeBias;
    +    return offset;
    +}
    +
    +QLocale::Country userCountry()
    +{
    +    const GEOID id = GetUserGeoID(GEOCLASS_NATION);
    +    wchar_t code[3];
    +    const int size = GetGeoInfo(id, GEO_ISO2, code, 3, 0);
    +    return (size == 3) ? QLocalePrivate::codeToCountry(QStringView(code, size))
    +                       : QLocale::AnyCountry;
    +}
    +
    +// Index of last rule in rules with .startYear <= year:
    +int ruleIndexForYear(const QList &rules, int year)
    +{
    +    if (rules.last().startYear <= year)
    +        return rules.count() - 1;
    +    // We don't have a rule for before the first, but the first is the best we can offer:
    +    if (rules.first().startYear > year)
    +        return 0;
    +
    +    // Otherwise, use binary chop:
    +    int lo = 0, hi = rules.count();
    +    // invariant: rules[i].startYear <= year < rules[hi].startYear
    +    // subject to treating rules[rules.count()] as "off the end of time"
    +    while (lo + 1 < hi) {
    +        const int mid = (lo + hi) / 2;
    +        // lo + 2 <= hi, so lo + 1 <= mid <= hi - 1, so lo < mid < hi
    +        // In particular, mid < rules.count()
    +        const int midYear = rules.at(mid).startYear;
    +        if (midYear > year)
    +            hi = mid;
    +        else if (midYear < year)
    +            lo = mid;
    +        else // No two rules have the same startYear:
    +            return mid;
    +    }
    +    return lo;
    +}
    +
    +} // anonymous namespace
    +
    +// Create the system default time zone
    +QWinTimeZonePrivate::QWinTimeZonePrivate()
    +                   : QTimeZonePrivate()
    +{
    +    init(QByteArray());
    +}
    +
    +// Create a named time zone
    +QWinTimeZonePrivate::QWinTimeZonePrivate(const QByteArray &ianaId)
    +                   : QTimeZonePrivate()
    +{
    +    init(ianaId);
    +}
    +
    +QWinTimeZonePrivate::QWinTimeZonePrivate(const QWinTimeZonePrivate &other)
    +                   : QTimeZonePrivate(other), m_windowsId(other.m_windowsId),
    +                     m_displayName(other.m_displayName), m_standardName(other.m_standardName),
    +                     m_daylightName(other.m_daylightName), m_tranRules(other.m_tranRules)
    +{
    +}
    +
    +QWinTimeZonePrivate::~QWinTimeZonePrivate()
    +{
    +}
    +
    +QWinTimeZonePrivate *QWinTimeZonePrivate::clone() const
    +{
    +    return new QWinTimeZonePrivate(*this);
    +}
    +
    +void QWinTimeZonePrivate::init(const QByteArray &ianaId)
    +{
    +    if (ianaId.isEmpty()) {
    +        m_windowsId = windowsSystemZoneId();
    +        m_id = systemTimeZoneId();
    +    } else {
    +        m_windowsId = ianaIdToWindowsId(ianaId);
    +        m_id = ianaId;
    +    }
    +
    +    bool badMonth = false; // Only warn once per zone, if at all.
    +    if (!m_windowsId.isEmpty()) {
    +#ifdef QT_USE_REGISTRY_TIMEZONE
    +        // Open the base TZI for the time zone
    +        HKEY baseKey = NULL;
    +        const QString baseKeyPath = QString::fromUtf8(tzRegPath) + QLatin1Char('\\')
    +                                   + QString::fromUtf8(m_windowsId);
    +        if (openRegistryKey(baseKeyPath, &baseKey)) {
    +            //  Load the localized names
    +            m_displayName = readRegistryString(baseKey, L"Display");
    +            m_standardName = readRegistryString(baseKey, L"Std");
    +            m_daylightName = readRegistryString(baseKey, L"Dlt");
    +            // On Vista and later the optional dynamic key holds historic data
    +            const QString dynamicKeyPath = baseKeyPath + QLatin1String("\\Dynamic DST");
    +            HKEY dynamicKey = NULL;
    +            if (openRegistryKey(dynamicKeyPath, &dynamicKey)) {
    +                // Find out the start and end years stored, then iterate over them
    +                int startYear = readRegistryValue(dynamicKey, L"FirstEntry");
    +                int endYear = readRegistryValue(dynamicKey, L"LastEntry");
    +                for (int year = startYear; year <= endYear; ++year) {
    +                    bool ruleOk;
    +                    QWinTransitionRule rule = readRegistryRule(dynamicKey,
    +                                                               reinterpret_cast(QString::number(year).utf16()),
    +                                                               &ruleOk);
    +                    if (ruleOk
    +                        // Don't repeat a recurrent rule:
    +                        && (m_tranRules.isEmpty()
    +                            || !isSameRule(m_tranRules.last(), rule))) {
    +                        if (!badMonth
    +                            && (rule.standardTimeRule.wMonth == 0)
    +                            != (rule.daylightTimeRule.wMonth == 0)) {
    +                            badMonth = true;
    +                            qWarning("MS registry TZ API violated its wMonth constraint;"
    +                                     "this may cause mistakes for %s from %d",
    +                                     ianaId.constData(), year);
    +                        }
    +                        rule.startYear = m_tranRules.isEmpty() ? MIN_YEAR : year;
    +                        m_tranRules.append(rule);
    +                    }
    +                }
    +                RegCloseKey(dynamicKey);
    +            } else {
    +                // No dynamic data so use the base data
    +                bool ruleOk;
    +                QWinTransitionRule rule = readRegistryRule(baseKey, L"TZI", &ruleOk);
    +                rule.startYear = MIN_YEAR;
    +                if (ruleOk)
    +                    m_tranRules.append(rule);
    +            }
    +            RegCloseKey(baseKey);
    +        }
    +#else // QT_USE_REGISTRY_TIMEZONE
    +        if (gTimeZones->isEmpty())
    +            enumerateTimeZones();
    +        QWinRTTimeZoneHash::const_iterator it = gTimeZones->find(m_windowsId);
    +        if (it != gTimeZones->constEnd()) {
    +            m_displayName = it->timezoneName;
    +            m_standardName = it->standardName;
    +            m_daylightName = it->daylightName;
    +            DWORD firstYear = 0;
    +            DWORD lastYear = 0;
    +            DYNAMIC_TIME_ZONE_INFORMATION dtzi = dynamicInfoForId(m_windowsId);
    +            if (GetDynamicTimeZoneInformationEffectiveYears(&dtzi, &firstYear, &lastYear)
    +                == ERROR_SUCCESS && firstYear < lastYear) {
    +                for (DWORD year = firstYear; year <= lastYear; ++year) {
    +                    bool ok = false;
    +                    QWinTransitionRule rule = readDynamicRule(dtzi, year, &ok);
    +                    if (ok
    +                        // Don't repeat a recurrent rule
    +                        && (m_tranRules.isEmpty()
    +                            || !isSameRule(m_tranRules.last(), rule))) {
    +                        if (!badMonth
    +                            && (rule.standardTimeRule.wMonth == 0)
    +                            != (rule.daylightTimeRule.wMonth == 0)) {
    +                            badMonth = true;
    +                            qWarning("MS dynamic TZ API violated its wMonth constraint;"
    +                                     "this may cause mistakes for %s from %d",
    +                                     ianaId.constData(), year);
    +                        }
    +                        rule.startYear = m_tranRules.isEmpty() ? MIN_YEAR : year;
    +                        m_tranRules.append(rule);
    +                    }
    +                }
    +            } else {
    +                // At least try to get the non-dynamic data:
    +                dtzi.DynamicDaylightTimeDisabled = false;
    +                bool ok = false;
    +                QWinTransitionRule rule = readDynamicRule(dtzi, 1970, &ok);
    +                if (ok) {
    +                    rule.startYear = MIN_YEAR;
    +                    m_tranRules.append(rule);
    +                }
    +            }
    +        }
    +#endif // QT_USE_REGISTRY_TIMEZONE
    +    }
    +
    +    // If there are no rules then we failed to find a windowsId or any tzi info
    +    if (m_tranRules.size() == 0) {
    +        m_id.clear();
    +        m_windowsId.clear();
    +        m_displayName.clear();
    +    }
    +}
    +
    +QString QWinTimeZonePrivate::comment() const
    +{
    +    return m_displayName;
    +}
    +
    +QString QWinTimeZonePrivate::displayName(QTimeZone::TimeType timeType,
    +                                         QTimeZone::NameType nameType,
    +                                         const QLocale &locale) const
    +{
    +    // TODO Registry holds MUI keys, should be able to look up translations?
    +    Q_UNUSED(locale);
    +
    +    if (nameType == QTimeZone::OffsetName) {
    +        const QWinTransitionRule &rule =
    +            m_tranRules.at(ruleIndexForYear(m_tranRules, QDate::currentDate().year()));
    +        int offset = rule.standardTimeBias;
    +        if (timeType == QTimeZone::DaylightTime)
    +            offset += rule.daylightTimeBias;
    +        return isoOffsetFormat(offset * -60);
    +    }
    +
    +    switch (timeType) {
    +    case  QTimeZone::DaylightTime :
    +        return m_daylightName;
    +    case  QTimeZone::GenericTime :
    +        return m_displayName;
    +    case  QTimeZone::StandardTime :
    +        return m_standardName;
    +    }
    +    return m_standardName;
    +}
    +
    +QString QWinTimeZonePrivate::abbreviation(qint64 atMSecsSinceEpoch) const
    +{
    +    return data(atMSecsSinceEpoch).abbreviation;
    +}
    +
    +int QWinTimeZonePrivate::offsetFromUtc(qint64 atMSecsSinceEpoch) const
    +{
    +    return data(atMSecsSinceEpoch).offsetFromUtc;
    +}
    +
    +int QWinTimeZonePrivate::standardTimeOffset(qint64 atMSecsSinceEpoch) const
    +{
    +    return data(atMSecsSinceEpoch).standardTimeOffset;
    +}
    +
    +int QWinTimeZonePrivate::daylightTimeOffset(qint64 atMSecsSinceEpoch) const
    +{
    +    return data(atMSecsSinceEpoch).daylightTimeOffset;
    +}
    +
    +bool QWinTimeZonePrivate::hasDaylightTime() const
    +{
    +    return hasTransitions();
    +}
    +
    +bool QWinTimeZonePrivate::isDaylightTime(qint64 atMSecsSinceEpoch) const
    +{
    +    return (data(atMSecsSinceEpoch).daylightTimeOffset != 0);
    +}
    +
    +QTimeZonePrivate::Data QWinTimeZonePrivate::data(qint64 forMSecsSinceEpoch) const
    +{
    +    int year = msecsToDate(forMSecsSinceEpoch).year();
    +    for (int ruleIndex = ruleIndexForYear(m_tranRules, year);
    +         ruleIndex >= 0; --ruleIndex) {
    +        const QWinTransitionRule &rule = m_tranRules.at(ruleIndex);
    +        // Does this rule's period include any transition at all ?
    +        if (rule.standardTimeRule.wMonth > 0 || rule.daylightTimeRule.wMonth > 0) {
    +            const int endYear = qMax(rule.startYear, year - 1);
    +            while (year >= endYear) {
    +                const int newYearOffset = (year <= rule.startYear && ruleIndex > 0)
    +                    ? yearEndOffset(m_tranRules.at(ruleIndex - 1), year - 1)
    +                    : yearEndOffset(rule, year - 1);
    +                const TransitionTimePair pair(rule, year, newYearOffset);
    +                bool isDst = false;
    +                if (pair.std != invalidMSecs() && pair.std <= forMSecsSinceEpoch) {
    +                    isDst = pair.std < pair.dst && pair.dst <= forMSecsSinceEpoch;
    +                } else if (pair.dst != invalidMSecs() && pair.dst <= forMSecsSinceEpoch) {
    +                    isDst = true;
    +                } else {
    +                    --year; // Try an earlier year for this rule (once).
    +                    continue;
    +                }
    +                return ruleToData(rule, forMSecsSinceEpoch,
    +                                  isDst ? QTimeZone::DaylightTime : QTimeZone::StandardTime,
    +                                  pair.fakesDst());
    +            }
    +            // Fell off start of rule, try previous rule.
    +        } else {
    +            // No transition, no DST, use the year's standard time.
    +            return ruleToData(rule, forMSecsSinceEpoch, QTimeZone::StandardTime);
    +        }
    +        if (year >= rule.startYear)
    +            year = rule.startYear - 1; // Seek last transition in new rule.
    +    }
    +    // We don't have relevant data :-(
    +    return invalidData();
    +}
    +
    +bool QWinTimeZonePrivate::hasTransitions() const
    +{
    +    for (const QWinTransitionRule &rule : m_tranRules) {
    +        if (rule.standardTimeRule.wMonth > 0 && rule.daylightTimeRule.wMonth > 0)
    +            return true;
    +    }
    +    return false;
    +}
    +
    +QTimeZonePrivate::Data QWinTimeZonePrivate::nextTransition(qint64 afterMSecsSinceEpoch) const
    +{
    +    int year = msecsToDate(afterMSecsSinceEpoch).year();
    +    for (int ruleIndex = ruleIndexForYear(m_tranRules, year);
    +         ruleIndex < m_tranRules.count(); ++ruleIndex) {
    +        const QWinTransitionRule &rule = m_tranRules.at(ruleIndex);
    +        // Does this rule's period include any transition at all ?
    +        if (rule.standardTimeRule.wMonth > 0 || rule.daylightTimeRule.wMonth > 0) {
    +            if (year < rule.startYear)
    +                year = rule.startYear; // Seek first transition in this rule.
    +            const int endYear = ruleIndex + 1 < m_tranRules.count()
    +                ? qMin(m_tranRules.at(ruleIndex + 1).startYear, year + 2) : (year + 2);
    +            int newYearOffset = (year <= rule.startYear && ruleIndex > 0)
    +                ? yearEndOffset(m_tranRules.at(ruleIndex - 1), year - 1)
    +                : yearEndOffset(rule, year - 1);
    +            while (year < endYear) {
    +                const TransitionTimePair pair(rule, year, newYearOffset);
    +                bool isDst = false;
    +                Q_ASSERT(invalidMSecs() <= afterMSecsSinceEpoch); // invalid is min qint64
    +                if (pair.std > afterMSecsSinceEpoch) {
    +                    isDst = pair.std > pair.dst && pair.dst > afterMSecsSinceEpoch;
    +                } else if (pair.dst > afterMSecsSinceEpoch) {
    +                    isDst = true;
    +                } else {
    +                    newYearOffset = rule.standardTimeBias;
    +                    if (pair.dst > pair.std)
    +                        newYearOffset += rule.daylightTimeBias;
    +                    ++year; // Try a later year for this rule (once).
    +                    continue;
    +                }
    +
    +                if (isDst)
    +                    return ruleToData(rule, pair.dst, QTimeZone::DaylightTime, pair.fakesDst());
    +                return ruleToData(rule, pair.std, QTimeZone::StandardTime, pair.fakesDst());
    +            }
    +            // Fell off end of rule, try next rule.
    +        } // else: no transition during rule's period
    +    }
    +    // Apparently no transition after the given time:
    +    return invalidData();
    +}
    +
    +QTimeZonePrivate::Data QWinTimeZonePrivate::previousTransition(qint64 beforeMSecsSinceEpoch) const
    +{
    +    const qint64 startOfTime = invalidMSecs() + 1;
    +    if (beforeMSecsSinceEpoch <= startOfTime)
    +        return invalidData();
    +
    +    int year = msecsToDate(beforeMSecsSinceEpoch).year();
    +    for (int ruleIndex = ruleIndexForYear(m_tranRules, year);
    +         ruleIndex >= 0; --ruleIndex) {
    +        const QWinTransitionRule &rule = m_tranRules.at(ruleIndex);
    +        // Does this rule's period include any transition at all ?
    +        if (rule.standardTimeRule.wMonth > 0 || rule.daylightTimeRule.wMonth > 0) {
    +            const int endYear = qMax(rule.startYear, year - 1);
    +            while (year >= endYear) {
    +                const int newYearOffset = (year <= rule.startYear && ruleIndex > 0)
    +                    ? yearEndOffset(m_tranRules.at(ruleIndex - 1), year - 1)
    +                    : yearEndOffset(rule, year - 1);
    +                const TransitionTimePair pair(rule, year, newYearOffset);
    +                bool isDst = false;
    +                if (pair.std != invalidMSecs() && pair.std < beforeMSecsSinceEpoch) {
    +                    isDst = pair.std < pair.dst && pair.dst < beforeMSecsSinceEpoch;
    +                } else if (pair.dst != invalidMSecs() && pair.dst < beforeMSecsSinceEpoch) {
    +                    isDst = true;
    +                } else {
    +                    --year; // Try an earlier year for this rule (once).
    +                    continue;
    +                }
    +                if (isDst)
    +                    return ruleToData(rule, pair.dst, QTimeZone::DaylightTime, pair.fakesDst());
    +                return ruleToData(rule, pair.std, QTimeZone::StandardTime, pair.fakesDst());
    +            }
    +            // Fell off start of rule, try previous rule.
    +        } else if (ruleIndex == 0) {
    +            // Treat a no-transition first rule as a transition at the start of
    +            // time, so that a scan through all rules *does* see it as the first
    +            // rule:
    +            return ruleToData(rule, startOfTime, QTimeZone::StandardTime, false);
    +        } // else: no transition during rule's period
    +        if (year >= rule.startYear)
    +            year = rule.startYear - 1; // Seek last transition in new rule
    +    }
    +    // Apparently no transition before the given time:
    +    return invalidData();
    +}
    +
    +QByteArray QWinTimeZonePrivate::systemTimeZoneId() const
    +{
    +    const QLocale::Country country = userCountry();
    +    const QByteArray windowsId = windowsSystemZoneId();
    +    QByteArray ianaId;
    +    // If we have a real country, then try get a specific match for that country
    +    if (country != QLocale::AnyCountry)
    +        ianaId = windowsIdToDefaultIanaId(windowsId, country);
    +    // If we don't have a real country, or there wasn't a specific match, try the global default
    +    if (ianaId.isEmpty()) {
    +        ianaId = windowsIdToDefaultIanaId(windowsId);
    +        // If no global default then probably an unknown Windows ID so return UTC
    +        if (ianaId.isEmpty())
    +            return utcQByteArray();
    +    }
    +    return ianaId;
    +}
    +
    +QList QWinTimeZonePrivate::availableTimeZoneIds() const
    +{
    +    QList result;
    +    const auto winIds = availableWindowsIds();
    +    for (const QByteArray &winId : winIds)
    +        result += windowsIdToIanaIds(winId);
    +    std::sort(result.begin(), result.end());
    +    result.erase(std::unique(result.begin(), result.end()), result.end());
    +    return result;
    +}
    +
    +QTimeZonePrivate::Data QWinTimeZonePrivate::ruleToData(const QWinTransitionRule &rule,
    +                                                       qint64 atMSecsSinceEpoch,
    +                                                       QTimeZone::TimeType type,
    +                                                       bool fakeDst) const
    +{
    +    Data tran = invalidData();
    +    tran.atMSecsSinceEpoch = atMSecsSinceEpoch;
    +    tran.standardTimeOffset = rule.standardTimeBias * -60;
    +    if (fakeDst) {
    +        tran.daylightTimeOffset = 0;
    +        tran.abbreviation = m_standardName;
    +        // Rule may claim we're in DST when it's actually a standard time change:
    +        if (type == QTimeZone::DaylightTime)
    +            tran.standardTimeOffset += rule.daylightTimeBias * -60;
    +    } else if (type == QTimeZone::DaylightTime) {
    +        tran.daylightTimeOffset = rule.daylightTimeBias * -60;
    +        tran.abbreviation = m_daylightName;
    +    } else {
    +        tran.daylightTimeOffset = 0;
    +        tran.abbreviation = m_standardName;
    +    }
    +    tran.offsetFromUtc = tran.standardTimeOffset + tran.daylightTimeOffset;
    +    return tran;
    +}
    +
    +QT_END_NAMESPACE
    diff --git a/src/corelib/time/time.pri b/src/corelib/time/time.pri
    new file mode 100644
    index 0000000000..bacb7e875d
    --- /dev/null
    +++ b/src/corelib/time/time.pri
    @@ -0,0 +1,34 @@
    +# Qt time / date / zone / calendar module
    +
    +HEADERS += \
    +        time/qdatetime.h \
    +        time/qdatetime_p.h
    +
    +SOURCES += time/qdatetime.cpp
    +
    +qtConfig(timezone) {
    +    HEADERS += \
    +        time/qtimezone.h \
    +        time/qtimezoneprivate_p.h \
    +        time/qtimezoneprivate_data_p.h
    +    SOURCES += \
    +        time/qtimezone.cpp \
    +        time/qtimezoneprivate.cpp
    +    !nacl:darwin: {
    +        SOURCES += time/qtimezoneprivate_mac.mm
    +    } else: android:!android-embedded: {
    +        SOURCES += time/qtimezoneprivate_android.cpp
    +    } else: unix: {
    +        SOURCES += time/qtimezoneprivate_tz.cpp
    +        qtConfig(icu): SOURCES += time/qtimezoneprivate_icu.cpp
    +    } else: qtConfig(icu): {
    +        SOURCES += time/qtimezoneprivate_icu.cpp
    +    } else: win32: {
    +        SOURCES += time/qtimezoneprivate_win.cpp
    +    }
    +}
    +
    +qtConfig(datetimeparser) {
    +    HEADERS += time/qdatetimeparser_p.h
    +    SOURCES += time/qdatetimeparser.cpp
    +}
    diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp
    deleted file mode 100644
    index 9220d210f1..0000000000
    --- a/src/corelib/tools/qdatetime.cpp
    +++ /dev/null
    @@ -1,5685 +0,0 @@
    -/****************************************************************************
    -**
    -** Copyright (C) 2019 The Qt Company Ltd.
    -** Copyright (C) 2016 Intel Corporation.
    -** Contact: https://www.qt.io/licensing/
    -**
    -** This file is part of the QtCore module of the Qt Toolkit.
    -**
    -** $QT_BEGIN_LICENSE:LGPL$
    -** Commercial License Usage
    -** Licensees holding valid commercial Qt licenses may use this file in
    -** accordance with the commercial license agreement provided with the
    -** Software or, alternatively, in accordance with the terms contained in
    -** a written agreement between you and The Qt Company. For licensing terms
    -** and conditions see https://www.qt.io/terms-conditions. For further
    -** information use the contact form at https://www.qt.io/contact-us.
    -**
    -** GNU Lesser General Public License Usage
    -** Alternatively, this file may be used under the terms of the GNU Lesser
    -** General Public License version 3 as published by the Free Software
    -** Foundation and appearing in the file LICENSE.LGPL3 included in the
    -** packaging of this file. Please review the following information to
    -** ensure the GNU Lesser General Public License version 3 requirements
    -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
    -**
    -** GNU General Public License Usage
    -** Alternatively, this file may be used under the terms of the GNU
    -** General Public License version 2.0 or (at your option) the GNU General
    -** Public license version 3 or any later version approved by the KDE Free
    -** Qt Foundation. The licenses are as published by the Free Software
    -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
    -** included in the packaging of this file. Please review the following
    -** information to ensure the GNU General Public License requirements will
    -** be met: https://www.gnu.org/licenses/gpl-2.0.html and
    -** https://www.gnu.org/licenses/gpl-3.0.html.
    -**
    -** $QT_END_LICENSE$
    -**
    -****************************************************************************/
    -
    -#include "qplatformdefs.h"
    -#include "private/qdatetime_p.h"
    -#if QT_CONFIG(datetimeparser)
    -#include "private/qdatetimeparser_p.h"
    -#endif
    -
    -#include "qdatastream.h"
    -#include "qset.h"
    -#include "qlocale.h"
    -#include "qdatetime.h"
    -#if QT_CONFIG(timezone)
    -#include "qtimezoneprivate_p.h"
    -#endif
    -#include "qregexp.h"
    -#include "qdebug.h"
    -#ifndef Q_OS_WIN
    -#include 
    -#endif
    -
    -#include 
    -#ifdef Q_CC_MINGW
    -#  include  // Define _POSIX_THREAD_SAFE_FUNCTIONS to obtain localtime_r()
    -#endif
    -#include 
    -#ifdef Q_OS_WIN
    -#  include 
    -#  ifdef Q_OS_WINRT
    -#    include "qfunctions_winrt.h"
    -#  endif
    -#endif
    -
    -#if defined(Q_OS_MAC)
    -#include 
    -#endif
    -
    -QT_BEGIN_NAMESPACE
    -
    -/*****************************************************************************
    -  Date/Time Constants
    - *****************************************************************************/
    -
    -enum {
    -    SECS_PER_DAY = 86400,
    -    MSECS_PER_DAY = 86400000,
    -    SECS_PER_HOUR = 3600,
    -    MSECS_PER_HOUR = 3600000,
    -    SECS_PER_MIN = 60,
    -    MSECS_PER_MIN = 60000,
    -    TIME_T_MAX = 2145916799,  // int maximum 2037-12-31T23:59:59 UTC
    -    JULIAN_DAY_FOR_EPOCH = 2440588 // result of julianDayFromDate(1970, 1, 1)
    -};
    -
    -/*****************************************************************************
    -  QDate static helper functions
    - *****************************************************************************/
    -
    -static inline QDate fixedDate(int y, int m, int d)
    -{
    -    QDate result(y, m, 1);
    -    result.setDate(y, m, qMin(d, result.daysInMonth()));
    -    return result;
    -}
    -
    -/*
    -  Division, rounding down (rather than towards zero).
    -
    -  From C++11 onwards, integer division is defined to round towards zero, so we
    -  can rely on that when implementing this.  This is only used with denominator b
    -  > 0, so we only have to treat negative numerator, a, specially.
    - */
    -static inline qint64 floordiv(qint64 a, int b)
    -{
    -    return (a - (a < 0 ? b - 1 : 0)) / b;
    -}
    -
    -static inline int floordiv(int a, int b)
    -{
    -    return (a - (a < 0 ? b - 1 : 0)) / b;
    -}
    -
    -static inline qint64 julianDayFromDate(int year, int month, int day)
    -{
    -    // Adjust for no year 0
    -    if (year < 0)
    -        ++year;
    -
    -/*
    - * Math from The Calendar FAQ at http://www.tondering.dk/claus/cal/julperiod.php
    - * This formula is correct for all julian days, when using mathematical integer
    - * division (round to negative infinity), not c++11 integer division (round to zero)
    - */
    -    int    a = floordiv(14 - month, 12);
    -    qint64 y = (qint64)year + 4800 - a;
    -    int    m = month + 12 * a - 3;
    -    return day + floordiv(153 * m + 2, 5) + 365 * y + floordiv(y, 4) - floordiv(y, 100) + floordiv(y, 400) - 32045;
    -}
    -
    -struct ParsedDate
    -{
    -    int year, month, day;
    -};
    -
    -// prevent this function from being inlined into all 10 users
    -Q_NEVER_INLINE
    -static ParsedDate getDateFromJulianDay(qint64 julianDay)
    -{
    -/*
    - * Math from The Calendar FAQ at http://www.tondering.dk/claus/cal/julperiod.php
    - * This formula is correct for all julian days, when using mathematical integer
    - * division (round to negative infinity), not c++11 integer division (round to zero)
    - */
    -    qint64 a = julianDay + 32044;
    -    qint64 b = floordiv(4 * a + 3, 146097);
    -    int    c = a - floordiv(146097 * b, 4);
    -
    -    int    d = floordiv(4 * c + 3, 1461);
    -    int    e = c - floordiv(1461 * d, 4);
    -    int    m = floordiv(5 * e + 2, 153);
    -
    -    int    day = e - floordiv(153 * m + 2, 5) + 1;
    -    int    month = m + 3 - 12 * floordiv(m, 10);
    -    int    year = 100 * b + d - 4800 + floordiv(m, 10);
    -
    -    // Adjust for no year 0
    -    if (year <= 0)
    -        --year ;
    -
    -    return { year, month, day };
    -}
    -
    -/*****************************************************************************
    -  Date/Time formatting helper functions
    - *****************************************************************************/
    -
    -#if QT_CONFIG(textdate)
    -static const char qt_shortMonthNames[][4] = {
    -    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
    -    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
    -};
    -
    -static int qt_monthNumberFromShortName(QStringRef shortName)
    -{
    -    for (unsigned int i = 0; i < sizeof(qt_shortMonthNames) / sizeof(qt_shortMonthNames[0]); ++i) {
    -        if (shortName == QLatin1String(qt_shortMonthNames[i], 3))
    -            return i + 1;
    -    }
    -    return -1;
    -}
    -static int qt_monthNumberFromShortName(const QString &shortName)
    -{ return qt_monthNumberFromShortName(QStringRef(&shortName)); }
    -
    -static int fromShortMonthName(const QStringRef &monthName)
    -{
    -    // Assume that English monthnames are the default
    -    int month = qt_monthNumberFromShortName(monthName);
    -    if (month != -1)
    -        return month;
    -    // If English names can't be found, search the localized ones
    -    for (int i = 1; i <= 12; ++i) {
    -        if (monthName == QLocale::system().monthName(i, QLocale::ShortFormat))
    -            return i;
    -    }
    -    return -1;
    -}
    -#endif // textdate
    -
    -#if QT_CONFIG(datestring)
    -struct ParsedRfcDateTime {
    -    QDate date;
    -    QTime time;
    -    int utcOffset;
    -};
    -
    -static ParsedRfcDateTime rfcDateImpl(const QString &s)
    -{
    -    ParsedRfcDateTime result;
    -
    -    // Matches "Wdy, dd Mon yyyy HH:mm:ss ±hhmm" (Wdy, being optional)
    -    QRegExp rex(QStringLiteral("^(?:[A-Z][a-z]+,)?[ \\t]*(\\d{1,2})[ \\t]+([A-Z][a-z]+)[ \\t]+(\\d\\d\\d\\d)(?:[ \\t]+(\\d\\d):(\\d\\d)(?::(\\d\\d))?)?[ \\t]*(?:([+-])(\\d\\d)(\\d\\d))?"));
    -    if (s.indexOf(rex) == 0) {
    -        const QStringList cap = rex.capturedTexts();
    -        result.date = QDate(cap[3].toInt(), qt_monthNumberFromShortName(cap[2]), cap[1].toInt());
    -        if (!cap[4].isEmpty())
    -            result.time = QTime(cap[4].toInt(), cap[5].toInt(), cap[6].toInt());
    -        const bool positiveOffset = (cap[7] == QLatin1String("+"));
    -        const int hourOffset = cap[8].toInt();
    -        const int minOffset = cap[9].toInt();
    -        result.utcOffset = ((hourOffset * 60 + minOffset) * (positiveOffset ? 60 : -60));
    -    } else {
    -        // Matches "Wdy Mon dd HH:mm:ss yyyy"
    -        QRegExp rex(QStringLiteral("^[A-Z][a-z]+[ \\t]+([A-Z][a-z]+)[ \\t]+(\\d\\d)(?:[ \\t]+(\\d\\d):(\\d\\d):(\\d\\d))?[ \\t]+(\\d\\d\\d\\d)[ \\t]*(?:([+-])(\\d\\d)(\\d\\d))?"));
    -        if (s.indexOf(rex) == 0) {
    -            const QStringList cap = rex.capturedTexts();
    -            result.date = QDate(cap[6].toInt(), qt_monthNumberFromShortName(cap[1]), cap[2].toInt());
    -            if (!cap[3].isEmpty())
    -                result.time = QTime(cap[3].toInt(), cap[4].toInt(), cap[5].toInt());
    -            const bool positiveOffset = (cap[7] == QLatin1String("+"));
    -            const int hourOffset = cap[8].toInt();
    -            const int minOffset = cap[9].toInt();
    -            result.utcOffset = ((hourOffset * 60 + minOffset) * (positiveOffset ? 60 : -60));
    -        }
    -    }
    -
    -    return result;
    -}
    -#endif // datestring
    -
    -// Return offset in [+-]HH:mm format
    -static QString toOffsetString(Qt::DateFormat format, int offset)
    -{
    -    return QString::asprintf("%c%02d%s%02d",
    -                             offset >= 0 ? '+' : '-',
    -                             qAbs(offset) / SECS_PER_HOUR,
    -                             // Qt::ISODate puts : between the hours and minutes, but Qt:TextDate does not:
    -                             format == Qt::TextDate ? "" : ":",
    -                             (qAbs(offset) / 60) % 60);
    -}
    -
    -#if QT_CONFIG(datestring)
    -// Parse offset in [+-]HH[[:]mm] format
    -static int fromOffsetString(const QStringRef &offsetString, bool *valid) noexcept
    -{
    -    *valid = false;
    -
    -    const int size = offsetString.size();
    -    if (size < 2 || size > 6)
    -        return 0;
    -
    -    // sign will be +1 for a positive and -1 for a negative offset
    -    int sign;
    -
    -    // First char must be + or -
    -    const QChar signChar = offsetString.at(0);
    -    if (signChar == QLatin1Char('+'))
    -        sign = 1;
    -    else if (signChar == QLatin1Char('-'))
    -        sign = -1;
    -    else
    -        return 0;
    -
    -    // Split the hour and minute parts
    -    const QStringRef time = offsetString.mid(1);
    -    int hhLen = time.indexOf(QLatin1Char(':'));
    -    int mmIndex;
    -    if (hhLen == -1)
    -        mmIndex = hhLen = 2; // [+-]HHmm or [+-]HH format
    -    else
    -        mmIndex = hhLen + 1;
    -
    -    const QStringRef hhRef = time.left(hhLen);
    -    bool ok = false;
    -    const int hour = hhRef.toInt(&ok);
    -    if (!ok)
    -        return 0;
    -
    -    const QStringRef mmRef = time.mid(mmIndex);
    -    const int minute = mmRef.isEmpty() ? 0 : mmRef.toInt(&ok);
    -    if (!ok || minute < 0 || minute > 59)
    -        return 0;
    -
    -    *valid = true;
    -    return sign * ((hour * 60) + minute) * 60;
    -}
    -#endif // datestring
    -
    -static constexpr int daysInUsualMonth(int month) // (February isn't usual.)
    -{
    -    // Long if odd up to July = 7, or if even from 8 = August onwards:
    -    return Q_ASSERT(month != 2 && month > 0 && month <= 12), 30 | ((month & 1) ^ (month >> 3));
    -}
    -
    -/*****************************************************************************
    -  QDate member functions
    - *****************************************************************************/
    -
    -/*!
    -    \since 4.5
    -
    -    \enum QDate::MonthNameType
    -
    -    This enum describes the types of the string representation used
    -    for the month name.
    -
    -    \value DateFormat This type of name can be used for date-to-string formatting.
    -    \value StandaloneFormat This type is used when you need to enumerate months or weekdays.
    -           Usually standalone names are represented in singular forms with
    -           capitalized first letter.
    -*/
    -
    -/*!
    -    \class QDate
    -    \inmodule QtCore
    -    \reentrant
    -    \brief The QDate class provides date functions.
    -
    -
    -    A QDate object encodes a calendar date, i.e. year, month, and day numbers,
    -    in the proleptic Gregorian calendar by default. It can read the current date
    -    from the system clock. It provides functions for comparing dates, and for
    -    manipulating dates. For example, it is possible to add and subtract days,
    -    months, and years to dates.
    -
    -    A QDate object is typically created by giving the year, month, and day
    -    numbers explicitly. Note that QDate interprets two digit years as presented,
    -    i.e., as years 0 through 99, without adding any offset.  A QDate can also be
    -    constructed with the static function currentDate(), which creates a QDate
    -    object containing the system clock's date.  An explicit date can also be set
    -    using setDate(). The fromString() function returns a QDate given a string
    -    and a date format which is used to interpret the date within the string.
    -
    -    The year(), month(), and day() functions provide access to the
    -    year, month, and day numbers. Also, dayOfWeek() and dayOfYear()
    -    functions are provided. The same information is provided in
    -    textual format by the toString(), shortDayName(), longDayName(),
    -    shortMonthName(), and longMonthName() functions.
    -
    -    QDate provides a full set of operators to compare two QDate
    -    objects where smaller means earlier, and larger means later.
    -
    -    You can increment (or decrement) a date by a given number of days
    -    using addDays(). Similarly you can use addMonths() and addYears().
    -    The daysTo() function returns the number of days between two
    -    dates.
    -
    -    The daysInMonth() and daysInYear() functions return how many days
    -    there are in this date's month and year, respectively. The
    -    isLeapYear() function indicates whether a date is in a leap year.
    -
    -    \section1 Remarks
    -
    -    \section2 No Year 0
    -
    -    There is no year 0. Dates in that year are considered invalid. The year -1
    -    is the year "1 before Christ" or "1 before current era." The day before 1
    -    January 1 CE, QDate(1, 1, 1), is 31 December 1 BCE, QDate(-1, 12, 31).
    -
    -    \section2 Range of Valid Dates
    -
    -    Dates are stored internally as a Julian Day number, an integer count of
    -    every day in a contiguous range, with 24 November 4714 BCE in the Gregorian
    -    calendar being Julian Day 0 (1 January 4713 BCE in the Julian calendar).
    -    As well as being an efficient and accurate way of storing an absolute date,
    -    it is suitable for converting a Date into other calendar systems such as
    -    Hebrew, Islamic or Chinese. The Julian Day number can be obtained using
    -    QDate::toJulianDay() and can be set using QDate::fromJulianDay().
    -
    -    The range of dates able to be stored by QDate as a Julian Day number is
    -    for technical reasons limited to between -784350574879 and 784354017364,
    -    which means from before 2 billion BCE to after 2 billion CE.
    -
    -    \sa QTime, QDateTime, QDateEdit, QDateTimeEdit, QCalendarWidget
    -*/
    -
    -/*!
    -    \fn QDate::QDate()
    -
    -    Constructs a null date. Null dates are invalid.
    -
    -    \sa isNull(), isValid()
    -*/
    -
    -/*!
    -    Constructs a date with year \a y, month \a m and day \a d.
    -
    -    If the specified date is invalid, the date is not set and
    -    isValid() returns \c false.
    -
    -    \warning Years 1 to 99 are interpreted as is. Year 0 is invalid.
    -
    -    \sa isValid()
    -*/
    -
    -QDate::QDate(int y, int m, int d)
    -{
    -    setDate(y, m, d);
    -}
    -
    -
    -/*!
    -    \fn bool QDate::isNull() const
    -
    -    Returns \c true if the date is null; otherwise returns \c false. A null
    -    date is invalid.
    -
    -    \note The behavior of this function is equivalent to isValid().
    -
    -    \sa isValid()
    -*/
    -
    -/*!
    -    \fn bool QDate::isValid() const
    -
    -    Returns \c true if this date is valid; otherwise returns \c false.
    -
    -    \sa isNull()
    -*/
    -
    -/*!
    -    Returns the year of this date. Negative numbers indicate years
    -    before 1 CE, such that year -44 is 44 BCE.
    -
    -    Returns 0 if the date is invalid.
    -
    -    \sa month(), day()
    -*/
    -
    -int QDate::year() const
    -{
    -    if (isNull())
    -        return 0;
    -
    -    return getDateFromJulianDay(jd).year;
    -}
    -
    -/*!
    -    Returns the number corresponding to the month of this date, using
    -    the following convention:
    -
    -    \list
    -    \li 1 = "January"
    -    \li 2 = "February"
    -    \li 3 = "March"
    -    \li 4 = "April"
    -    \li 5 = "May"
    -    \li 6 = "June"
    -    \li 7 = "July"
    -    \li 8 = "August"
    -    \li 9 = "September"
    -    \li 10 = "October"
    -    \li 11 = "November"
    -    \li 12 = "December"
    -    \endlist
    -
    -    Returns 0 if the date is invalid.
    -
    -    \sa year(), day()
    -*/
    -
    -int QDate::month() const
    -{
    -    if (isNull())
    -        return 0;
    -
    -    return getDateFromJulianDay(jd).month;
    -}
    -
    -/*!
    -    Returns the day of the month (1 to 31) of this date.
    -
    -    Returns 0 if the date is invalid.
    -
    -    \sa year(), month(), dayOfWeek()
    -*/
    -
    -int QDate::day() const
    -{
    -    if (isNull())
    -        return 0;
    -
    -    return getDateFromJulianDay(jd).day;
    -}
    -
    -/*!
    -    Returns the weekday (1 = Monday to 7 = Sunday) for this date.
    -
    -    Returns 0 if the date is invalid.
    -
    -    \sa day(), dayOfYear(), Qt::DayOfWeek
    -*/
    -
    -int QDate::dayOfWeek() const
    -{
    -    if (isNull())
    -        return 0;
    -
    -    if (jd >= 0)
    -        return (jd % 7) + 1;
    -    else
    -        return ((jd + 1) % 7) + 7;
    -}
    -
    -/*!
    -    Returns the day of the year (1 to 365 or 366 on leap years) for
    -    this date.
    -
    -    Returns 0 if the date is invalid.
    -
    -    \sa day(), dayOfWeek()
    -*/
    -
    -int QDate::dayOfYear() const
    -{
    -    if (isNull())
    -        return 0;
    -
    -    return jd - julianDayFromDate(year(), 1, 1) + 1;
    -}
    -
    -/*!
    -    Returns the number of days in the month (28 to 31) for this date.
    -
    -    Returns 0 if the date is invalid.
    -
    -    \sa day(), daysInYear()
    -*/
    -
    -int QDate::daysInMonth() const
    -{
    -    if (isNull())
    -        return 0;
    -
    -    const ParsedDate pd = getDateFromJulianDay(jd);
    -    if (pd.month == 2)
    -        return isLeapYear(pd.year) ? 29 : 28;
    -
    -    return daysInUsualMonth(pd.month);
    -}
    -
    -/*!
    -    Returns the number of days in the year (365 or 366) for this date.
    -
    -    Returns 0 if the date is invalid.
    -
    -    \sa day(), daysInMonth()
    -*/
    -
    -int QDate::daysInYear() const
    -{
    -    if (isNull())
    -        return 0;
    -
    -    return isLeapYear(getDateFromJulianDay(jd).year) ? 366 : 365;
    -}
    -
    -/*!
    -    Returns the week number (1 to 53), and stores the year in
    -    *\a{yearNumber} unless \a yearNumber is null (the default).
    -
    -    Returns 0 if the date is invalid.
    -
    -    In accordance with ISO 8601, weeks start on Monday and the first
    -    Thursday of a year is always in week 1 of that year. Most years
    -    have 52 weeks, but some have 53.
    -
    -    *\a{yearNumber} is not always the same as year(). For example, 1
    -    January 2000 has week number 52 in the year 1999, and 31 December
    -    2002 has week number 1 in the year 2003.
    -
    -    \sa isValid()
    -*/
    -
    -int QDate::weekNumber(int *yearNumber) const
    -{
    -    if (!isValid())
    -        return 0;
    -
    -    int year = QDate::year();
    -    int yday = dayOfYear();
    -    int wday = dayOfWeek();
    -
    -    int week = (yday - wday + 10) / 7;
    -
    -    if (week == 0) {
    -        // last week of previous year
    -        --year;
    -        week = (yday + 365 + (QDate::isLeapYear(year) ? 1 : 0) - wday + 10) / 7;
    -        Q_ASSERT(week == 52 || week == 53);
    -    } else if (week == 53) {
    -        // maybe first week of next year
    -        int w = (yday - 365 - (QDate::isLeapYear(year) ? 1 : 0) - wday + 10) / 7;
    -        if (w > 0) {
    -            ++year;
    -            week = w;
    -        }
    -        Q_ASSERT(week == 53 || week == 1);
    -    }
    -
    -    if (yearNumber != 0)
    -        *yearNumber = year;
    -    return week;
    -}
    -
    -static bool inDateTimeRange(qint64 jd, bool start)
    -{
    -    using Bounds = std::numeric_limits;
    -    if (jd < Bounds::min() + JULIAN_DAY_FOR_EPOCH)
    -        return false;
    -    jd -= JULIAN_DAY_FOR_EPOCH;
    -    const qint64 maxDay = Bounds::max() / MSECS_PER_DAY;
    -    const qint64 minDay = Bounds::min() / MSECS_PER_DAY - 1;
    -    // (Divisions rounded towards zero, as MSECS_PER_DAY has factors other than two.)
    -    // Range includes start of last day and end of first:
    -    if (start)
    -        return jd > minDay && jd <= maxDay;
    -    return jd >= minDay && jd < maxDay;
    -}
    -
    -static QDateTime toEarliest(const QDate &day, const QDateTime &form)
    -{
    -    const Qt::TimeSpec spec = form.timeSpec();
    -    const int offset = (spec == Qt::OffsetFromUTC) ? form.offsetFromUtc() : 0;
    -#if QT_CONFIG(timezone)
    -    QTimeZone zone;
    -    if (spec == Qt::TimeZone)
    -        zone = form.timeZone();
    -#endif
    -    auto moment = [=](QTime time) {
    -        switch (spec) {
    -        case Qt::OffsetFromUTC: return QDateTime(day, time, spec, offset);
    -#if QT_CONFIG(timezone)
    -        case Qt::TimeZone: return QDateTime(day, time, zone);
    -#endif
    -        default: return QDateTime(day, time, spec);
    -        }
    -    };
    -    // Longest routine time-zone transition is 2 hours:
    -    QDateTime when = moment(QTime(2, 0));
    -    if (!when.isValid()) {
    -        // Noon should be safe ...
    -        when = moment(QTime(12, 0));
    -        if (!when.isValid()) {
    -            // ... unless it's a 24-hour jump (moving the date-line)
    -            when = moment(QTime(23, 59, 59, 999));
    -            if (!when.isValid())
    -                return QDateTime();
    -        }
    -    }
    -    int high = when.time().msecsSinceStartOfDay() / 60000;
    -    int low = 0;
    -    // Binary chop to the right minute
    -    while (high > low + 1) {
    -        int mid = (high + low) / 2;
    -        QDateTime probe = moment(QTime(mid / 60, mid % 60));
    -        if (probe.isValid() && probe.date() == day) {
    -            high = mid;
    -            when = probe;
    -        } else {
    -            low = mid;
    -        }
    -    }
    -    return when;
    -}
    -
    -/*!
    -    \since 5.14
    -    \fn QDateTime QDate::startOfDay(Qt::TimeSpec spec, int offsetSeconds) const
    -    \fn QDateTime QDate::startOfDay(const QTimeZone &zone) const
    -
    -    Returns the start-moment of the day.  Usually, this shall be midnight at the
    -    start of the day: however, if a time-zone transition causes the given date
    -    to skip over that midnight (e.g. a DST spring-forward skipping from the end
    -    of the previous day to 01:00 of the new day), the actual earliest time in
    -    the day is returned.  This can only arise when the start-moment is specified
    -    in terms of a time-zone (by passing its QTimeZone as \a zone) or in terms of
    -    local time (by passing Qt::LocalTime as \a spec; this is its default).
    -
    -    The \a offsetSeconds is ignored unless \a spec is Qt::OffsetFromUTC, when it
    -    gives the implied zone's offset from UTC.  As UTC and such zones have no
    -    transitions, the start of the day is QTime(0, 0) in these cases.
    -
    -    In the rare case of a date that was entirely skipped (this happens when a
    -    zone east of the international date-line switches to being west of it), the
    -    return shall be invalid.  Passing Qt::TimeZone as \a spec (instead of
    -    passing a QTimeZone) or passing an invalid time-zone as \a zone will also
    -    produce an invalid result, as shall dates that start outside the range
    -    representable by QDateTime.
    -
    -    \sa endOfDay()
    -*/
    -QDateTime QDate::startOfDay(Qt::TimeSpec spec, int offsetSeconds) const
    -{
    -    if (!inDateTimeRange(jd, true))
    -        return QDateTime();
    -
    -    switch (spec) {
    -    case Qt::TimeZone: // should pass a QTimeZone instead of Qt::TimeZone
    -        qWarning() << "Called QDate::startOfDay(Qt::TimeZone) on" << *this;
    -        return QDateTime();
    -    case Qt::OffsetFromUTC:
    -    case Qt::UTC:
    -        return QDateTime(*this, QTime(0, 0), spec, offsetSeconds);
    -
    -    case Qt::LocalTime:
    -        if (offsetSeconds)
    -            qWarning("Ignoring offset (%d seconds) passed with Qt::LocalTime", offsetSeconds);
    -        break;
    -    }
    -    QDateTime when(*this, QTime(0, 0), spec);
    -    if (!when.isValid())
    -        when = toEarliest(*this, when);
    -
    -    return when.isValid() ? when : QDateTime();
    -}
    -
    -#if QT_CONFIG(timezone)
    -/*!
    -  \overload
    -  \since 5.14
    -*/
    -QDateTime QDate::startOfDay(const QTimeZone &zone) const
    -{
    -    if (!inDateTimeRange(jd, true) || !zone.isValid())
    -        return QDateTime();
    -
    -    QDateTime when(*this, QTime(0, 0), zone);
    -    if (when.isValid())
    -        return when;
    -
    -    // The start of the day must have fallen in a spring-forward's gap; find the spring-forward:
    -    if (zone.hasTransitions()) {
    -        QTimeZone::OffsetData tran = zone.previousTransition(QDateTime(*this, QTime(23, 59, 59, 999), zone));
    -        const QDateTime &at = tran.atUtc.toTimeZone(zone);
    -        if (at.isValid() && at.date() == *this)
    -            return at;
    -    }
    -
    -    when = toEarliest(*this, when);
    -    return when.isValid() ? when : QDateTime();
    -}
    -#endif // timezone
    -
    -static QDateTime toLatest(const QDate &day, const QDateTime &form)
    -{
    -    const Qt::TimeSpec spec = form.timeSpec();
    -    const int offset = (spec == Qt::OffsetFromUTC) ? form.offsetFromUtc() : 0;
    -#if QT_CONFIG(timezone)
    -    QTimeZone zone;
    -    if (spec == Qt::TimeZone)
    -        zone = form.timeZone();
    -#endif
    -    auto moment = [=](QTime time) {
    -        switch (spec) {
    -        case Qt::OffsetFromUTC: return QDateTime(day, time, spec, offset);
    -#if QT_CONFIG(timezone)
    -        case Qt::TimeZone: return QDateTime(day, time, zone);
    -#endif
    -        default: return QDateTime(day, time, spec);
    -        }
    -    };
    -    // Longest routine time-zone transition is 2 hours:
    -    QDateTime when = moment(QTime(21, 59, 59, 999));
    -    if (!when.isValid()) {
    -        // Noon should be safe ...
    -        when = moment(QTime(12, 0));
    -        if (!when.isValid()) {
    -            // ... unless it's a 24-hour jump (moving the date-line)
    -            when = moment(QTime(0, 0));
    -            if (!when.isValid())
    -                return QDateTime();
    -        }
    -    }
    -    int high = 24 * 60;
    -    int low = when.time().msecsSinceStartOfDay() / 60000;
    -    // Binary chop to the right minute
    -    while (high > low + 1) {
    -        int mid = (high + low) / 2;
    -        QDateTime probe = moment(QTime(mid / 60, mid % 60, 59, 999));
    -        if (probe.isValid() && probe.date() == day) {
    -            low = mid;
    -            when = probe;
    -        } else {
    -            high = mid;
    -        }
    -    }
    -    return when;
    -}
    -
    -/*!
    -    \since 5.14
    -    \fn QDateTime QDate::endOfDay(Qt::TimeSpec spec, int offsetSeconds) const
    -    \fn QDateTime QDate::endOfDay(const QTimeZone &zone) const
    -
    -    Returns the end-moment of the day.  Usually, this is one millisecond before
    -    the midnight at the end of the day: however, if a time-zone transition
    -    causes the given date to skip over that midnight (e.g. a DST spring-forward
    -    skipping from just before 23:00 to the start of the next day), the actual
    -    latest time in the day is returned.  This can only arise when the
    -    start-moment is specified in terms of a time-zone (by passing its QTimeZone
    -    as \a zone) or in terms of local time (by passing Qt::LocalTime as \a spec;
    -    this is its default).
    -
    -    The \a offsetSeconds is ignored unless \a spec is Qt::OffsetFromUTC, when it
    -    gives the implied zone's offset from UTC.  As UTC and such zones have no
    -    transitions, the end of the day is QTime(23, 59, 59, 999) in these cases.
    -
    -    In the rare case of a date that was entirely skipped (this happens when a
    -    zone east of the international date-line switches to being west of it), the
    -    return shall be invalid.  Passing Qt::TimeZone as \a spec (instead of
    -    passing a QTimeZone) will also produce an invalid result, as shall dates
    -    that end outside the range representable by QDateTime.
    -
    -    \sa startOfDay()
    -*/
    -QDateTime QDate::endOfDay(Qt::TimeSpec spec, int offsetSeconds) const
    -{
    -    if (!inDateTimeRange(jd, false))
    -        return QDateTime();
    -
    -    switch (spec) {
    -    case Qt::TimeZone: // should pass a QTimeZone instead of Qt::TimeZone
    -        qWarning() << "Called QDate::endOfDay(Qt::TimeZone) on" << *this;
    -        return QDateTime();
    -    case Qt::UTC:
    -    case Qt::OffsetFromUTC:
    -        return QDateTime(*this, QTime(23, 59, 59, 999), spec, offsetSeconds);
    -
    -    case Qt::LocalTime:
    -        if (offsetSeconds)
    -            qWarning("Ignoring offset (%d seconds) passed with Qt::LocalTime", offsetSeconds);
    -        break;
    -    }
    -    QDateTime when(*this, QTime(23, 59, 59, 999), spec);
    -    if (!when.isValid())
    -        when = toLatest(*this, when);
    -    return when.isValid() ? when : QDateTime();
    -}
    -
    -#if QT_CONFIG(timezone)
    -/*!
    -  \overload
    -  \since 5.14
    -*/
    -QDateTime QDate::endOfDay(const QTimeZone &zone) const
    -{
    -    if (!inDateTimeRange(jd, false) || !zone.isValid())
    -        return QDateTime();
    -
    -    QDateTime when(*this, QTime(23, 59, 59, 999), zone);
    -    if (when.isValid())
    -        return when;
    -
    -    // The end of the day must have fallen in a spring-forward's gap; find the spring-forward:
    -    if (zone.hasTransitions()) {
    -        QTimeZone::OffsetData tran = zone.nextTransition(QDateTime(*this, QTime(0, 0), zone));
    -        const QDateTime &at = tran.atUtc.toTimeZone(zone);
    -        if (at.isValid() && at.date() == *this)
    -            return at;
    -    }
    -
    -    when = toLatest(*this, when);
    -    return when.isValid() ? when : QDateTime();
    -}
    -#endif // timezone
    -
    -#if QT_DEPRECATED_SINCE(5, 11) && QT_CONFIG(textdate)
    -
    -/*!
    -    \since 4.5
    -    \deprecated
    -
    -    Returns the short name of the \a month for the representation specified
    -    by \a type.
    -
    -    The months are enumerated using the following convention:
    -
    -    \list
    -    \li 1 = "Jan"
    -    \li 2 = "Feb"
    -    \li 3 = "Mar"
    -    \li 4 = "Apr"
    -    \li 5 = "May"
    -    \li 6 = "Jun"
    -    \li 7 = "Jul"
    -    \li 8 = "Aug"
    -    \li 9 = "Sep"
    -    \li 10 = "Oct"
    -    \li 11 = "Nov"
    -    \li 12 = "Dec"
    -    \endlist
    -
    -    The month names will be localized according to the system's
    -    locale settings, i.e. using QLocale::system().
    -
    -    Returns an empty string if the date is invalid.
    -
    -    \sa toString(), longMonthName(), shortDayName(), longDayName()
    -*/
    -
    -QString QDate::shortMonthName(int month, QDate::MonthNameType type)
    -{
    -    switch (type) {
    -    case QDate::DateFormat:
    -        return QLocale::system().monthName(month, QLocale::ShortFormat);
    -    case QDate::StandaloneFormat:
    -        return QLocale::system().standaloneMonthName(month, QLocale::ShortFormat);
    -    }
    -    return QString();
    -}
    -
    -/*!
    -    \since 4.5
    -    \deprecated
    -
    -    Returns the long name of the \a month for the representation specified
    -    by \a type.
    -
    -    The months are enumerated using the following convention:
    -
    -    \list
    -    \li 1 = "January"
    -    \li 2 = "February"
    -    \li 3 = "March"
    -    \li 4 = "April"
    -    \li 5 = "May"
    -    \li 6 = "June"
    -    \li 7 = "July"
    -    \li 8 = "August"
    -    \li 9 = "September"
    -    \li 10 = "October"
    -    \li 11 = "November"
    -    \li 12 = "December"
    -    \endlist
    -
    -    The month names will be localized according to the system's
    -    locale settings, i.e. using QLocale::system().
    -
    -    Returns an empty string if the date is invalid.
    -
    -    \sa toString(), shortMonthName(), shortDayName(), longDayName()
    -*/
    -
    -QString QDate::longMonthName(int month, MonthNameType type)
    -{
    -    switch (type) {
    -    case QDate::DateFormat:
    -        return QLocale::system().monthName(month, QLocale::LongFormat);
    -    case QDate::StandaloneFormat:
    -        return QLocale::system().standaloneMonthName(month, QLocale::LongFormat);
    -    }
    -    return QString();
    -}
    -
    -/*!
    -    \since 4.5
    -    \deprecated
    -
    -    Returns the short name of the \a weekday for the representation specified
    -    by \a type.
    -
    -    The days are enumerated using the following convention:
    -
    -    \list
    -    \li 1 = "Mon"
    -    \li 2 = "Tue"
    -    \li 3 = "Wed"
    -    \li 4 = "Thu"
    -    \li 5 = "Fri"
    -    \li 6 = "Sat"
    -    \li 7 = "Sun"
    -    \endlist
    -
    -    The day names will be localized according to the system's
    -    locale settings, i.e. using QLocale::system().
    -
    -    Returns an empty string if the date is invalid.
    -
    -    \sa toString(), shortMonthName(), longMonthName(), longDayName()
    -*/
    -
    -QString QDate::shortDayName(int weekday, MonthNameType type)
    -{
    -    switch (type) {
    -    case QDate::DateFormat:
    -        return QLocale::system().dayName(weekday, QLocale::ShortFormat);
    -    case QDate::StandaloneFormat:
    -        return QLocale::system().standaloneDayName(weekday, QLocale::ShortFormat);
    -    }
    -    return QString();
    -}
    -
    -/*!
    -    \since 4.5
    -    \deprecated
    -
    -    Returns the long name of the \a weekday for the representation specified
    -    by \a type.
    -
    -    The days are enumerated using the following convention:
    -
    -    \list
    -    \li 1 = "Monday"
    -    \li 2 = "Tuesday"
    -    \li 3 = "Wednesday"
    -    \li 4 = "Thursday"
    -    \li 5 = "Friday"
    -    \li 6 = "Saturday"
    -    \li 7 = "Sunday"
    -    \endlist
    -
    -    The day names will be localized according to the system's
    -    locale settings, i.e. using QLocale::system().
    -
    -    Returns an empty string if the date is invalid.
    -
    -    \sa toString(), shortDayName(), shortMonthName(), longMonthName()
    -*/
    -
    -QString QDate::longDayName(int weekday, MonthNameType type)
    -{
    -    switch (type) {
    -    case QDate::DateFormat:
    -        return QLocale::system().dayName(weekday, QLocale::LongFormat);
    -    case QDate::StandaloneFormat:
    -        return QLocale::system().standaloneDayName(weekday, QLocale::LongFormat);
    -    }
    -    return QString();
    -}
    -#endif // textdate && deprecated
    -
    -#if QT_CONFIG(datestring)
    -
    -#if QT_CONFIG(textdate)
    -static QString toStringTextDate(QDate date)
    -{
    -    const ParsedDate pd = getDateFromJulianDay(date.toJulianDay());
    -    static const QLatin1Char sp(' ');
    -    return QLocale::system().dayName(date.dayOfWeek(), QLocale::ShortFormat) + sp
    -         + QLocale::system().monthName(pd.month, QLocale::ShortFormat) + sp
    -         + QString::number(pd.day) + sp
    -         + QString::number(pd.year);
    -}
    -#endif // textdate
    -
    -static QString toStringIsoDate(qint64 jd)
    -{
    -    const ParsedDate pd = getDateFromJulianDay(jd);
    -    if (pd.year >= 0 && pd.year <= 9999)
    -        return QString::asprintf("%04d-%02d-%02d", pd.year, pd.month, pd.day);
    -    else
    -        return QString();
    -}
    -
    -/*!
    -    \fn QString QDate::toString(Qt::DateFormat format) const
    -
    -    \overload
    -
    -    Returns the date as a string. The \a format parameter determines
    -    the format of the string.
    -
    -    If the \a format is Qt::TextDate, the string is formatted in
    -    the default way. QDate::shortDayName() and QDate::shortMonthName()
    -    are used to generate the string, so the day and month names will
    -    be localized names using the system locale, i.e. QLocale::system(). An
    -    example of this formatting is "Sat May 20 1995".
    -
    -    If the \a format is Qt::ISODate, the string format corresponds
    -    to the ISO 8601 extended specification for representations of
    -    dates and times, taking the form yyyy-MM-dd, where yyyy is the
    -    year, MM is the month of the year (between 01 and 12), and dd is
    -    the day of the month between 01 and 31.
    -
    -    If the \a format is Qt::SystemLocaleShortDate or
    -    Qt::SystemLocaleLongDate, the string format depends on the locale
    -    settings of the system. Identical to calling
    -    QLocale::system().toString(date, QLocale::ShortFormat) or
    -    QLocale::system().toString(date, QLocale::LongFormat).
    -
    -    If the \a format is Qt::DefaultLocaleShortDate or
    -    Qt::DefaultLocaleLongDate, the string format depends on the
    -    default application locale. This is the locale set with
    -    QLocale::setDefault(), or the system locale if no default locale
    -    has been set. Identical to calling
    -    \l {QLocale::toString()}{QLocale().toString(date, QLocale::ShortFormat) } or
    -    \l {QLocale::toString()}{QLocale().toString(date, QLocale::LongFormat)}.
    -
    -    If the \a format is Qt::RFC2822Date, the string is formatted in
    -    an \l{RFC 2822} compatible way. An example of this formatting is
    -    "20 May 1995".
    -
    -    If the date is invalid, an empty string will be returned.
    -
    -    \warning The Qt::ISODate format is only valid for years in the
    -    range 0 to 9999. This restriction may apply to locale-aware
    -    formats as well, depending on the locale settings.
    -
    -    \sa fromString(), shortDayName(), shortMonthName(), QLocale::toString()
    -*/
    -QString QDate::toString(Qt::DateFormat format) const
    -{
    -    if (!isValid())
    -        return QString();
    -
    -    switch (format) {
    -    case Qt::SystemLocaleDate:
    -    case Qt::SystemLocaleShortDate:
    -        return QLocale::system().toString(*this, QLocale::ShortFormat);
    -    case Qt::SystemLocaleLongDate:
    -        return QLocale::system().toString(*this, QLocale::LongFormat);
    -    case Qt::LocaleDate:
    -    case Qt::DefaultLocaleShortDate:
    -        return QLocale().toString(*this, QLocale::ShortFormat);
    -    case Qt::DefaultLocaleLongDate:
    -        return QLocale().toString(*this, QLocale::LongFormat);
    -    case Qt::RFC2822Date:
    -        return QLocale::c().toString(*this, QStringViewLiteral("dd MMM yyyy"));
    -    default:
    -#if QT_CONFIG(textdate)
    -    case Qt::TextDate:
    -        return toStringTextDate(*this);
    -#endif
    -    case Qt::ISODate:
    -    case Qt::ISODateWithMs:
    -        return toStringIsoDate(jd);
    -    }
    -}
    -
    -/*!
    -    \fn QString QDate::toString(const QString &format) const
    -    \fn QString QDate::toString(QStringView format) const
    -
    -    Returns the date as a string. The \a format parameter determines
    -    the format of the result string.
    -
    -    These expressions may be used:
    -
    -    \table
    -    \header \li Expression \li Output
    -    \row \li d \li the day as number without a leading zero (1 to 31)
    -    \row \li dd \li the day as number with a leading zero (01 to 31)
    -    \row \li ddd
    -         \li the abbreviated localized day name (e.g. 'Mon' to 'Sun').
    -             Uses the system locale to localize the name, i.e. QLocale::system().
    -    \row \li dddd
    -         \li the long localized day name (e.g. 'Monday' to 'Sunday').
    -             Uses the system locale to localize the name, i.e. QLocale::system().
    -    \row \li M \li the month as number without a leading zero (1 to 12)
    -    \row \li MM \li the month as number with a leading zero (01 to 12)
    -    \row \li MMM
    -         \li the abbreviated localized month name (e.g. 'Jan' to 'Dec').
    -             Uses the system locale to localize the name, i.e. QLocale::system().
    -    \row \li MMMM
    -         \li the long localized month name (e.g. 'January' to 'December').
    -             Uses the system locale to localize the name, i.e. QLocale::system().
    -    \row \li yy \li the year as two digit number (00 to 99)
    -    \row \li yyyy \li the year as four digit number. If the year is negative,
    -            a minus sign is prepended in addition.
    -    \endtable
    -
    -    Any sequence of characters enclosed in single quotes will be included
    -    verbatim in the output string (stripped of the quotes), even if it contains
    -    formatting characters. Two consecutive single quotes ("''") are replaced by
    -    a single quote in the output. All other characters in the format string are
    -    included verbatim in the output string.
    -
    -    Formats without separators (e.g. "ddMM") are supported but must be used with
    -    care, as the resulting strings aren't always reliably readable (e.g. if "dM"
    -    produces "212" it could mean either the 2nd of December or the 21st of
    -    February).
    -
    -    Example format strings (assuming that the QDate is the 20 July
    -    1969):
    -
    -    \table
    -    \header \li Format            \li Result
    -    \row    \li dd.MM.yyyy        \li 20.07.1969
    -    \row    \li ddd MMMM d yy     \li Sun July 20 69
    -    \row    \li 'The day is' dddd \li The day is Sunday
    -    \endtable
    -
    -    If the datetime is invalid, an empty string will be returned.
    -
    -    \sa fromString(), QDateTime::toString(), QTime::toString(), QLocale::toString()
    -
    -*/
    -QString QDate::toString(QStringView format) const
    -{
    -    return QLocale::system().toString(*this, format); // QLocale::c() ### Qt6
    -}
    -
    -#if QT_STRINGVIEW_LEVEL < 2
    -QString QDate::toString(const QString &format) const
    -{
    -    return toString(qToStringViewIgnoringNull(format));
    -}
    -#endif
    -
    -#endif // datestring
    -
    -/*!
    -    \fn bool QDate::setYMD(int y, int m, int d)
    -
    -    \deprecated in 5.0, use setDate() instead.
    -
    -    Sets the date's year \a y, month \a m, and day \a d.
    -
    -    If \a y is in the range 0 to 99, it is interpreted as 1900 to
    -    1999.
    -    Returns \c false if the date is invalid.
    -
    -    Use setDate() instead.
    -*/
    -
    -/*!
    -    \since 4.2
    -
    -    Sets the date's \a year, \a month, and \a day. Returns \c true if
    -    the date is valid; otherwise returns \c false.
    -
    -    If the specified date is invalid, the QDate object is set to be
    -    invalid.
    -
    -    \sa isValid()
    -*/
    -bool QDate::setDate(int year, int month, int day)
    -{
    -    if (isValid(year, month, day))
    -        jd = julianDayFromDate(year, month, day);
    -    else
    -        jd = nullJd();
    -
    -    return isValid();
    -}
    -
    -/*!
    -    \since 4.5
    -
    -    Extracts the date's year, month, and day, and assigns them to
    -    *\a year, *\a month, and *\a day. The pointers may be null.
    -
    -    Returns 0 if the date is invalid.
    -
    -    \note In Qt versions prior to 5.7, this function is marked as non-\c{const}.
    -
    -    \sa year(), month(), day(), isValid()
    -*/
    -void QDate::getDate(int *year, int *month, int *day) const
    -{
    -    ParsedDate pd = { 0, 0, 0 };
    -    if (isValid())
    -        pd = getDateFromJulianDay(jd);
    -
    -    if (year)
    -        *year = pd.year;
    -    if (month)
    -        *month = pd.month;
    -    if (day)
    -        *day = pd.day;
    -}
    -
    -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    -/*!
    -    \overload
    -    \internal
    -*/
    -void QDate::getDate(int *year, int *month, int *day)
    -{
    -    qAsConst(*this).getDate(year, month, day);
    -}
    -#endif // < Qt 6
    -
    -/*!
    -    Returns a QDate object containing a date \a ndays later than the
    -    date of this object (or earlier if \a ndays is negative).
    -
    -    Returns a null date if the current date is invalid or the new date is
    -    out of range.
    -
    -    \sa addMonths(), addYears(), daysTo()
    -*/
    -
    -QDate QDate::addDays(qint64 ndays) const
    -{
    -    if (isNull())
    -        return QDate();
    -
    -    // Due to limits on minJd() and maxJd() we know that any overflow
    -    // will be invalid and caught by fromJulianDay().
    -    return fromJulianDay(jd + ndays);
    -}
    -
    -/*!
    -    Returns a QDate object containing a date \a nmonths later than the
    -    date of this object (or earlier if \a nmonths is negative).
    -
    -    \note If the ending day/month combination does not exist in the
    -    resulting month/year, this function will return a date that is the
    -    latest valid date.
    -
    -    \sa addDays(), addYears()
    -*/
    -
    -QDate QDate::addMonths(int nmonths) const
    -{
    -    if (!isValid())
    -        return QDate();
    -    if (!nmonths)
    -        return *this;
    -
    -    int old_y, y, m, d;
    -    {
    -        const ParsedDate pd = getDateFromJulianDay(jd);
    -        y = pd.year;
    -        m = pd.month;
    -        d = pd.day;
    -    }
    -    old_y = y;
    -
    -    bool increasing = nmonths > 0;
    -
    -    while (nmonths != 0) {
    -        if (nmonths < 0 && nmonths + 12 <= 0) {
    -            y--;
    -            nmonths+=12;
    -        } else if (nmonths < 0) {
    -            m+= nmonths;
    -            nmonths = 0;
    -            if (m <= 0) {
    -                --y;
    -                m += 12;
    -            }
    -        } else if (nmonths - 12 >= 0) {
    -            y++;
    -            nmonths -= 12;
    -        } else if (m == 12) {
    -            y++;
    -            m = 0;
    -        } else {
    -            m += nmonths;
    -            nmonths = 0;
    -            if (m > 12) {
    -                ++y;
    -                m -= 12;
    -            }
    -        }
    -    }
    -
    -    // was there a sign change?
    -    if ((old_y > 0 && y <= 0) ||
    -        (old_y < 0 && y >= 0))
    -        // yes, adjust the date by +1 or -1 years
    -        y += increasing ? +1 : -1;
    -
    -    return fixedDate(y, m, d);
    -}
    -
    -/*!
    -    Returns a QDate object containing a date \a nyears later than the
    -    date of this object (or earlier if \a nyears is negative).
    -
    -    \note If the ending day/month combination does not exist in the
    -    resulting year (i.e., if the date was Feb 29 and the final year is
    -    not a leap year), this function will return a date that is the
    -    latest valid date (that is, Feb 28).
    -
    -    \sa addDays(), addMonths()
    -*/
    -
    -QDate QDate::addYears(int nyears) const
    -{
    -    if (!isValid())
    -        return QDate();
    -
    -    ParsedDate pd = getDateFromJulianDay(jd);
    -
    -    int old_y = pd.year;
    -    pd.year += nyears;
    -
    -    // was there a sign change?
    -    if ((old_y > 0 && pd.year <= 0) ||
    -        (old_y < 0 && pd.year >= 0))
    -        // yes, adjust the date by +1 or -1 years
    -        pd.year += nyears > 0 ? +1 : -1;
    -
    -    return fixedDate(pd.year, pd.month, pd.day);
    -}
    -
    -/*!
    -    Returns the number of days from this date to \a d (which is
    -    negative if \a d is earlier than this date).
    -
    -    Returns 0 if either date is invalid.
    -
    -    Example:
    -    \snippet code/src_corelib_tools_qdatetime.cpp 0
    -
    -    \sa addDays()
    -*/
    -
    -qint64 QDate::daysTo(const QDate &d) const
    -{
    -    if (isNull() || d.isNull())
    -        return 0;
    -
    -    // Due to limits on minJd() and maxJd() we know this will never overflow
    -    return d.jd - jd;
    -}
    -
    -
    -/*!
    -    \fn bool QDate::operator==(const QDate &d) const
    -
    -    Returns \c true if this date is equal to \a d; otherwise returns
    -    false.
    -
    -*/
    -
    -/*!
    -    \fn bool QDate::operator!=(const QDate &d) const
    -
    -    Returns \c true if this date is different from \a d; otherwise
    -    returns \c false.
    -*/
    -
    -/*!
    -    \fn bool QDate::operator<(const QDate &d) const
    -
    -    Returns \c true if this date is earlier than \a d; otherwise returns
    -    false.
    -*/
    -
    -/*!
    -    \fn bool QDate::operator<=(const QDate &d) const
    -
    -    Returns \c true if this date is earlier than or equal to \a d;
    -    otherwise returns \c false.
    -*/
    -
    -/*!
    -    \fn bool QDate::operator>(const QDate &d) const
    -
    -    Returns \c true if this date is later than \a d; otherwise returns
    -    false.
    -*/
    -
    -/*!
    -    \fn bool QDate::operator>=(const QDate &d) const
    -
    -    Returns \c true if this date is later than or equal to \a d;
    -    otherwise returns \c false.
    -*/
    -
    -/*!
    -    \fn QDate::currentDate()
    -    Returns the current date, as reported by the system clock.
    -
    -    \sa QTime::currentTime(), QDateTime::currentDateTime()
    -*/
    -
    -#if QT_CONFIG(datestring)
    -/*!
    -    Returns the QDate represented by the \a string, using the
    -    \a format given, or an invalid date if the string cannot be
    -    parsed.
    -
    -    Note for Qt::TextDate: It is recommended that you use the
    -    English short month names (e.g. "Jan"). Although localized month
    -    names can also be used, they depend on the user's locale settings.
    -
    -    \sa toString(), QLocale::toDate()
    -*/
    -
    -QDate QDate::fromString(const QString &string, Qt::DateFormat format)
    -{
    -    if (string.isEmpty())
    -        return QDate();
    -
    -    switch (format) {
    -    case Qt::SystemLocaleDate:
    -    case Qt::SystemLocaleShortDate:
    -        return QLocale::system().toDate(string, QLocale::ShortFormat);
    -    case Qt::SystemLocaleLongDate:
    -        return QLocale::system().toDate(string, QLocale::LongFormat);
    -    case Qt::LocaleDate:
    -    case Qt::DefaultLocaleShortDate:
    -        return QLocale().toDate(string, QLocale::ShortFormat);
    -    case Qt::DefaultLocaleLongDate:
    -        return QLocale().toDate(string, QLocale::LongFormat);
    -    case Qt::RFC2822Date:
    -        return rfcDateImpl(string).date;
    -    default:
    -#if QT_CONFIG(textdate)
    -    case Qt::TextDate: {
    -        QVector parts = string.splitRef(QLatin1Char(' '), QString::SkipEmptyParts);
    -
    -        if (parts.count() != 4)
    -            return QDate();
    -
    -        QStringRef monthName = parts.at(1);
    -        const int month = fromShortMonthName(monthName);
    -        if (month == -1) {
    -            // Month name matches neither English nor other localised name.
    -            return QDate();
    -        }
    -
    -        bool ok = false;
    -        int year = parts.at(3).toInt(&ok);
    -        if (!ok)
    -            return QDate();
    -
    -        return QDate(year, month, parts.at(2).toInt());
    -        }
    -#endif // textdate
    -    case Qt::ISODate: {
    -        // Semi-strict parsing, must be long enough and have non-numeric separators
    -        if (string.size() < 10 || string.at(4).isDigit() || string.at(7).isDigit()
    -            || (string.size() > 10 && string.at(10).isDigit())) {
    -            return QDate();
    -        }
    -        const int year = string.midRef(0, 4).toInt();
    -        if (year <= 0 || year > 9999)
    -            return QDate();
    -        return QDate(year, string.midRef(5, 2).toInt(), string.midRef(8, 2).toInt());
    -        }
    -    }
    -    return QDate();
    -}
    -
    -/*!
    -    Returns the QDate represented by the \a string, using the \a
    -    format given, or an invalid date if the string cannot be parsed.
    -
    -    These expressions may be used for the format:
    -
    -    \table
    -    \header \li Expression \li Output
    -    \row \li d \li The day as a number without a leading zero (1 to 31)
    -    \row \li dd \li The day as a number with a leading zero (01 to 31)
    -    \row \li ddd
    -         \li The abbreviated localized day name (e.g. 'Mon' to 'Sun').
    -             Uses the system locale to localize the name, i.e. QLocale::system().
    -    \row \li dddd
    -         \li The long localized day name (e.g. 'Monday' to 'Sunday').
    -             Uses the system locale to localize the name, i.e. QLocale::system().
    -    \row \li M \li The month as a number without a leading zero (1 to 12)
    -    \row \li MM \li The month as a number with a leading zero (01 to 12)
    -    \row \li MMM
    -         \li The abbreviated localized month name (e.g. 'Jan' to 'Dec').
    -             Uses the system locale to localize the name, i.e. QLocale::system().
    -    \row \li MMMM
    -         \li The long localized month name (e.g. 'January' to 'December').
    -             Uses the system locale to localize the name, i.e. QLocale::system().
    -    \row \li yy \li The year as two digit number (00 to 99)
    -    \row \li yyyy \li The year as four digit number. If the year is negative,
    -            a minus sign is prepended in addition.
    -    \endtable
    -
    -    All other input characters will be treated as text. Any sequence
    -    of characters that are enclosed in single quotes will also be
    -    treated as text and will not be used as an expression. For example:
    -
    -    \snippet code/src_corelib_tools_qdatetime.cpp 1
    -
    -    If the format is not satisfied, an invalid QDate is returned. The
    -    expressions that don't expect leading zeroes (d, M) will be
    -    greedy. This means that they will use two digits even if this
    -    will put them outside the accepted range of values and leaves too
    -    few digits for other sections. For example, the following format
    -    string could have meant January 30 but the M will grab two
    -    digits, resulting in an invalid date:
    -
    -    \snippet code/src_corelib_tools_qdatetime.cpp 2
    -
    -    For any field that is not represented in the format the following
    -    defaults are used:
    -
    -    \table
    -    \header \li Field  \li Default value
    -    \row    \li Year   \li 1900
    -    \row    \li Month  \li 1
    -    \row    \li Day    \li 1
    -    \endtable
    -
    -    The following examples demonstrate the default values:
    -
    -    \snippet code/src_corelib_tools_qdatetime.cpp 3
    -
    -    \sa toString(), QDateTime::fromString(), QTime::fromString(),
    -        QLocale::toDate()
    -*/
    -
    -QDate QDate::fromString(const QString &string, const QString &format)
    -{
    -    QDate date;
    -#if QT_CONFIG(datetimeparser)
    -    QDateTimeParser dt(QVariant::Date, QDateTimeParser::FromString);
    -    // dt.setDefaultLocale(QLocale::c()); ### Qt 6
    -    if (dt.parseFormat(format))
    -        dt.fromString(string, &date, 0);
    -#else
    -    Q_UNUSED(string);
    -    Q_UNUSED(format);
    -#endif
    -    return date;
    -}
    -#endif // datestring
    -
    -/*!
    -    \overload
    -
    -    Returns \c true if the specified date (\a year, \a month, and \a
    -    day) is valid; otherwise returns \c false.
    -
    -    Example:
    -    \snippet code/src_corelib_tools_qdatetime.cpp 4
    -
    -    \sa isNull(), setDate()
    -*/
    -
    -bool QDate::isValid(int year, int month, int day)
    -{
    -    // There is no year 0 in the Gregorian calendar.
    -    return year && day > 0 && month > 0 && month <= 12 &&
    -        day <= (month == 2 ? isLeapYear(year) ? 29 : 28 : daysInUsualMonth(month));
    -}
    -
    -/*!
    -    \fn bool QDate::isLeapYear(int year)
    -
    -    Returns \c true if the specified \a year is a leap year; otherwise
    -    returns \c false.
    -*/
    -
    -bool QDate::isLeapYear(int y)
    -{
    -    // No year 0 in Gregorian calendar, so -1, -5, -9 etc are leap years
    -    if ( y < 1)
    -        ++y;
    -
    -    return (y % 4 == 0 && y % 100 != 0) || y % 400 == 0;
    -}
    -
    -/*! \fn static QDate QDate::fromJulianDay(qint64 jd)
    -
    -    Converts the Julian day \a jd to a QDate.
    -
    -    \sa toJulianDay()
    -*/
    -
    -/*! \fn int QDate::toJulianDay() const
    -
    -    Converts the date to a Julian day.
    -
    -    \sa fromJulianDay()
    -*/
    -
    -/*****************************************************************************
    -  QTime member functions
    - *****************************************************************************/
    -
    -/*!
    -    \class QTime
    -    \inmodule QtCore
    -    \reentrant
    -
    -    \brief The QTime class provides clock time functions.
    -
    -
    -    A QTime object contains a clock time, which it can express as the numbers of
    -    hours, minutes, seconds, and milliseconds since midnight. It provides
    -    functions for comparing times and for manipulating a time by adding a number
    -    of milliseconds.
    -
    -    QTime uses the 24-hour clock format; it has no concept of AM/PM.
    -    Unlike QDateTime, QTime knows nothing about time zones or
    -    daylight-saving time (DST).
    -
    -    A QTime object is typically created either by giving the number
    -    of hours, minutes, seconds, and milliseconds explicitly, or by
    -    using the static function currentTime(), which creates a QTime
    -    object that contains the system's local time. Note that the
    -    accuracy depends on the accuracy of the underlying operating
    -    system; not all systems provide 1-millisecond accuracy.
    -
    -    The hour(), minute(), second(), and msec() functions provide
    -    access to the number of hours, minutes, seconds, and milliseconds
    -    of the time. The same information is provided in textual format by
    -    the toString() function.
    -
    -    The addSecs() and addMSecs() functions provide the time a given
    -    number of seconds or milliseconds later than a given time.
    -    Correspondingly, the number of seconds or milliseconds
    -    between two times can be found using secsTo() or msecsTo().
    -
    -    QTime provides a full set of operators to compare two QTime
    -    objects; an earlier time is considered smaller than a later one;
    -    if A.msecsTo(B) is positive, then A < B.
    -
    -    \sa QDate, QDateTime
    -*/
    -
    -/*!
    -    \fn QTime::QTime()
    -
    -    Constructs a null time object. For a null time, isNull() returns \c true and
    -    isValid() returns \c false. If you need a zero time, use QTime(0, 0).  For
    -    the start of a day, see QDate::startOfDay().
    -
    -    \sa isNull(), isValid()
    -*/
    -
    -/*!
    -    Constructs a time with hour \a h, minute \a m, seconds \a s and
    -    milliseconds \a ms.
    -
    -    \a h must be in the range 0 to 23, \a m and \a s must be in the
    -    range 0 to 59, and \a ms must be in the range 0 to 999.
    -
    -    \sa isValid()
    -*/
    -
    -QTime::QTime(int h, int m, int s, int ms)
    -{
    -    setHMS(h, m, s, ms);
    -}
    -
    -
    -/*!
    -    \fn bool QTime::isNull() const
    -
    -    Returns \c true if the time is null (i.e., the QTime object was
    -    constructed using the default constructor); otherwise returns
    -    false. A null time is also an invalid time.
    -
    -    \sa isValid()
    -*/
    -
    -/*!
    -    Returns \c true if the time is valid; otherwise returns \c false. For example,
    -    the time 23:30:55.746 is valid, but 24:12:30 is invalid.
    -
    -    \sa isNull()
    -*/
    -
    -bool QTime::isValid() const
    -{
    -    return mds > NullTime && mds < MSECS_PER_DAY;
    -}
    -
    -
    -/*!
    -    Returns the hour part (0 to 23) of the time.
    -
    -    Returns -1 if the time is invalid.
    -
    -    \sa minute(), second(), msec()
    -*/
    -
    -int QTime::hour() const
    -{
    -    if (!isValid())
    -        return -1;
    -
    -    return ds() / MSECS_PER_HOUR;
    -}
    -
    -/*!
    -    Returns the minute part (0 to 59) of the time.
    -
    -    Returns -1 if the time is invalid.
    -
    -    \sa hour(), second(), msec()
    -*/
    -
    -int QTime::minute() const
    -{
    -    if (!isValid())
    -        return -1;
    -
    -    return (ds() % MSECS_PER_HOUR) / MSECS_PER_MIN;
    -}
    -
    -/*!
    -    Returns the second part (0 to 59) of the time.
    -
    -    Returns -1 if the time is invalid.
    -
    -    \sa hour(), minute(), msec()
    -*/
    -
    -int QTime::second() const
    -{
    -    if (!isValid())
    -        return -1;
    -
    -    return (ds() / 1000)%SECS_PER_MIN;
    -}
    -
    -/*!
    -    Returns the millisecond part (0 to 999) of the time.
    -
    -    Returns -1 if the time is invalid.
    -
    -    \sa hour(), minute(), second()
    -*/
    -
    -int QTime::msec() const
    -{
    -    if (!isValid())
    -        return -1;
    -
    -    return ds() % 1000;
    -}
    -
    -#if QT_CONFIG(datestring)
    -/*!
    -    \overload
    -
    -    Returns the time as a string. The \a format parameter determines
    -    the format of the string.
    -
    -    If \a format is Qt::TextDate, the string format is HH:mm:ss;
    -    e.g. 1 second before midnight would be "23:59:59".
    -
    -    If \a format is Qt::ISODate, the string format corresponds to the
    -    ISO 8601 extended specification for representations of dates,
    -    represented by HH:mm:ss. To include milliseconds in the ISO 8601
    -    date, use the \a format Qt::ISODateWithMs, which corresponds to
    -    HH:mm:ss.zzz.
    -
    -    If the \a format is Qt::SystemLocaleShortDate or
    -    Qt::SystemLocaleLongDate, the string format depends on the locale
    -    settings of the system. Identical to calling
    -    QLocale::system().toString(time, QLocale::ShortFormat) or
    -    QLocale::system().toString(time, QLocale::LongFormat).
    -
    -    If the \a format is Qt::DefaultLocaleShortDate or
    -    Qt::DefaultLocaleLongDate, the string format depends on the
    -    default application locale. This is the locale set with
    -    QLocale::setDefault(), or the system locale if no default locale
    -    has been set. Identical to calling
    -
    -    \l {QLocale::toString()}{QLocale().toString(time, QLocale::ShortFormat)} or
    -    \l {QLocale::toString()}{QLocale().toString(time, QLocale::LongFormat)}.
    -
    -    If the \a format is Qt::RFC2822Date, the string is formatted in
    -    an \l{RFC 2822} compatible way. An example of this formatting is
    -    "23:59:20".
    -
    -    If the time is invalid, an empty string will be returned.
    -
    -    \sa fromString(), QDate::toString(), QDateTime::toString(), QLocale::toString()
    -*/
    -
    -QString QTime::toString(Qt::DateFormat format) const
    -{
    -    if (!isValid())
    -        return QString();
    -
    -    switch (format) {
    -    case Qt::SystemLocaleDate:
    -    case Qt::SystemLocaleShortDate:
    -        return QLocale::system().toString(*this, QLocale::ShortFormat);
    -    case Qt::SystemLocaleLongDate:
    -        return QLocale::system().toString(*this, QLocale::LongFormat);
    -    case Qt::LocaleDate:
    -    case Qt::DefaultLocaleShortDate:
    -        return QLocale().toString(*this, QLocale::ShortFormat);
    -    case Qt::DefaultLocaleLongDate:
    -        return QLocale().toString(*this, QLocale::LongFormat);
    -    case Qt::ISODateWithMs:
    -        return QString::asprintf("%02d:%02d:%02d.%03d", hour(), minute(), second(), msec());
    -    case Qt::RFC2822Date:
    -    case Qt::ISODate:
    -    case Qt::TextDate:
    -    default:
    -        return QString::asprintf("%02d:%02d:%02d", hour(), minute(), second());
    -    }
    -}
    -
    -/*!
    -    \fn QString QTime::toString(const QString &format) const
    -    \fn QString QTime::toString(QStringView format) const
    -
    -    Returns the time as a string. The \a format parameter determines
    -    the format of the result string.
    -
    -    These expressions may be used:
    -
    -    \table
    -    \header \li Expression \li Output
    -    \row \li h
    -         \li the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
    -    \row \li hh
    -         \li the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
    -    \row \li H
    -         \li the hour without a leading zero (0 to 23, even with AM/PM display)
    -    \row \li HH
    -         \li the hour with a leading zero (00 to 23, even with AM/PM display)
    -    \row \li m \li the minute without a leading zero (0 to 59)
    -    \row \li mm \li the minute with a leading zero (00 to 59)
    -    \row \li s \li the whole second, without any leading zero (0 to 59)
    -    \row \li ss \li the whole second, with a leading zero where applicable (00 to 59)
    -    \row \li z \li the fractional part of the second, to go after a decimal
    -                point, without trailing zeroes (0 to 999).  Thus "\c{s.z}"
    -                reports the seconds to full available (millisecond) precision
    -                without trailing zeroes.
    -    \row \li zzz \li the fractional part of the second, to millisecond
    -                precision, including trailing zeroes where applicable (000 to 999).
    -    \row \li AP or A
    -         \li use AM/PM display. \e A/AP will be replaced by either
    -             QLocale::amText() or QLocale::pmText().
    -    \row \li ap or a
    -         \li use am/pm display. \e a/ap will be replaced by a lower-case version of
    -             QLocale::amText() or QLocale::pmText().
    -    \row \li t \li the timezone (for example "CEST")
    -    \endtable
    -
    -    Any sequence of characters enclosed in single quotes will be included
    -    verbatim in the output string (stripped of the quotes), even if it contains
    -    formatting characters. Two consecutive single quotes ("''") are replaced by
    -    a single quote in the output. All other characters in the format string are
    -    included verbatim in the output string.
    -
    -    Formats without separators (e.g. "ddMM") are supported but must be used with
    -    care, as the resulting strings aren't always reliably readable (e.g. if "dM"
    -    produces "212" it could mean either the 2nd of December or the 21st of
    -    February).
    -
    -    Example format strings (assuming that the QTime is 14:13:09.042 and the system
    -    locale is \c{en_US})
    -
    -    \table
    -    \header \li Format \li Result
    -    \row \li hh:mm:ss.zzz \li 14:13:09.042
    -    \row \li h:m:s ap     \li 2:13:9 pm
    -    \row \li H:m:s a      \li 14:13:9 pm
    -    \endtable
    -
    -    If the time is invalid, an empty string will be returned.
    -    If \a format is empty, the default format "hh:mm:ss" is used.
    -
    -    \sa fromString(), QDate::toString(), QDateTime::toString(), QLocale::toString()
    -*/
    -QString QTime::toString(QStringView format) const
    -{
    -    return QLocale::system().toString(*this, format); // QLocale::c() ### Qt6
    -}
    -
    -#if QT_STRINGVIEW_VERSION < 2
    -QString QTime::toString(const QString &format) const
    -{
    -    return toString(qToStringViewIgnoringNull(format));
    -}
    -#endif
    -
    -#endif // datestring
    -
    -/*!
    -    Sets the time to hour \a h, minute \a m, seconds \a s and
    -    milliseconds \a ms.
    -
    -    \a h must be in the range 0 to 23, \a m and \a s must be in the
    -    range 0 to 59, and \a ms must be in the range 0 to 999.
    -    Returns \c true if the set time is valid; otherwise returns \c false.
    -
    -    \sa isValid()
    -*/
    -
    -bool QTime::setHMS(int h, int m, int s, int ms)
    -{
    -    if (!isValid(h,m,s,ms)) {
    -        mds = NullTime;                // make this invalid
    -        return false;
    -    }
    -    mds = (h*SECS_PER_HOUR + m*SECS_PER_MIN + s)*1000 + ms;
    -    return true;
    -}
    -
    -/*!
    -    Returns a QTime object containing a time \a s seconds later
    -    than the time of this object (or earlier if \a s is negative).
    -
    -    Note that the time will wrap if it passes midnight.
    -
    -    Returns a null time if this time is invalid.
    -
    -    Example:
    -
    -    \snippet code/src_corelib_tools_qdatetime.cpp 5
    -
    -    \sa addMSecs(), secsTo(), QDateTime::addSecs()
    -*/
    -
    -QTime QTime::addSecs(int s) const
    -{
    -    s %= SECS_PER_DAY;
    -    return addMSecs(s * 1000);
    -}
    -
    -/*!
    -    Returns the number of seconds from this time to \a t.
    -    If \a t is earlier than this time, the number of seconds returned
    -    is negative.
    -
    -    Because QTime measures time within a day and there are 86400
    -    seconds in a day, the result is always between -86400 and 86400.
    -
    -    secsTo() does not take into account any milliseconds.
    -
    -    Returns 0 if either time is invalid.
    -
    -    \sa addSecs(), QDateTime::secsTo()
    -*/
    -
    -int QTime::secsTo(const QTime &t) const
    -{
    -    if (!isValid() || !t.isValid())
    -        return 0;
    -
    -    // Truncate milliseconds as we do not want to consider them.
    -    int ourSeconds = ds() / 1000;
    -    int theirSeconds = t.ds() / 1000;
    -    return theirSeconds - ourSeconds;
    -}
    -
    -/*!
    -    Returns a QTime object containing a time \a ms milliseconds later
    -    than the time of this object (or earlier if \a ms is negative).
    -
    -    Note that the time will wrap if it passes midnight. See addSecs()
    -    for an example.
    -
    -    Returns a null time if this time is invalid.
    -
    -    \sa addSecs(), msecsTo(), QDateTime::addMSecs()
    -*/
    -
    -QTime QTime::addMSecs(int ms) const
    -{
    -    QTime t;
    -    if (isValid()) {
    -        if (ms < 0) {
    -            // %,/ not well-defined for -ve, so always work with +ve.
    -            int negdays = (MSECS_PER_DAY - ms) / MSECS_PER_DAY;
    -            t.mds = (ds() + ms + negdays * MSECS_PER_DAY) % MSECS_PER_DAY;
    -        } else {
    -            t.mds = (ds() + ms) % MSECS_PER_DAY;
    -        }
    -    }
    -    return t;
    -}
    -
    -/*!
    -    Returns the number of milliseconds from this time to \a t.
    -    If \a t is earlier than this time, the number of milliseconds returned
    -    is negative.
    -
    -    Because QTime measures time within a day and there are 86400
    -    seconds in a day, the result is always between -86400000 and
    -    86400000 ms.
    -
    -    Returns 0 if either time is invalid.
    -
    -    \sa secsTo(), addMSecs(), QDateTime::msecsTo()
    -*/
    -
    -int QTime::msecsTo(const QTime &t) const
    -{
    -    if (!isValid() || !t.isValid())
    -        return 0;
    -    return t.ds() - ds();
    -}
    -
    -
    -/*!
    -    \fn bool QTime::operator==(const QTime &t) const
    -
    -    Returns \c true if this time is equal to \a t; otherwise returns \c false.
    -*/
    -
    -/*!
    -    \fn bool QTime::operator!=(const QTime &t) const
    -
    -    Returns \c true if this time is different from \a t; otherwise returns \c false.
    -*/
    -
    -/*!
    -    \fn bool QTime::operator<(const QTime &t) const
    -
    -    Returns \c true if this time is earlier than \a t; otherwise returns \c false.
    -*/
    -
    -/*!
    -    \fn bool QTime::operator<=(const QTime &t) const
    -
    -    Returns \c true if this time is earlier than or equal to \a t;
    -    otherwise returns \c false.
    -*/
    -
    -/*!
    -    \fn bool QTime::operator>(const QTime &t) const
    -
    -    Returns \c true if this time is later than \a t; otherwise returns \c false.
    -*/
    -
    -/*!
    -    \fn bool QTime::operator>=(const QTime &t) const
    -
    -    Returns \c true if this time is later than or equal to \a t;
    -    otherwise returns \c false.
    -*/
    -
    -/*!
    -    \fn QTime QTime::fromMSecsSinceStartOfDay(int msecs)
    -
    -    Returns a new QTime instance with the time set to the number of \a msecs
    -    since the start of the day, i.e. since 00:00:00.
    -
    -    If \a msecs falls outside the valid range an invalid QTime will be returned.
    -
    -    \sa msecsSinceStartOfDay()
    -*/
    -
    -/*!
    -    \fn int QTime::msecsSinceStartOfDay() const
    -
    -    Returns the number of msecs since the start of the day, i.e. since 00:00:00.
    -
    -    \sa fromMSecsSinceStartOfDay()
    -*/
    -
    -/*!
    -    \fn QTime::currentTime()
    -
    -    Returns the current time as reported by the system clock.
    -
    -    Note that the accuracy depends on the accuracy of the underlying
    -    operating system; not all systems provide 1-millisecond accuracy.
    -*/
    -
    -#if QT_CONFIG(datestring)
    -
    -static QTime fromIsoTimeString(const QStringRef &string, Qt::DateFormat format, bool *isMidnight24)
    -{
    -    if (isMidnight24)
    -        *isMidnight24 = false;
    -
    -    const int size = string.size();
    -    if (size < 5)
    -        return QTime();
    -
    -    bool ok = false;
    -    int hour = string.mid(0, 2).toInt(&ok);
    -    if (!ok)
    -        return QTime();
    -    const int minute = string.mid(3, 2).toInt(&ok);
    -    if (!ok)
    -        return QTime();
    -    int second = 0;
    -    int msec = 0;
    -
    -    if (size == 5) {
    -        // HH:mm format
    -        second = 0;
    -        msec = 0;
    -    } else if (string.at(5) == QLatin1Char(',') || string.at(5) == QLatin1Char('.')) {
    -        if (format == Qt::TextDate)
    -            return QTime();
    -        // ISODate HH:mm.ssssss format
    -        // We only want 5 digits worth of fraction of minute. This follows the existing
    -        // behavior that determines how milliseconds are read; 4 millisecond digits are
    -        // read and then rounded to 3. If we read at most 5 digits for fraction of minute,
    -        // the maximum amount of millisecond digits it will expand to once converted to
    -        // seconds is 4. E.g. 12:34,99999 will expand to 12:34:59.9994. The milliseconds
    -        // will then be rounded up AND clamped to 999.
    -
    -        const QStringRef minuteFractionStr = string.mid(6, 5);
    -        const long minuteFractionInt = minuteFractionStr.toLong(&ok);
    -        if (!ok)
    -            return QTime();
    -        const float minuteFraction = double(minuteFractionInt) / (std::pow(double(10), minuteFractionStr.count()));
    -
    -        const float secondWithMs = minuteFraction * 60;
    -        const float secondNoMs = std::floor(secondWithMs);
    -        const float secondFraction = secondWithMs - secondNoMs;
    -        second = secondNoMs;
    -        msec = qMin(qRound(secondFraction * 1000.0), 999);
    -    } else {
    -        // HH:mm:ss or HH:mm:ss.zzz
    -        second = string.mid(6, 2).toInt(&ok);
    -        if (!ok)
    -            return QTime();
    -        if (size > 8 && (string.at(8) == QLatin1Char(',') || string.at(8) == QLatin1Char('.'))) {
    -            const QStringRef msecStr(string.mid(9, 4));
    -            int msecInt = msecStr.isEmpty() ? 0 : msecStr.toInt(&ok);
    -            if (!ok)
    -                return QTime();
    -            const double secondFraction(msecInt / (std::pow(double(10), msecStr.count())));
    -            msec = qMin(qRound(secondFraction * 1000.0), 999);
    -        }
    -    }
    -
    -    const bool isISODate = format == Qt::ISODate || format == Qt::ISODateWithMs;
    -    if (isISODate && hour == 24 && minute == 0 && second == 0 && msec == 0) {
    -        if (isMidnight24)
    -            *isMidnight24 = true;
    -        hour = 0;
    -    }
    -
    -    return QTime(hour, minute, second, msec);
    -}
    -
    -/*!
    -    Returns the time represented in the \a string as a QTime using the
    -    \a format given, or an invalid time if this is not possible.
    -
    -    Note that fromString() uses a "C" locale encoded string to convert
    -    milliseconds to a float value. If the default locale is not "C",
    -    this may result in two conversion attempts (if the conversion
    -    fails for the default locale). This should be considered an
    -    implementation detail.
    -
    -    \sa toString(), QLocale::toTime()
    -*/
    -QTime QTime::fromString(const QString &string, Qt::DateFormat format)
    -{
    -    if (string.isEmpty())
    -        return QTime();
    -
    -    switch (format) {
    -    case Qt::SystemLocaleDate:
    -    case Qt::SystemLocaleShortDate:
    -        return QLocale::system().toTime(string, QLocale::ShortFormat);
    -    case Qt::SystemLocaleLongDate:
    -        return QLocale::system().toTime(string, QLocale::LongFormat);
    -    case Qt::LocaleDate:
    -    case Qt::DefaultLocaleShortDate:
    -        return QLocale().toTime(string, QLocale::ShortFormat);
    -    case Qt::DefaultLocaleLongDate:
    -        return QLocale().toTime(string, QLocale::LongFormat);
    -    case Qt::RFC2822Date:
    -        return rfcDateImpl(string).time;
    -    case Qt::ISODate:
    -    case Qt::ISODateWithMs:
    -    case Qt::TextDate:
    -    default:
    -        return fromIsoTimeString(QStringRef(&string), format, 0);
    -    }
    -}
    -
    -/*!
    -    Returns the QTime represented by the \a string, using the \a
    -    format given, or an invalid time if the string cannot be parsed.
    -
    -    These expressions may be used for the format:
    -
    -    \table
    -    \header \li Expression \li Output
    -    \row \li h
    -         \li the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
    -    \row \li hh
    -         \li the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
    -    \row \li m \li the minute without a leading zero (0 to 59)
    -    \row \li mm \li the minute with a leading zero (00 to 59)
    -    \row \li s \li the whole second, without any leading zero (0 to 59)
    -    \row \li ss \li the whole second, with a leading zero where applicable (00 to 59)
    -    \row \li z \li the fractional part of the second, to go after a decimal
    -                point, without trailing zeroes (0 to 999).  Thus "\c{s.z}"
    -                reports the seconds to full available (millisecond) precision
    -                without trailing zeroes.
    -    \row \li zzz \li the fractional part of the second, to millisecond
    -                precision, including trailing zeroes where applicable (000 to 999).
    -    \row \li AP
    -         \li interpret as an AM/PM time. \e AP must be either "AM" or "PM".
    -    \row \li ap
    -         \li Interpret as an AM/PM time. \e ap must be either "am" or "pm".
    -    \endtable
    -
    -    All other input characters will be treated as text. Any sequence
    -    of characters that are enclosed in single quotes will also be
    -    treated as text and not be used as an expression.
    -
    -    \snippet code/src_corelib_tools_qdatetime.cpp 6
    -
    -    If the format is not satisfied, an invalid QTime is returned.
    -    Expressions that do not expect leading zeroes to be given (h, m, s
    -    and z) are greedy. This means that they will use two digits even if
    -    this puts them outside the range of accepted values and leaves too
    -    few digits for other sections. For example, the following string
    -    could have meant 00:07:10, but the m will grab two digits, resulting
    -    in an invalid time:
    -
    -    \snippet code/src_corelib_tools_qdatetime.cpp 7
    -
    -    Any field that is not represented in the format will be set to zero.
    -    For example:
    -
    -    \snippet code/src_corelib_tools_qdatetime.cpp 8
    -
    -    \sa toString(), QDateTime::fromString(), QDate::fromString(),
    -    QLocale::toTime()
    -*/
    -
    -QTime QTime::fromString(const QString &string, const QString &format)
    -{
    -    QTime time;
    -#if QT_CONFIG(datetimeparser)
    -    QDateTimeParser dt(QVariant::Time, QDateTimeParser::FromString);
    -    // dt.setDefaultLocale(QLocale::c()); ### Qt 6
    -    if (dt.parseFormat(format))
    -        dt.fromString(string, 0, &time);
    -#else
    -    Q_UNUSED(string);
    -    Q_UNUSED(format);
    -#endif
    -    return time;
    -}
    -
    -#endif // datestring
    -
    -
    -/*!
    -    \overload
    -
    -    Returns \c true if the specified time is valid; otherwise returns
    -    false.
    -
    -    The time is valid if \a h is in the range 0 to 23, \a m and
    -    \a s are in the range 0 to 59, and \a ms is in the range 0 to 999.
    -
    -    Example:
    -
    -    \snippet code/src_corelib_tools_qdatetime.cpp 9
    -*/
    -
    -bool QTime::isValid(int h, int m, int s, int ms)
    -{
    -    return (uint)h < 24 && (uint)m < 60 && (uint)s < 60 && (uint)ms < 1000;
    -}
    -
    -#if QT_DEPRECATED_SINCE(5, 14) // ### Qt 6: remove
    -/*!
    -    Sets this time to the current time. This is practical for timing:
    -
    -    \snippet code/src_corelib_tools_qdatetime.cpp 10
    -
    -    \sa restart(), elapsed(), currentTime()
    -*/
    -
    -void QTime::start()
    -{
    -    *this = currentTime();
    -}
    -
    -/*!
    -    Sets this time to the current time and returns the number of
    -    milliseconds that have elapsed since the last time start() or
    -    restart() was called.
    -
    -    This function is guaranteed to be atomic and is thus very handy
    -    for repeated measurements. Call start() to start the first
    -    measurement, and restart() for each later measurement.
    -
    -    Note that the counter wraps to zero 24 hours after the last call
    -    to start() or restart().
    -
    -    \warning If the system's clock setting has been changed since the
    -    last time start() or restart() was called, the result is
    -    undefined. This can happen when daylight-saving time is turned on
    -    or off.
    -
    -    \sa start(), elapsed(), currentTime()
    -*/
    -
    -int QTime::restart()
    -{
    -    QTime t = currentTime();
    -    int n = msecsTo(t);
    -    if (n < 0)                                // passed midnight
    -        n += 86400*1000;
    -    *this = t;
    -    return n;
    -}
    -
    -/*!
    -    Returns the number of milliseconds that have elapsed since the
    -    last time start() or restart() was called.
    -
    -    Note that the counter wraps to zero 24 hours after the last call
    -    to start() or restart.
    -
    -    Note that the accuracy depends on the accuracy of the underlying
    -    operating system; not all systems provide 1-millisecond accuracy.
    -
    -    \warning If the system's clock setting has been changed since the
    -    last time start() or restart() was called, the result is
    -    undefined. This can happen when daylight-saving time is turned on
    -    or off.
    -
    -    \sa start(), restart()
    -*/
    -
    -int QTime::elapsed() const
    -{
    -    int n = msecsTo(currentTime());
    -    if (n < 0)                                // passed midnight
    -        n += 86400 * 1000;
    -    return n;
    -}
    -#endif // Use QElapsedTimer instead !
    -
    -/*****************************************************************************
    -  QDateTime static helper functions
    - *****************************************************************************/
    -
    -// get the types from QDateTime (through QDateTimePrivate)
    -typedef QDateTimePrivate::QDateTimeShortData ShortData;
    -typedef QDateTimePrivate::QDateTimeData QDateTimeData;
    -
    -// Returns the platform variant of timezone, i.e. the standard time offset
    -// The timezone external variable is documented as always holding the
    -// Standard Time offset as seconds west of Greenwich, i.e. UTC+01:00 is -3600
    -// Note this may not be historicaly accurate.
    -// Relies on tzset, mktime, or localtime having been called to populate timezone
    -static int qt_timezone()
    -{
    -#if defined(_MSC_VER)
    -        long offset;
    -        _get_timezone(&offset);
    -        return offset;
    -#elif defined(Q_OS_BSD4) && !defined(Q_OS_DARWIN)
    -        time_t clock = time(NULL);
    -        struct tm t;
    -        localtime_r(&clock, &t);
    -        // QTBUG-36080 Workaround for systems without the POSIX timezone
    -        // variable. This solution is not very efficient but fixing it is up to
    -        // the libc implementations.
    -        //
    -        // tm_gmtoff has some important differences compared to the timezone
    -        // variable:
    -        // - It returns the number of seconds east of UTC, and we want the
    -        //   number of seconds west of UTC.
    -        // - It also takes DST into account, so we need to adjust it to always
    -        //   get the Standard Time offset.
    -        return -t.tm_gmtoff + (t.tm_isdst ? (long)SECS_PER_HOUR : 0L);
    -#elif defined(Q_OS_INTEGRITY)
    -        return 0;
    -#else
    -        return timezone;
    -#endif // Q_OS_WIN
    -}
    -
    -// Returns the tzname, assume tzset has been called already
    -static QString qt_tzname(QDateTimePrivate::DaylightStatus daylightStatus)
    -{
    -    int isDst = (daylightStatus == QDateTimePrivate::DaylightTime) ? 1 : 0;
    -#if defined(Q_CC_MSVC)
    -    size_t s = 0;
    -    char name[512];
    -    if (_get_tzname(&s, name, 512, isDst))
    -        return QString();
    -    return QString::fromLocal8Bit(name);
    -#else
    -    return QString::fromLocal8Bit(tzname[isDst]);
    -#endif // Q_OS_WIN
    -}
    -
    -#if QT_CONFIG(datetimeparser) && QT_CONFIG(timezone)
    -/*
    -  \internal
    -  Implemented here to share qt_tzname()
    -*/
    -int QDateTimeParser::startsWithLocalTimeZone(const QStringRef name)
    -{
    -    QDateTimePrivate::DaylightStatus zones[2] = {
    -        QDateTimePrivate::StandardTime,
    -        QDateTimePrivate::DaylightTime
    -    };
    -    for (const auto z : zones) {
    -        QString zone(qt_tzname(z));
    -        if (name.startsWith(zone))
    -            return zone.size();
    -    }
    -    return 0;
    -}
    -#endif // datetimeparser && timezone
    -
    -// Calls the platform variant of mktime for the given date, time and daylightStatus,
    -// and updates the date, time, daylightStatus and abbreviation with the returned values
    -// If the date falls outside the 1970 to 2037 range supported by mktime / time_t
    -// then null date/time will be returned, you should adjust the date first if
    -// you need a guaranteed result.
    -static qint64 qt_mktime(QDate *date, QTime *time, QDateTimePrivate::DaylightStatus *daylightStatus,
    -                        QString *abbreviation, bool *ok = 0)
    -{
    -    const qint64 msec = time->msec();
    -    int yy, mm, dd;
    -    date->getDate(&yy, &mm, &dd);
    -
    -    // All other platforms provide standard C library time functions
    -    tm local;
    -    memset(&local, 0, sizeof(local)); // tm_[wy]day plus any non-standard fields
    -    local.tm_sec = time->second();
    -    local.tm_min = time->minute();
    -    local.tm_hour = time->hour();
    -    local.tm_mday = dd;
    -    local.tm_mon = mm - 1;
    -    local.tm_year = yy - 1900;
    -    if (daylightStatus)
    -        local.tm_isdst = int(*daylightStatus);
    -    else
    -        local.tm_isdst = -1;
    -
    -#if defined(Q_OS_WIN)
    -    int hh = local.tm_hour;
    -#endif // Q_OS_WIN
    -    time_t secsSinceEpoch = qMkTime(&local);
    -    if (secsSinceEpoch != time_t(-1)) {
    -        *date = QDate(local.tm_year + 1900, local.tm_mon + 1, local.tm_mday);
    -        *time = QTime(local.tm_hour, local.tm_min, local.tm_sec, msec);
    -#if defined(Q_OS_WIN)
    -        // Windows mktime for the missing hour subtracts 1 hour from the time
    -        // instead of adding 1 hour.  If time differs and is standard time then
    -        // this has happened, so add 2 hours to the time and 1 hour to the msecs
    -        if (local.tm_isdst == 0 && local.tm_hour != hh) {
    -            if (time->hour() >= 22)
    -                *date = date->addDays(1);
    -            *time = time->addSecs(2 * SECS_PER_HOUR);
    -            secsSinceEpoch += SECS_PER_HOUR;
    -            local.tm_isdst = 1;
    -        }
    -#endif // Q_OS_WIN
    -        if (local.tm_isdst >= 1) {
    -            if (daylightStatus)
    -                *daylightStatus = QDateTimePrivate::DaylightTime;
    -            if (abbreviation)
    -                *abbreviation = qt_tzname(QDateTimePrivate::DaylightTime);
    -        } else if (local.tm_isdst == 0) {
    -            if (daylightStatus)
    -                *daylightStatus = QDateTimePrivate::StandardTime;
    -            if (abbreviation)
    -                *abbreviation = qt_tzname(QDateTimePrivate::StandardTime);
    -        } else {
    -            if (daylightStatus)
    -                *daylightStatus = QDateTimePrivate::UnknownDaylightTime;
    -            if (abbreviation)
    -                *abbreviation = qt_tzname(QDateTimePrivate::StandardTime);
    -        }
    -        if (ok)
    -            *ok = true;
    -    } else {
    -        *date = QDate();
    -        *time = QTime();
    -        if (daylightStatus)
    -            *daylightStatus = QDateTimePrivate::UnknownDaylightTime;
    -        if (abbreviation)
    -            *abbreviation = QString();
    -        if (ok)
    -            *ok = false;
    -    }
    -
    -    return ((qint64)secsSinceEpoch * 1000) + msec;
    -}
    -
    -// Calls the platform variant of localtime for the given msecs, and updates
    -// the date, time, and DST status with the returned values.
    -static bool qt_localtime(qint64 msecsSinceEpoch, QDate *localDate, QTime *localTime,
    -                         QDateTimePrivate::DaylightStatus *daylightStatus)
    -{
    -    const time_t secsSinceEpoch = msecsSinceEpoch / 1000;
    -    const int msec = msecsSinceEpoch % 1000;
    -
    -    tm local;
    -    bool valid = false;
    -
    -    // localtime() is specified to work as if it called tzset().
    -    // localtime_r() does not have this constraint, so make an explicit call.
    -    // The explicit call should also request the timezone info be re-parsed.
    -    qTzSet();
    -#if QT_CONFIG(thread) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
    -    // Use the reentrant version of localtime() where available
    -    // as is thread-safe and doesn't use a shared static data area
    -    tm *res = 0;
    -    res = localtime_r(&secsSinceEpoch, &local);
    -    if (res)
    -        valid = true;
    -#elif defined(Q_CC_MSVC)
    -    if (!_localtime64_s(&local, &secsSinceEpoch))
    -        valid = true;
    -#else
    -    // Returns shared static data which may be overwritten at any time
    -    // So copy the result asap
    -    tm *res = 0;
    -    res = localtime(&secsSinceEpoch);
    -    if (res) {
    -        local = *res;
    -        valid = true;
    -    }
    -#endif
    -    if (valid) {
    -        *localDate = QDate(local.tm_year + 1900, local.tm_mon + 1, local.tm_mday);
    -        *localTime = QTime(local.tm_hour, local.tm_min, local.tm_sec, msec);
    -        if (daylightStatus) {
    -            if (local.tm_isdst > 0)
    -                *daylightStatus = QDateTimePrivate::DaylightTime;
    -            else if (local.tm_isdst < 0)
    -                *daylightStatus = QDateTimePrivate::UnknownDaylightTime;
    -            else
    -                *daylightStatus = QDateTimePrivate::StandardTime;
    -        }
    -        return true;
    -    } else {
    -        *localDate = QDate();
    -        *localTime = QTime();
    -        if (daylightStatus)
    -            *daylightStatus = QDateTimePrivate::UnknownDaylightTime;
    -        return false;
    -    }
    -}
    -
    -// Converts an msecs value into a date and time
    -static void msecsToTime(qint64 msecs, QDate *date, QTime *time)
    -{
    -    qint64 jd = JULIAN_DAY_FOR_EPOCH;
    -    qint64 ds = 0;
    -
    -    if (msecs >= MSECS_PER_DAY || msecs <= -MSECS_PER_DAY) {
    -        jd += msecs / MSECS_PER_DAY;
    -        msecs %= MSECS_PER_DAY;
    -    }
    -
    -    if (msecs < 0) {
    -        ds = MSECS_PER_DAY - msecs - 1;
    -        jd -= ds / MSECS_PER_DAY;
    -        ds = ds % MSECS_PER_DAY;
    -        ds = MSECS_PER_DAY - ds - 1;
    -    } else {
    -        ds = msecs;
    -    }
    -
    -    if (date)
    -        *date = QDate::fromJulianDay(jd);
    -    if (time)
    -        *time = QTime::fromMSecsSinceStartOfDay(ds);
    -}
    -
    -// Converts a date/time value into msecs
    -static qint64 timeToMSecs(const QDate &date, const QTime &time)
    -{
    -    return ((date.toJulianDay() - JULIAN_DAY_FOR_EPOCH) * MSECS_PER_DAY)
    -           + time.msecsSinceStartOfDay();
    -}
    -
    -// Convert an MSecs Since Epoch into Local Time
    -static bool epochMSecsToLocalTime(qint64 msecs, QDate *localDate, QTime *localTime,
    -                                  QDateTimePrivate::DaylightStatus *daylightStatus = 0)
    -{
    -    if (msecs < 0) {
    -        // Docs state any LocalTime before 1970-01-01 will *not* have any Daylight Time applied
    -        // Instead just use the standard offset from UTC to convert to UTC time
    -        qTzSet();
    -        msecsToTime(msecs - qt_timezone() * 1000, localDate, localTime);
    -        if (daylightStatus)
    -            *daylightStatus = QDateTimePrivate::StandardTime;
    -        return true;
    -    } else if (msecs > (qint64(TIME_T_MAX) * 1000)) {
    -        // Docs state any LocalTime after 2037-12-31 *will* have any DST applied
    -        // but this may fall outside the supported time_t range, so need to fake it.
    -        // Use existing method to fake the conversion, but this is deeply flawed as it may
    -        // apply the conversion from the wrong day number, e.g. if rule is last Sunday of month
    -        // TODO Use QTimeZone when available to apply the future rule correctly
    -        QDate utcDate;
    -        QTime utcTime;
    -        msecsToTime(msecs, &utcDate, &utcTime);
    -        int year, month, day;
    -        utcDate.getDate(&year, &month, &day);
    -        // 2037 is not a leap year, so make sure date isn't Feb 29
    -        if (month == 2 && day == 29)
    -            --day;
    -        QDate fakeDate(2037, month, day);
    -        qint64 fakeMsecs = QDateTime(fakeDate, utcTime, Qt::UTC).toMSecsSinceEpoch();
    -        bool res = qt_localtime(fakeMsecs, localDate, localTime, daylightStatus);
    -        *localDate = localDate->addDays(fakeDate.daysTo(utcDate));
    -        return res;
    -    } else {
    -        // Falls inside time_t suported range so can use localtime
    -        return qt_localtime(msecs, localDate, localTime, daylightStatus);
    -    }
    -}
    -
    -// Convert a LocalTime expressed in local msecs encoding and the corresponding
    -// DST status into a UTC epoch msecs. Optionally populate the returned
    -// values from mktime for the adjusted local date and time.
    -static qint64 localMSecsToEpochMSecs(qint64 localMsecs,
    -                                     QDateTimePrivate::DaylightStatus *daylightStatus,
    -                                     QDate *localDate = 0, QTime *localTime = 0,
    -                                     QString *abbreviation = 0)
    -{
    -    QDate dt;
    -    QTime tm;
    -    msecsToTime(localMsecs, &dt, &tm);
    -
    -    const qint64 msecsMax = qint64(TIME_T_MAX) * 1000;
    -
    -    if (localMsecs <= qint64(MSECS_PER_DAY)) {
    -
    -        // Docs state any LocalTime before 1970-01-01 will *not* have any DST applied
    -
    -        // First, if localMsecs is within +/- 1 day of minimum time_t try mktime in case it does
    -        // fall after minimum and needs proper DST conversion
    -        if (localMsecs >= -qint64(MSECS_PER_DAY)) {
    -            bool valid;
    -            qint64 utcMsecs = qt_mktime(&dt, &tm, daylightStatus, abbreviation, &valid);
    -            if (valid && utcMsecs >= 0) {
    -                // mktime worked and falls in valid range, so use it
    -                if (localDate)
    -                    *localDate = dt;
    -                if (localTime)
    -                    *localTime = tm;
    -                return utcMsecs;
    -            }
    -        } else {
    -            // If we don't call mktime then need to call tzset to get offset
    -            qTzSet();
    -        }
    -        // Time is clearly before 1970-01-01 so just use standard offset to convert
    -        qint64 utcMsecs = localMsecs + qt_timezone() * 1000;
    -        if (localDate || localTime)
    -            msecsToTime(localMsecs, localDate, localTime);
    -        if (daylightStatus)
    -            *daylightStatus = QDateTimePrivate::StandardTime;
    -        if (abbreviation)
    -            *abbreviation = qt_tzname(QDateTimePrivate::StandardTime);
    -        return utcMsecs;
    -
    -    } else if (localMsecs >= msecsMax - MSECS_PER_DAY) {
    -
    -        // Docs state any LocalTime after 2037-12-31 *will* have any DST applied
    -        // but this may fall outside the supported time_t range, so need to fake it.
    -
    -        // First, if localMsecs is within +/- 1 day of maximum time_t try mktime in case it does
    -        // fall before maximum and can use proper DST conversion
    -        if (localMsecs <= msecsMax + MSECS_PER_DAY) {
    -            bool valid;
    -            qint64 utcMsecs = qt_mktime(&dt, &tm, daylightStatus, abbreviation, &valid);
    -            if (valid && utcMsecs <= msecsMax) {
    -                // mktime worked and falls in valid range, so use it
    -                if (localDate)
    -                    *localDate = dt;
    -                if (localTime)
    -                    *localTime = tm;
    -                return utcMsecs;
    -            }
    -        }
    -        // Use existing method to fake the conversion, but this is deeply flawed as it may
    -        // apply the conversion from the wrong day number, e.g. if rule is last Sunday of month
    -        // TODO Use QTimeZone when available to apply the future rule correctly
    -        int year, month, day;
    -        dt.getDate(&year, &month, &day);
    -        // 2037 is not a leap year, so make sure date isn't Feb 29
    -        if (month == 2 && day == 29)
    -            --day;
    -        QDate fakeDate(2037, month, day);
    -        qint64 fakeDiff = fakeDate.daysTo(dt);
    -        qint64 utcMsecs = qt_mktime(&fakeDate, &tm, daylightStatus, abbreviation);
    -        if (localDate)
    -            *localDate = fakeDate.addDays(fakeDiff);
    -        if (localTime)
    -            *localTime = tm;
    -        QDate utcDate;
    -        QTime utcTime;
    -        msecsToTime(utcMsecs, &utcDate, &utcTime);
    -        utcDate = utcDate.addDays(fakeDiff);
    -        utcMsecs = timeToMSecs(utcDate, utcTime);
    -        return utcMsecs;
    -
    -    } else {
    -
    -        // Clearly falls inside 1970-2037 suported range so can use mktime
    -        qint64 utcMsecs = qt_mktime(&dt, &tm, daylightStatus, abbreviation);
    -        if (localDate)
    -            *localDate = dt;
    -        if (localTime)
    -            *localTime = tm;
    -        return utcMsecs;
    -
    -    }
    -}
    -
    -static inline bool specCanBeSmall(Qt::TimeSpec spec)
    -{
    -    return spec == Qt::LocalTime || spec == Qt::UTC;
    -}
    -
    -static inline bool msecsCanBeSmall(qint64 msecs)
    -{
    -    if (!QDateTimeData::CanBeSmall)
    -        return false;
    -
    -    ShortData sd;
    -    sd.msecs = qintptr(msecs);
    -    return sd.msecs == msecs;
    -}
    -
    -static Q_DECL_CONSTEXPR inline
    -QDateTimePrivate::StatusFlags mergeSpec(QDateTimePrivate::StatusFlags status, Qt::TimeSpec spec)
    -{
    -    return QDateTimePrivate::StatusFlags((status & ~QDateTimePrivate::TimeSpecMask) |
    -                                         (int(spec) << QDateTimePrivate::TimeSpecShift));
    -}
    -
    -static Q_DECL_CONSTEXPR inline Qt::TimeSpec extractSpec(QDateTimePrivate::StatusFlags status)
    -{
    -    return Qt::TimeSpec((status & QDateTimePrivate::TimeSpecMask) >> QDateTimePrivate::TimeSpecShift);
    -}
    -
    -// Set the Daylight Status if LocalTime set via msecs
    -static Q_DECL_RELAXED_CONSTEXPR inline QDateTimePrivate::StatusFlags
    -mergeDaylightStatus(QDateTimePrivate::StatusFlags sf, QDateTimePrivate::DaylightStatus status)
    -{
    -    sf &= ~QDateTimePrivate::DaylightMask;
    -    if (status == QDateTimePrivate::DaylightTime) {
    -        sf |= QDateTimePrivate::SetToDaylightTime;
    -    } else if (status == QDateTimePrivate::StandardTime) {
    -        sf |= QDateTimePrivate::SetToStandardTime;
    -    }
    -    return sf;
    -}
    -
    -// Get the DST Status if LocalTime set via msecs
    -static Q_DECL_RELAXED_CONSTEXPR inline
    -QDateTimePrivate::DaylightStatus extractDaylightStatus(QDateTimePrivate::StatusFlags status)
    -{
    -    if (status & QDateTimePrivate::SetToDaylightTime)
    -        return QDateTimePrivate::DaylightTime;
    -    if (status & QDateTimePrivate::SetToStandardTime)
    -        return QDateTimePrivate::StandardTime;
    -    return QDateTimePrivate::UnknownDaylightTime;
    -}
    -
    -static inline qint64 getMSecs(const QDateTimeData &d)
    -{
    -    if (d.isShort()) {
    -        // same as, but producing better code
    -        //return d.data.msecs;
    -        return qintptr(d.d) >> 8;
    -    }
    -    return d->m_msecs;
    -}
    -
    -static inline QDateTimePrivate::StatusFlags getStatus(const QDateTimeData &d)
    -{
    -    if (d.isShort()) {
    -        // same as, but producing better code
    -        //return StatusFlag(d.data.status);
    -        return QDateTimePrivate::StatusFlag(qintptr(d.d) & 0xFF);
    -    }
    -    return d->m_status;
    -}
    -
    -static inline Qt::TimeSpec getSpec(const QDateTimeData &d)
    -{
    -    return extractSpec(getStatus(d));
    -}
    -
    -#if QT_CONFIG(timezone)
    -void QDateTimePrivate::setUtcOffsetByTZ(qint64 atMSecsSinceEpoch)
    -{
    -    m_offsetFromUtc = m_timeZone.d->offsetFromUtc(atMSecsSinceEpoch);
    -}
    -#endif
    -
    -// Refresh the LocalTime validity and offset
    -static void refreshDateTime(QDateTimeData &d)
    -{
    -    auto status = getStatus(d);
    -    const auto spec = extractSpec(status);
    -    const qint64 msecs = getMSecs(d);
    -    qint64 epochMSecs = 0;
    -    int offsetFromUtc = 0;
    -    QDate testDate;
    -    QTime testTime;
    -    Q_ASSERT(spec == Qt::TimeZone || spec == Qt::LocalTime);
    -
    -#if QT_CONFIG(timezone)
    -    // If not valid time zone then is invalid
    -    if (spec == Qt::TimeZone) {
    -        if (!d->m_timeZone.isValid()) {
    -            status &= ~QDateTimePrivate::ValidDateTime;
    -        } else {
    -            epochMSecs = QDateTimePrivate::zoneMSecsToEpochMSecs(msecs, d->m_timeZone, extractDaylightStatus(status), &testDate, &testTime);
    -            d->setUtcOffsetByTZ(epochMSecs);
    -        }
    -    }
    -#endif // timezone
    -
    -    // If not valid date and time then is invalid
    -    if (!(status & QDateTimePrivate::ValidDate) || !(status & QDateTimePrivate::ValidTime)) {
    -        status &= ~QDateTimePrivate::ValidDateTime;
    -        if (status & QDateTimePrivate::ShortData) {
    -            d.data.status = status;
    -        } else {
    -            d->m_status = status;
    -            d->m_offsetFromUtc = 0;
    -        }
    -        return;
    -    }
    -
    -    // We have a valid date and time and a Qt::LocalTime or Qt::TimeZone that needs calculating
    -    // LocalTime and TimeZone might fall into a "missing" DST transition hour
    -    // Calling toEpochMSecs will adjust the returned date/time if it does
    -    if (spec == Qt::LocalTime) {
    -        auto dstStatus = extractDaylightStatus(status);
    -        epochMSecs = localMSecsToEpochMSecs(msecs, &dstStatus, &testDate, &testTime);
    -    }
    -    if (timeToMSecs(testDate, testTime) == msecs) {
    -        status |= QDateTimePrivate::ValidDateTime;
    -        // Cache the offset to use in offsetFromUtc()
    -        offsetFromUtc = (msecs - epochMSecs) / 1000;
    -    } else {
    -        status &= ~QDateTimePrivate::ValidDateTime;
    -    }
    -
    -    if (status & QDateTimePrivate::ShortData) {
    -        d.data.status = status;
    -    } else {
    -        d->m_status = status;
    -        d->m_offsetFromUtc = offsetFromUtc;
    -    }
    -}
    -
    -// Check the UTC / offsetFromUTC validity
    -static void checkValidDateTime(QDateTimeData &d)
    -{
    -    auto status = getStatus(d);
    -    auto spec = extractSpec(status);
    -    switch (spec) {
    -    case Qt::OffsetFromUTC:
    -    case Qt::UTC:
    -        // for these, a valid date and a valid time imply a valid QDateTime
    -        if ((status & QDateTimePrivate::ValidDate) && (status & QDateTimePrivate::ValidTime))
    -            status |= QDateTimePrivate::ValidDateTime;
    -        else
    -            status &= ~QDateTimePrivate::ValidDateTime;
    -        if (status & QDateTimePrivate::ShortData)
    -            d.data.status = status;
    -        else
    -            d->m_status = status;
    -        break;
    -    case Qt::TimeZone:
    -    case Qt::LocalTime:
    -        // for these, we need to check whether the timezone is valid and whether
    -        // the time is valid in that timezone. Expensive, but no other option.
    -        refreshDateTime(d);
    -        break;
    -    }
    -}
    -
    -static void setTimeSpec(QDateTimeData &d, Qt::TimeSpec spec, int offsetSeconds)
    -{
    -    auto status = getStatus(d);
    -    status &= ~(QDateTimePrivate::ValidDateTime | QDateTimePrivate::DaylightMask |
    -                QDateTimePrivate::TimeSpecMask);
    -
    -    switch (spec) {
    -    case Qt::OffsetFromUTC:
    -        if (offsetSeconds == 0)
    -            spec = Qt::UTC;
    -        break;
    -    case Qt::TimeZone:
    -        // Use system time zone instead
    -        spec = Qt::LocalTime;
    -        Q_FALLTHROUGH();
    -    case Qt::UTC:
    -    case Qt::LocalTime:
    -        offsetSeconds = 0;
    -        break;
    -    }
    -
    -    status = mergeSpec(status, spec);
    -    if (d.isShort() && offsetSeconds == 0) {
    -        d.data.status = status;
    -    } else {
    -        d.detach();
    -        d->m_status = status & ~QDateTimePrivate::ShortData;
    -        d->m_offsetFromUtc = offsetSeconds;
    -#if QT_CONFIG(timezone)
    -        d->m_timeZone = QTimeZone();
    -#endif // timezone
    -    }
    -}
    -
    -static void setDateTime(QDateTimeData &d, const QDate &date, const QTime &time)
    -{
    -    // If the date is valid and the time is not we set time to 00:00:00
    -    QTime useTime = time;
    -    if (!useTime.isValid() && date.isValid())
    -        useTime = QTime::fromMSecsSinceStartOfDay(0);
    -
    -    QDateTimePrivate::StatusFlags newStatus = 0;
    -
    -    // Set date value and status
    -    qint64 days = 0;
    -    if (date.isValid()) {
    -        days = date.toJulianDay() - JULIAN_DAY_FOR_EPOCH;
    -        newStatus = QDateTimePrivate::ValidDate;
    -    }
    -
    -    // Set time value and status
    -    int ds = 0;
    -    if (useTime.isValid()) {
    -        ds = useTime.msecsSinceStartOfDay();
    -        newStatus |= QDateTimePrivate::ValidTime;
    -    }
    -
    -    // Set msecs serial value
    -    qint64 msecs = (days * MSECS_PER_DAY) + ds;
    -    if (d.isShort()) {
    -        // let's see if we can keep this short
    -        if (msecsCanBeSmall(msecs)) {
    -            // yes, we can
    -            d.data.msecs = qintptr(msecs);
    -            d.data.status &= ~(QDateTimePrivate::ValidityMask | QDateTimePrivate::DaylightMask);
    -            d.data.status |= newStatus;
    -        } else {
    -            // nope...
    -            d.detach();
    -        }
    -    }
    -    if (!d.isShort()) {
    -        d.detach();
    -        d->m_msecs = msecs;
    -        d->m_status &= ~(QDateTimePrivate::ValidityMask | QDateTimePrivate::DaylightMask);
    -        d->m_status |= newStatus;
    -    }
    -
    -    // Set if date and time are valid
    -    checkValidDateTime(d);
    -}
    -
    -static QPair getDateTime(const QDateTimeData &d)
    -{
    -    QPair result;
    -    qint64 msecs = getMSecs(d);
    -    auto status = getStatus(d);
    -    msecsToTime(msecs, &result.first, &result.second);
    -
    -    if (!status.testFlag(QDateTimePrivate::ValidDate))
    -        result.first = QDate();
    -
    -    if (!status.testFlag(QDateTimePrivate::ValidTime))
    -        result.second = QTime();
    -
    -    return result;
    -}
    -
    -/*****************************************************************************
    -  QDateTime::Data member functions
    - *****************************************************************************/
    -
    -inline QDateTime::Data::Data()
    -{
    -    // default-constructed data has a special exception:
    -    // it can be small even if CanBeSmall == false
    -    // (optimization so we don't allocate memory in the default constructor)
    -    quintptr value = quintptr(mergeSpec(QDateTimePrivate::ShortData, Qt::LocalTime));
    -    d = reinterpret_cast(value);
    -}
    -
    -inline QDateTime::Data::Data(Qt::TimeSpec spec)
    -{
    -    if (CanBeSmall && Q_LIKELY(specCanBeSmall(spec))) {
    -        d = reinterpret_cast(quintptr(mergeSpec(QDateTimePrivate::ShortData, spec)));
    -    } else {
    -        // the structure is too small, we need to detach
    -        d = new QDateTimePrivate;
    -        d->ref.ref();
    -        d->m_status = mergeSpec(0, spec);
    -    }
    -}
    -
    -inline QDateTime::Data::Data(const Data &other)
    -    : d(other.d)
    -{
    -    if (!isShort()) {
    -        // check if we could shrink
    -        if (specCanBeSmall(extractSpec(d->m_status)) && msecsCanBeSmall(d->m_msecs)) {
    -            ShortData sd;
    -            sd.msecs = qintptr(d->m_msecs);
    -            sd.status = d->m_status | QDateTimePrivate::ShortData;
    -            data = sd;
    -        } else {
    -            // no, have to keep it big
    -            d->ref.ref();
    -        }
    -    }
    -}
    -
    -inline QDateTime::Data::Data(Data &&other)
    -    : d(other.d)
    -{
    -    // reset the other to a short state
    -    Data dummy;
    -    Q_ASSERT(dummy.isShort());
    -    other.d = dummy.d;
    -}
    -
    -inline QDateTime::Data &QDateTime::Data::operator=(const Data &other)
    -{
    -    if (d == other.d)
    -        return *this;
    -
    -    auto x = d;
    -    d = other.d;
    -    if (!other.isShort()) {
    -        // check if we could shrink
    -        if (specCanBeSmall(extractSpec(other.d->m_status)) && msecsCanBeSmall(other.d->m_msecs)) {
    -            ShortData sd;
    -            sd.msecs = qintptr(other.d->m_msecs);
    -            sd.status = other.d->m_status | QDateTimePrivate::ShortData;
    -            data = sd;
    -        } else {
    -            // no, have to keep it big
    -            other.d->ref.ref();
    -        }
    -    }
    -
    -    if (!(quintptr(x) & QDateTimePrivate::ShortData) && !x->ref.deref())
    -        delete x;
    -    return *this;
    -}
    -
    -inline QDateTime::Data::~Data()
    -{
    -    if (!isShort() && !d->ref.deref())
    -        delete d;
    -}
    -
    -inline bool QDateTime::Data::isShort() const
    -{
    -    bool b = quintptr(d) & QDateTimePrivate::ShortData;
    -
    -    // sanity check:
    -    Q_ASSERT(b || (d->m_status & QDateTimePrivate::ShortData) == 0);
    -
    -    // even if CanBeSmall = false, we have short data for a default-constructed
    -    // QDateTime object. But it's unlikely.
    -    if (CanBeSmall)
    -        return Q_LIKELY(b);
    -    return Q_UNLIKELY(b);
    -}
    -
    -inline void QDateTime::Data::detach()
    -{
    -    QDateTimePrivate *x;
    -    bool wasShort = isShort();
    -    if (wasShort) {
    -        // force enlarging
    -        x = new QDateTimePrivate;
    -        x->m_status = QDateTimePrivate::StatusFlag(data.status & ~QDateTimePrivate::ShortData);
    -        x->m_msecs = data.msecs;
    -    } else {
    -        if (d->ref.load() == 1)
    -            return;
    -
    -        x = new QDateTimePrivate(*d);
    -    }
    -
    -    x->ref.store(1);
    -    if (!wasShort && !d->ref.deref())
    -        delete d;
    -    d = x;
    -}
    -
    -inline const QDateTimePrivate *QDateTime::Data::operator->() const
    -{
    -    Q_ASSERT(!isShort());
    -    return d;
    -}
    -
    -inline QDateTimePrivate *QDateTime::Data::operator->()
    -{
    -    // should we attempt to detach here?
    -    Q_ASSERT(!isShort());
    -    Q_ASSERT(d->ref.load() == 1);
    -    return d;
    -}
    -
    -/*****************************************************************************
    -  QDateTimePrivate member functions
    - *****************************************************************************/
    -
    -Q_NEVER_INLINE
    -QDateTime::Data QDateTimePrivate::create(const QDate &toDate, const QTime &toTime, Qt::TimeSpec toSpec,
    -                                         int offsetSeconds)
    -{
    -    QDateTime::Data result(toSpec);
    -    setTimeSpec(result, toSpec, offsetSeconds);
    -    setDateTime(result, toDate, toTime);
    -    return result;
    -}
    -
    -#if QT_CONFIG(timezone)
    -inline QDateTime::Data QDateTimePrivate::create(const QDate &toDate, const QTime &toTime,
    -                                                const QTimeZone &toTimeZone)
    -{
    -    QDateTime::Data result(Qt::TimeZone);
    -    Q_ASSERT(!result.isShort());
    -
    -    result.d->m_status = mergeSpec(result.d->m_status, Qt::TimeZone);
    -    result.d->m_timeZone = toTimeZone;
    -    setDateTime(result, toDate, toTime);
    -    return result;
    -}
    -
    -// Convert a TimeZone time expressed in zone msecs encoding into a UTC epoch msecs
    -// DST transitions are disambiguated by hint.
    -inline qint64 QDateTimePrivate::zoneMSecsToEpochMSecs(qint64 zoneMSecs, const QTimeZone &zone,
    -                                                      DaylightStatus hint,
    -                                                      QDate *zoneDate, QTime *zoneTime)
    -{
    -    // Get the effective data from QTimeZone
    -    QTimeZonePrivate::Data data = zone.d->dataForLocalTime(zoneMSecs, int(hint));
    -    // Docs state any time before 1970-01-01 will *not* have any DST applied
    -    // but all affected times afterwards will have DST applied.
    -    if (data.atMSecsSinceEpoch < 0) {
    -        msecsToTime(zoneMSecs, zoneDate, zoneTime);
    -        return zoneMSecs - data.standardTimeOffset * 1000;
    -    } else {
    -        msecsToTime(data.atMSecsSinceEpoch + data.offsetFromUtc * 1000, zoneDate, zoneTime);
    -        return data.atMSecsSinceEpoch;
    -    }
    -}
    -#endif // timezone
    -
    -/*****************************************************************************
    -  QDateTime member functions
    - *****************************************************************************/
    -
    -/*!
    -    \class QDateTime
    -    \inmodule QtCore
    -    \ingroup shared
    -    \reentrant
    -    \brief The QDateTime class provides date and time functions.
    -
    -
    -    A QDateTime object encodes a calendar date and a clock time (a
    -    "datetime"). It combines features of the QDate and QTime classes.
    -    It can read the current datetime from the system clock. It
    -    provides functions for comparing datetimes and for manipulating a
    -    datetime by adding a number of seconds, days, months, or years.
    -
    -    A QDateTime object is typically created either by giving a date
    -    and time explicitly in the constructor, or by using the static
    -    function currentDateTime() that returns a QDateTime object set
    -    to the system clock's time. The date and time can be changed with
    -    setDate() and setTime(). A datetime can also be set using the
    -    setTime_t() function that takes a POSIX-standard "number of
    -    seconds since 00:00:00 on January 1, 1970" value. The fromString()
    -    function returns a QDateTime, given a string and a date format
    -    used to interpret the date within the string.
    -
    -    The date() and time() functions provide access to the date and
    -    time parts of the datetime. The same information is provided in
    -    textual format by the toString() function.
    -
    -    QDateTime provides a full set of operators to compare two
    -    QDateTime objects, where smaller means earlier and larger means
    -    later.
    -
    -    You can increment (or decrement) a datetime by a given number of
    -    milliseconds using addMSecs(), seconds using addSecs(), or days
    -    using addDays(). Similarly, you can use addMonths() and addYears().
    -    The daysTo() function returns the number of days between two datetimes,
    -    secsTo() returns the number of seconds between two datetimes, and
    -    msecsTo() returns the number of milliseconds between two datetimes.
    -
    -    QDateTime can store datetimes as \l{Qt::LocalTime}{local time} or
    -    as \l{Qt::UTC}{UTC}. QDateTime::currentDateTime() returns a
    -    QDateTime expressed as local time; use toUTC() to convert it to
    -    UTC. You can also use timeSpec() to find out if a QDateTime
    -    object stores a UTC time or a local time. Operations such as
    -    addSecs() and secsTo() are aware of daylight-saving time (DST).
    -
    -    \note QDateTime does not account for leap seconds.
    -
    -    \section1 Remarks
    -
    -    \section2 No Year 0
    -
    -    There is no year 0. Dates in that year are considered invalid. The
    -    year -1 is the year "1 before Christ" or "1 before current era."
    -    The day before 1 January 1 CE is 31 December 1 BCE.
    -
    -    \section2 Range of Valid Dates
    -
    -    The range of valid values able to be stored in QDateTime is dependent on
    -    the internal storage implementation. QDateTime is currently stored in a
    -    qint64 as a serial msecs value encoding the date and time.  This restricts
    -    the date range to about +/- 292 million years, compared to the QDate range
    -    of +/- 2 billion years.  Care must be taken when creating a QDateTime with
    -    extreme values that you do not overflow the storage.  The exact range of
    -    supported values varies depending on the Qt::TimeSpec and time zone.
    -
    -    \section2 Use of System Timezone
    -
    -    QDateTime uses the system's time zone information to determine the
    -    offset of local time from UTC. If the system is not configured
    -    correctly or not up-to-date, QDateTime will give wrong results as
    -    well.
    -
    -    \section2 Daylight-Saving Time (DST)
    -
    -    QDateTime takes into account the system's time zone information
    -    when dealing with DST. On modern Unix systems, this means it
    -    applies the correct historical DST data whenever possible. On
    -    Windows, where the system doesn't support historical DST data,
    -    historical accuracy is not maintained with respect to DST.
    -
    -    The range of valid dates taking DST into account is 1970-01-01 to
    -    the present, and rules are in place for handling DST correctly
    -    until 2037-12-31, but these could change. For dates falling
    -    outside that range, QDateTime makes a \e{best guess} using the
    -    rules for year 1970 or 2037, but we can't guarantee accuracy. This
    -    means QDateTime doesn't take into account changes in a locale's
    -    time zone before 1970, even if the system's time zone database
    -    supports that information.
    -
    -    QDateTime takes into consideration the Standard Time to Daylight-Saving Time
    -    transition.  For example if the transition is at 2am and the clock goes
    -    forward to 3am, then there is a "missing" hour from 02:00:00 to 02:59:59.999
    -    which QDateTime considers to be invalid.  Any date maths performed
    -    will take this missing hour into account and return a valid result.
    -
    -    \section2 Offset From UTC
    -
    -    A Qt::TimeSpec of Qt::OffsetFromUTC is also supported. This allows you
    -    to define a QDateTime relative to UTC at a fixed offset of a given number
    -    of seconds from UTC.  For example, an offset of +3600 seconds is one hour
    -    ahead of UTC and is usually written in ISO standard notation as
    -    "UTC+01:00".  Daylight-Saving Time never applies with this TimeSpec.
    -
    -    There is no explicit size restriction to the offset seconds, but there is
    -    an implicit limit imposed when using the toString() and fromString()
    -    methods which use a format of [+|-]hh:mm, effectively limiting the range
    -    to +/- 99 hours and 59 minutes and whole minutes only.  Note that currently
    -    no time zone lies outside the range of +/- 14 hours.
    -
    -    \section2 Time Zone Support
    -
    -    A Qt::TimeSpec of Qt::TimeZone is also supported in conjunction with the
    -    QTimeZone class.  This allows you to define a datetime in a named time zone
    -    adhering to a consistent set of daylight-saving transition rules.  For
    -    example a time zone of "Europe/Berlin" will apply the daylight-saving
    -    rules as used in Germany since 1970.  Note that the transition rules
    -    applied depend on the platform support.  See the QTimeZone documentation
    -    for more details.
    -
    -    \sa QDate, QTime, QDateTimeEdit, QTimeZone
    -*/
    -
    -/*!
    -    Constructs a null datetime (i.e. null date and null time). A null
    -    datetime is invalid, since the date is invalid.
    -
    -    \sa isValid()
    -*/
    -QDateTime::QDateTime() noexcept(Data::CanBeSmall)
    -{
    -}
    -
    -
    -/*!
    -    Constructs a datetime with the given \a date, a valid
    -    time(00:00:00.000), and sets the timeSpec() to Qt::LocalTime.
    -*/
    -
    -QDateTime::QDateTime(const QDate &date)
    -    : d(QDateTimePrivate::create(date, QTime(0, 0), Qt::LocalTime, 0))
    -{
    -}
    -
    -/*!
    -    Constructs a datetime with the given \a date and \a time, using
    -    the time specification defined by \a spec.
    -
    -    If \a date is valid and \a time is not, the time will be set to midnight.
    -
    -    If \a spec is Qt::OffsetFromUTC then it will be set to Qt::UTC, i.e. an
    -    offset of 0 seconds. To create a Qt::OffsetFromUTC datetime use the
    -    correct constructor.
    -
    -    If \a spec is Qt::TimeZone then the spec will be set to Qt::LocalTime,
    -    i.e. the current system time zone.  To create a Qt::TimeZone datetime
    -    use the correct constructor.
    -*/
    -
    -QDateTime::QDateTime(const QDate &date, const QTime &time, Qt::TimeSpec spec)
    -    : d(QDateTimePrivate::create(date, time, spec, 0))
    -{
    -}
    -
    -/*!
    -    \since 5.2
    -
    -    Constructs a datetime with the given \a date and \a time, using
    -    the time specification defined by \a spec and \a offsetSeconds seconds.
    -
    -    If \a date is valid and \a time is not, the time will be set to midnight.
    -
    -    If the \a spec is not Qt::OffsetFromUTC then \a offsetSeconds will be ignored.
    -
    -    If the \a spec is Qt::OffsetFromUTC and \a offsetSeconds is 0 then the
    -    timeSpec() will be set to Qt::UTC, i.e. an offset of 0 seconds.
    -
    -    If \a spec is Qt::TimeZone then the spec will be set to Qt::LocalTime,
    -    i.e. the current system time zone.  To create a Qt::TimeZone datetime
    -    use the correct constructor.
    -*/
    -
    -QDateTime::QDateTime(const QDate &date, const QTime &time, Qt::TimeSpec spec, int offsetSeconds)
    -         : d(QDateTimePrivate::create(date, time, spec, offsetSeconds))
    -{
    -}
    -
    -#if QT_CONFIG(timezone)
    -/*!
    -    \since 5.2
    -
    -    Constructs a datetime with the given \a date and \a time, using
    -    the Time Zone specified by \a timeZone.
    -
    -    If \a date is valid and \a time is not, the time will be set to 00:00:00.
    -
    -    If \a timeZone is invalid then the datetime will be invalid.
    -*/
    -
    -QDateTime::QDateTime(const QDate &date, const QTime &time, const QTimeZone &timeZone)
    -    : d(QDateTimePrivate::create(date, time, timeZone))
    -{
    -}
    -#endif // timezone
    -
    -/*!
    -    Constructs a copy of the \a other datetime.
    -*/
    -QDateTime::QDateTime(const QDateTime &other) noexcept
    -    : d(other.d)
    -{
    -}
    -
    -/*!
    -    \since 5.8
    -    Moves the content of the temporary \a other datetime to this object and
    -    leaves \a other in an unspecified (but proper) state.
    -*/
    -QDateTime::QDateTime(QDateTime &&other) noexcept
    -    : d(std::move(other.d))
    -{
    -}
    -
    -/*!
    -    Destroys the datetime.
    -*/
    -QDateTime::~QDateTime()
    -{
    -}
    -
    -/*!
    -    Makes a copy of the \a other datetime and returns a reference to the
    -    copy.
    -*/
    -
    -QDateTime &QDateTime::operator=(const QDateTime &other) noexcept
    -{
    -    d = other.d;
    -    return *this;
    -}
    -/*!
    -    \fn void QDateTime::swap(QDateTime &other)
    -    \since 5.0
    -
    -    Swaps this datetime with \a other. This operation is very fast
    -    and never fails.
    -*/
    -
    -/*!
    -    Returns \c true if both the date and the time are null; otherwise
    -    returns \c false. A null datetime is invalid.
    -
    -    \sa QDate::isNull(), QTime::isNull(), isValid()
    -*/
    -
    -bool QDateTime::isNull() const
    -{
    -    auto status = getStatus(d);
    -    return !status.testFlag(QDateTimePrivate::ValidDate) &&
    -            !status.testFlag(QDateTimePrivate::ValidTime);
    -}
    -
    -/*!
    -    Returns \c true if both the date and the time are valid and they are valid in
    -    the current Qt::TimeSpec, otherwise returns \c false.
    -
    -    If the timeSpec() is Qt::LocalTime or Qt::TimeZone then the date and time are
    -    checked to see if they fall in the Standard Time to Daylight-Saving Time transition
    -    hour, i.e. if the transition is at 2am and the clock goes forward to 3am
    -    then the time from 02:00:00 to 02:59:59.999 is considered to be invalid.
    -
    -    \sa QDate::isValid(), QTime::isValid()
    -*/
    -
    -bool QDateTime::isValid() const
    -{
    -    auto status = getStatus(d);
    -    return status & QDateTimePrivate::ValidDateTime;
    -}
    -
    -/*!
    -    Returns the date part of the datetime.
    -
    -    \sa setDate(), time(), timeSpec()
    -*/
    -
    -QDate QDateTime::date() const
    -{
    -    auto status = getStatus(d);
    -    if (!status.testFlag(QDateTimePrivate::ValidDate))
    -        return QDate();
    -    QDate dt;
    -    msecsToTime(getMSecs(d), &dt, 0);
    -    return dt;
    -}
    -
    -/*!
    -    Returns the time part of the datetime.
    -
    -    \sa setTime(), date(), timeSpec()
    -*/
    -
    -QTime QDateTime::time() const
    -{
    -    auto status = getStatus(d);
    -    if (!status.testFlag(QDateTimePrivate::ValidTime))
    -        return QTime();
    -    QTime tm;
    -    msecsToTime(getMSecs(d), 0, &tm);
    -    return tm;
    -}
    -
    -/*!
    -    Returns the time specification of the datetime.
    -
    -    \sa setTimeSpec(), date(), time(), Qt::TimeSpec
    -*/
    -
    -Qt::TimeSpec QDateTime::timeSpec() const
    -{
    -    return getSpec(d);
    -}
    -
    -#if QT_CONFIG(timezone)
    -/*!
    -    \since 5.2
    -
    -    Returns the time zone of the datetime.
    -
    -    If the timeSpec() is Qt::LocalTime then an instance of the current system
    -    time zone will be returned. Note however that if you copy this time zone
    -    the instance will not remain in sync if the system time zone changes.
    -
    -    \sa setTimeZone(), Qt::TimeSpec
    -*/
    -
    -QTimeZone QDateTime::timeZone() const
    -{
    -    switch (getSpec(d)) {
    -    case Qt::UTC:
    -        return QTimeZone::utc();
    -    case Qt::OffsetFromUTC:
    -        return QTimeZone(d->m_offsetFromUtc);
    -    case Qt::TimeZone:
    -        Q_ASSERT(d->m_timeZone.isValid());
    -        return d->m_timeZone;
    -    case Qt::LocalTime:
    -        return QTimeZone::systemTimeZone();
    -    }
    -    return QTimeZone();
    -}
    -#endif // timezone
    -
    -/*!
    -    \since 5.2
    -
    -    Returns the current Offset From UTC in seconds.
    -
    -    If the timeSpec() is Qt::OffsetFromUTC this will be the value originally set.
    -
    -    If the timeSpec() is Qt::TimeZone this will be the offset effective in the
    -    Time Zone including any Daylight-Saving Offset.
    -
    -    If the timeSpec() is Qt::LocalTime this will be the difference between the
    -    Local Time and UTC including any Daylight-Saving Offset.
    -
    -    If the timeSpec() is Qt::UTC this will be 0.
    -
    -    \sa setOffsetFromUtc()
    -*/
    -
    -int QDateTime::offsetFromUtc() const
    -{
    -    if (!d.isShort())
    -        return d->m_offsetFromUtc;
    -    if (!isValid())
    -        return 0;
    -
    -    auto spec = getSpec(d);
    -    if (spec == Qt::LocalTime) {
    -        // we didn't cache the value, so we need to calculate it now...
    -        qint64 msecs = getMSecs(d);
    -        return (msecs - toMSecsSinceEpoch()) / 1000;
    -    }
    -
    -    Q_ASSERT(spec == Qt::UTC);
    -    return 0;
    -}
    -
    -/*!
    -    \since 5.2
    -
    -    Returns the Time Zone Abbreviation for the datetime.
    -
    -    If the timeSpec() is Qt::UTC this will be "UTC".
    -
    -    If the timeSpec() is Qt::OffsetFromUTC this will be in the format
    -    "UTC[+-]00:00".
    -
    -    If the timeSpec() is Qt::LocalTime then the host system is queried for the
    -    correct abbreviation.
    -
    -    Note that abbreviations may or may not be localized.
    -
    -    Note too that the abbreviation is not guaranteed to be a unique value,
    -    i.e. different time zones may have the same abbreviation.
    -
    -    \sa timeSpec()
    -*/
    -
    -QString QDateTime::timeZoneAbbreviation() const
    -{
    -    switch (getSpec(d)) {
    -    case Qt::UTC:
    -        return QLatin1String("UTC");
    -    case Qt::OffsetFromUTC:
    -        return QLatin1String("UTC") + toOffsetString(Qt::ISODate, d->m_offsetFromUtc);
    -    case Qt::TimeZone:
    -#if !QT_CONFIG(timezone)
    -        break;
    -#else
    -        return d->m_timeZone.d->abbreviation(toMSecsSinceEpoch());
    -#endif // timezone
    -    case Qt::LocalTime:  {
    -        QString abbrev;
    -        auto status = extractDaylightStatus(getStatus(d));
    -        localMSecsToEpochMSecs(getMSecs(d), &status, 0, 0, &abbrev);
    -        return abbrev;
    -        }
    -    }
    -    return QString();
    -}
    -
    -/*!
    -    \since 5.2
    -
    -    Returns if this datetime falls in Daylight-Saving Time.
    -
    -    If the Qt::TimeSpec is not Qt::LocalTime or Qt::TimeZone then will always
    -    return false.
    -
    -    \sa timeSpec()
    -*/
    -
    -bool QDateTime::isDaylightTime() const
    -{
    -    switch (getSpec(d)) {
    -    case Qt::UTC:
    -    case Qt::OffsetFromUTC:
    -        return false;
    -    case Qt::TimeZone:
    -#if !QT_CONFIG(timezone)
    -        break;
    -#else
    -        return d->m_timeZone.d->isDaylightTime(toMSecsSinceEpoch());
    -#endif // timezone
    -    case Qt::LocalTime: {
    -        auto status = extractDaylightStatus(getStatus(d));
    -        if (status == QDateTimePrivate::UnknownDaylightTime)
    -            localMSecsToEpochMSecs(getMSecs(d), &status);
    -        return (status == QDateTimePrivate::DaylightTime);
    -        }
    -    }
    -    return false;
    -}
    -
    -/*!
    -    Sets the date part of this datetime to \a date. If no time is set yet, it
    -    is set to midnight. If \a date is invalid, this QDateTime becomes invalid.
    -
    -    \sa date(), setTime(), setTimeSpec()
    -*/
    -
    -void QDateTime::setDate(const QDate &date)
    -{
    -    setDateTime(d, date, time());
    -}
    -
    -/*!
    -    Sets the time part of this datetime to \a time. If \a time is not valid,
    -    this function sets it to midnight. Therefore, it's possible to clear any
    -    set time in a QDateTime by setting it to a default QTime:
    -
    -    \code
    -        QDateTime dt = QDateTime::currentDateTime();
    -        dt.setTime(QTime());
    -    \endcode
    -
    -    \sa time(), setDate(), setTimeSpec()
    -*/
    -
    -void QDateTime::setTime(const QTime &time)
    -{
    -    setDateTime(d, date(), time);
    -}
    -
    -/*!
    -    Sets the time specification used in this datetime to \a spec.
    -    The datetime will refer to a different point in time.
    -
    -    If \a spec is Qt::OffsetFromUTC then the timeSpec() will be set
    -    to Qt::UTC, i.e. an effective offset of 0.
    -
    -    If \a spec is Qt::TimeZone then the spec will be set to Qt::LocalTime,
    -    i.e. the current system time zone.
    -
    -    Example:
    -    \snippet code/src_corelib_tools_qdatetime.cpp 19
    -
    -    \sa timeSpec(), setDate(), setTime(), setTimeZone(), Qt::TimeSpec
    -*/
    -
    -void QDateTime::setTimeSpec(Qt::TimeSpec spec)
    -{
    -    QT_PREPEND_NAMESPACE(setTimeSpec(d, spec, 0));
    -    checkValidDateTime(d);
    -}
    -
    -/*!
    -    \since 5.2
    -
    -    Sets the timeSpec() to Qt::OffsetFromUTC and the offset to \a offsetSeconds.
    -    The datetime will refer to a different point in time.
    -
    -    The maximum and minimum offset is 14 positive or negative hours.  If
    -    \a offsetSeconds is larger or smaller than that, then the result is
    -    undefined.
    -
    -    If \a offsetSeconds is 0 then the timeSpec() will be set to Qt::UTC.
    -
    -    \sa isValid(), offsetFromUtc()
    -*/
    -
    -void QDateTime::setOffsetFromUtc(int offsetSeconds)
    -{
    -    QT_PREPEND_NAMESPACE(setTimeSpec(d, Qt::OffsetFromUTC, offsetSeconds));
    -    checkValidDateTime(d);
    -}
    -
    -#if QT_CONFIG(timezone)
    -/*!
    -    \since 5.2
    -
    -    Sets the time zone used in this datetime to \a toZone.
    -    The datetime will refer to a different point in time.
    -
    -    If \a toZone is invalid then the datetime will be invalid.
    -
    -    \sa timeZone(), Qt::TimeSpec
    -*/
    -
    -void QDateTime::setTimeZone(const QTimeZone &toZone)
    -{
    -    d.detach();         // always detach
    -    d->m_status = mergeSpec(d->m_status, Qt::TimeZone);
    -    d->m_offsetFromUtc = 0;
    -    d->m_timeZone = toZone;
    -    refreshDateTime(d);
    -}
    -#endif // timezone
    -
    -/*!
    -    \since 4.7
    -
    -    Returns the datetime as the number of milliseconds that have passed
    -    since 1970-01-01T00:00:00.000, Coordinated Universal Time (Qt::UTC).
    -
    -    On systems that do not support time zones, this function will
    -    behave as if local time were Qt::UTC.
    -
    -    The behavior for this function is undefined if the datetime stored in
    -    this object is not valid. However, for all valid dates, this function
    -    returns a unique value.
    -
    -    \sa toSecsSinceEpoch(), setMSecsSinceEpoch()
    -*/
    -qint64 QDateTime::toMSecsSinceEpoch() const
    -{
    -    switch (getSpec(d)) {
    -    case Qt::UTC:
    -        return getMSecs(d);
    -
    -    case Qt::OffsetFromUTC:
    -        return d->m_msecs - (d->m_offsetFromUtc * 1000);
    -
    -    case Qt::LocalTime: {
    -        // recalculate the local timezone
    -        auto status = extractDaylightStatus(getStatus(d));
    -        return localMSecsToEpochMSecs(getMSecs(d), &status);
    -    }
    -
    -    case Qt::TimeZone:
    -#if !QT_CONFIG(timezone)
    -        return 0;
    -#else
    -        return QDateTimePrivate::zoneMSecsToEpochMSecs(d->m_msecs, d->m_timeZone,
    -                                                       extractDaylightStatus(getStatus(d)));
    -#endif
    -    }
    -    Q_UNREACHABLE();
    -    return 0;
    -}
    -
    -/*!
    -    \since 5.8
    -
    -    Returns the datetime as the number of seconds that have passed since
    -    1970-01-01T00:00:00.000, Coordinated Universal Time (Qt::UTC).
    -
    -    On systems that do not support time zones, this function will
    -    behave as if local time were Qt::UTC.
    -
    -    The behavior for this function is undefined if the datetime stored in
    -    this object is not valid. However, for all valid dates, this function
    -    returns a unique value.
    -
    -    \sa toMSecsSinceEpoch(), setSecsSinceEpoch()
    -*/
    -qint64 QDateTime::toSecsSinceEpoch() const
    -{
    -    return toMSecsSinceEpoch() / 1000;
    -}
    -
    -#if QT_DEPRECATED_SINCE(5, 8)
    -/*!
    -    \deprecated
    -
    -    Returns the datetime as the number of seconds that have passed
    -    since 1970-01-01T00:00:00, Coordinated Universal Time (Qt::UTC).
    -
    -    On systems that do not support time zones, this function will
    -    behave as if local time were Qt::UTC.
    -
    -    \note This function returns a 32-bit unsigned integer and is deprecated.
    -
    -    If the date is outside the range 1970-01-01T00:00:00 to
    -    2106-02-07T06:28:14, this function returns -1 cast to an unsigned integer
    -    (i.e., 0xFFFFFFFF).
    -
    -    To get an extended range, use toMSecsSinceEpoch() or toSecsSinceEpoch().
    -
    -    \sa toSecsSinceEpoch(), toMSecsSinceEpoch(), setTime_t()
    -*/
    -
    -uint QDateTime::toTime_t() const
    -{
    -    if (!isValid())
    -        return uint(-1);
    -    qint64 retval = toMSecsSinceEpoch() / 1000;
    -    if (quint64(retval) >= Q_UINT64_C(0xFFFFFFFF))
    -        return uint(-1);
    -    return uint(retval);
    -}
    -#endif
    -
    -/*!
    -    \since 4.7
    -
    -    Sets the date and time given the number of milliseconds \a msecs that have
    -    passed since 1970-01-01T00:00:00.000, Coordinated Universal Time
    -    (Qt::UTC). On systems that do not support time zones this function
    -    will behave as if local time were Qt::UTC.
    -
    -    Note that passing the minimum of \c qint64
    -    (\c{std::numeric_limits::min()}) to \a msecs will result in
    -    undefined behavior.
    -
    -    \sa toMSecsSinceEpoch(), setSecsSinceEpoch()
    -*/
    -void QDateTime::setMSecsSinceEpoch(qint64 msecs)
    -{
    -    const auto spec = getSpec(d);
    -    auto status = getStatus(d);
    -
    -    status &= ~QDateTimePrivate::ValidityMask;
    -    switch (spec) {
    -    case Qt::UTC:
    -        status = status
    -                    | QDateTimePrivate::ValidDate
    -                    | QDateTimePrivate::ValidTime
    -                    | QDateTimePrivate::ValidDateTime;
    -        break;
    -    case Qt::OffsetFromUTC:
    -        msecs = msecs + (d->m_offsetFromUtc * 1000);
    -        status = status
    -                    | QDateTimePrivate::ValidDate
    -                    | QDateTimePrivate::ValidTime
    -                    | QDateTimePrivate::ValidDateTime;
    -        break;
    -    case Qt::TimeZone:
    -        Q_ASSERT(!d.isShort());
    -#if QT_CONFIG(timezone)
    -        // Docs state any LocalTime before 1970-01-01 will *not* have any DST applied
    -        // but all affected times afterwards will have DST applied.
    -        d.detach();
    -        if (msecs >= 0) {
    -            status = mergeDaylightStatus(status,
    -                                         d->m_timeZone.d->isDaylightTime(msecs)
    -                                         ? QDateTimePrivate::DaylightTime
    -                                         : QDateTimePrivate::StandardTime);
    -            d->m_offsetFromUtc = d->m_timeZone.d->offsetFromUtc(msecs);
    -        } else {
    -            status = mergeDaylightStatus(status, QDateTimePrivate::StandardTime);
    -            d->m_offsetFromUtc = d->m_timeZone.d->standardTimeOffset(msecs);
    -        }
    -        msecs = msecs + (d->m_offsetFromUtc * 1000);
    -        status = status
    -                    | QDateTimePrivate::ValidDate
    -                    | QDateTimePrivate::ValidTime
    -                    | QDateTimePrivate::ValidDateTime;
    -#endif // timezone
    -        break;
    -    case Qt::LocalTime: {
    -        QDate dt;
    -        QTime tm;
    -        QDateTimePrivate::DaylightStatus dstStatus;
    -        epochMSecsToLocalTime(msecs, &dt, &tm, &dstStatus);
    -        setDateTime(d, dt, tm);
    -        msecs = getMSecs(d);
    -        status = mergeDaylightStatus(getStatus(d), dstStatus);
    -        break;
    -        }
    -    }
    -
    -    if (msecsCanBeSmall(msecs) && d.isShort()) {
    -        // we can keep short
    -        d.data.msecs = qintptr(msecs);
    -        d.data.status = status;
    -    } else {
    -        d.detach();
    -        d->m_status = status & ~QDateTimePrivate::ShortData;
    -        d->m_msecs = msecs;
    -    }
    -
    -    if (spec == Qt::LocalTime || spec == Qt::TimeZone)
    -        refreshDateTime(d);
    -}
    -
    -/*!
    -    \since 5.8
    -
    -    Sets the date and time given the number of seconds \a secs that have
    -    passed since 1970-01-01T00:00:00.000, Coordinated Universal Time
    -    (Qt::UTC). On systems that do not support time zones this function
    -    will behave as if local time were Qt::UTC.
    -
    -    \sa toSecsSinceEpoch(), setMSecsSinceEpoch()
    -*/
    -void QDateTime::setSecsSinceEpoch(qint64 secs)
    -{
    -    setMSecsSinceEpoch(secs * 1000);
    -}
    -
    -#if QT_DEPRECATED_SINCE(5, 8)
    -/*!
    -    \fn void QDateTime::setTime_t(uint seconds)
    -    \deprecated
    -
    -    Sets the date and time given the number of \a seconds that have
    -    passed since 1970-01-01T00:00:00, Coordinated Universal Time
    -    (Qt::UTC). On systems that do not support time zones this function
    -    will behave as if local time were Qt::UTC.
    -
    -    \note This function is deprecated. For new code, use setSecsSinceEpoch().
    -
    -    \sa toTime_t()
    -*/
    -
    -void QDateTime::setTime_t(uint secsSince1Jan1970UTC)
    -{
    -    setMSecsSinceEpoch((qint64)secsSince1Jan1970UTC * 1000);
    -}
    -#endif
    -
    -#if QT_CONFIG(datestring)
    -/*!
    -    \fn QString QDateTime::toString(Qt::DateFormat format) const
    -
    -    \overload
    -
    -    Returns the datetime as a string in the \a format given.
    -
    -    If the \a format is Qt::TextDate, the string is formatted in
    -    the default way. QDate::shortDayName(), QDate::shortMonthName(),
    -    and QTime::toString() are used to generate the string, so the
    -    day and month names will be localized names using the system locale,
    -    i.e. QLocale::system(). An example of this formatting is
    -    "Wed May 20 03:40:13 1998".
    -
    -    If the \a format is Qt::ISODate, the string format corresponds
    -    to the ISO 8601 extended specification for representations of
    -    dates and times, taking the form yyyy-MM-ddTHH:mm:ss[Z|[+|-]HH:mm],
    -    depending on the timeSpec() of the QDateTime. If the timeSpec()
    -    is Qt::UTC, Z will be appended to the string; if the timeSpec() is
    -    Qt::OffsetFromUTC, the offset in hours and minutes from UTC will
    -    be appended to the string. To include milliseconds in the ISO 8601
    -    date, use the \a format Qt::ISODateWithMs, which corresponds to
    -    yyyy-MM-ddTHH:mm:ss.zzz[Z|[+|-]HH:mm].
    -
    -    If the \a format is Qt::SystemLocaleShortDate or
    -    Qt::SystemLocaleLongDate, the string format depends on the locale
    -    settings of the system. Identical to calling
    -    QLocale::system().toString(datetime, QLocale::ShortFormat) or
    -    QLocale::system().toString(datetime, QLocale::LongFormat).
    -
    -    If the \a format is Qt::DefaultLocaleShortDate or
    -    Qt::DefaultLocaleLongDate, the string format depends on the
    -    default application locale. This is the locale set with
    -    QLocale::setDefault(), or the system locale if no default locale
    -    has been set. Identical to calling QLocale().toString(datetime,
    -    QLocale::ShortFormat) or QLocale().toString(datetime,
    -    QLocale::LongFormat).
    -
    -    If the \a format is Qt::RFC2822Date, the string is formatted
    -    following \l{RFC 2822}.
    -
    -    If the datetime is invalid, an empty string will be returned.
    -
    -    \warning The Qt::ISODate format is only valid for years in the
    -    range 0 to 9999. This restriction may apply to locale-aware
    -    formats as well, depending on the locale settings.
    -
    -    \sa fromString(), QDate::toString(), QTime::toString(),
    -    QLocale::toString()
    -*/
    -
    -QString QDateTime::toString(Qt::DateFormat format) const
    -{
    -    QString buf;
    -    if (!isValid())
    -        return buf;
    -
    -    switch (format) {
    -    case Qt::SystemLocaleDate:
    -    case Qt::SystemLocaleShortDate:
    -        return QLocale::system().toString(*this, QLocale::ShortFormat);
    -    case Qt::SystemLocaleLongDate:
    -        return QLocale::system().toString(*this, QLocale::LongFormat);
    -    case Qt::LocaleDate:
    -    case Qt::DefaultLocaleShortDate:
    -        return QLocale().toString(*this, QLocale::ShortFormat);
    -    case Qt::DefaultLocaleLongDate:
    -        return QLocale().toString(*this, QLocale::LongFormat);
    -    case Qt::RFC2822Date: {
    -        buf = QLocale::c().toString(*this, QStringViewLiteral("dd MMM yyyy hh:mm:ss "));
    -        buf += toOffsetString(Qt::TextDate, offsetFromUtc());
    -        return buf;
    -    }
    -    default:
    -#if QT_CONFIG(textdate)
    -    case Qt::TextDate: {
    -        const QPair p = getDateTime(d);
    -        buf = p.first.toString(Qt::TextDate);
    -        // Insert time between date's day and year:
    -        buf.insert(buf.lastIndexOf(QLatin1Char(' ')),
    -                   QLatin1Char(' ') + p.second.toString(Qt::TextDate));
    -        // Append zone/offset indicator, as appropriate:
    -        switch (timeSpec()) {
    -        case Qt::LocalTime:
    -            break;
    -# if QT_CONFIG(timezone)
    -        case Qt::TimeZone:
    -            buf += QLatin1Char(' ') + d->m_timeZone.abbreviation(*this);
    -            break;
    -# endif
    -        default:
    -            buf += QLatin1String(" GMT");
    -            if (getSpec(d) == Qt::OffsetFromUTC)
    -                buf += toOffsetString(Qt::TextDate, offsetFromUtc());
    -        }
    -        return buf;
    -    }
    -#endif
    -    case Qt::ISODate:
    -    case Qt::ISODateWithMs: {
    -        const QPair p = getDateTime(d);
    -        const QDate &dt = p.first;
    -        const QTime &tm = p.second;
    -        buf = dt.toString(Qt::ISODate);
    -        if (buf.isEmpty())
    -            return QString();   // failed to convert
    -        buf += QLatin1Char('T');
    -        buf += tm.toString(format);
    -        switch (getSpec(d)) {
    -        case Qt::UTC:
    -            buf += QLatin1Char('Z');
    -            break;
    -        case Qt::OffsetFromUTC:
    -#if QT_CONFIG(timezone)
    -        case Qt::TimeZone:
    -#endif
    -            buf += toOffsetString(Qt::ISODate, offsetFromUtc());
    -            break;
    -        default:
    -            break;
    -        }
    -        return buf;
    -    }
    -    }
    -}
    -
    -/*!
    -    \fn QString QDateTime::toString(const QString &format) const
    -    \fn QString QDateTime::toString(QStringView format) const
    -
    -    Returns the datetime as a string. The \a format parameter
    -    determines the format of the result string.
    -
    -    These expressions may be used for the date:
    -
    -    \table
    -    \header \li Expression \li Output
    -    \row \li d \li the day as number without a leading zero (1 to 31)
    -    \row \li dd \li the day as number with a leading zero (01 to 31)
    -    \row \li ddd
    -            \li the abbreviated localized day name (e.g. 'Mon' to 'Sun').
    -            Uses the system locale to localize the name, i.e. QLocale::system().
    -    \row \li dddd
    -            \li the long localized day name (e.g. 'Monday' to 'Sunday').
    -            Uses the system locale to localize the name, i.e. QLocale::system().
    -    \row \li M \li the month as number without a leading zero (1-12)
    -    \row \li MM \li the month as number with a leading zero (01-12)
    -    \row \li MMM
    -            \li the abbreviated localized month name (e.g. 'Jan' to 'Dec').
    -            Uses the system locale to localize the name, i.e. QLocale::system().
    -    \row \li MMMM
    -            \li the long localized month name (e.g. 'January' to 'December').
    -            Uses the system locale to localize the name, i.e. QLocale::system().
    -    \row \li yy \li the year as two digit number (00-99)
    -    \row \li yyyy \li the year as four digit number
    -    \endtable
    -
    -    These expressions may be used for the time:
    -
    -    \table
    -    \header \li Expression \li Output
    -    \row \li h
    -         \li the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
    -    \row \li hh
    -         \li the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
    -    \row \li H
    -         \li the hour without a leading zero (0 to 23, even with AM/PM display)
    -    \row \li HH
    -         \li the hour with a leading zero (00 to 23, even with AM/PM display)
    -    \row \li m \li the minute without a leading zero (0 to 59)
    -    \row \li mm \li the minute with a leading zero (00 to 59)
    -    \row \li s \li the whole second without a leading zero (0 to 59)
    -    \row \li ss \li the whole second with a leading zero where applicable (00 to 59)
    -    \row \li z \li the fractional part of the second, to go after a decimal
    -                point, without trailing zeroes (0 to 999).  Thus "\c{s.z}"
    -                reports the seconds to full available (millisecond) precision
    -                without trailing zeroes.
    -    \row \li zzz \li the fractional part of the second, to millisecond
    -                precision, including trailing zeroes where applicable (000 to 999).
    -    \row \li AP or A
    -         \li use AM/PM display. \e A/AP will be replaced by either "AM" or "PM".
    -    \row \li ap or a
    -         \li use am/pm display. \e a/ap will be replaced by either "am" or "pm".
    -    \row \li t \li the timezone (for example "CEST")
    -    \endtable
    -
    -    Any sequence of characters enclosed in single quotes will be included
    -    verbatim in the output string (stripped of the quotes), even if it contains
    -    formatting characters. Two consecutive single quotes ("''") are replaced by
    -    a single quote in the output. All other characters in the format string are
    -    included verbatim in the output string.
    -
    -    Formats without separators (e.g. "ddMM") are supported but must be used with
    -    care, as the resulting strings aren't always reliably readable (e.g. if "dM"
    -    produces "212" it could mean either the 2nd of December or the 21st of
    -    February).
    -
    -    Example format strings (assumed that the QDateTime is 21 May 2001
    -    14:13:09.120):
    -
    -    \table
    -    \header \li Format       \li Result
    -    \row \li dd.MM.yyyy      \li 21.05.2001
    -    \row \li ddd MMMM d yy   \li Tue May 21 01
    -    \row \li hh:mm:ss.zzz    \li 14:13:09.120
    -    \row \li hh:mm:ss.z      \li 14:13:09.12
    -    \row \li h:m:s ap        \li 2:13:9 pm
    -    \endtable
    -
    -    If the datetime is invalid, an empty string will be returned.
    -
    -    \sa fromString(), QDate::toString(), QTime::toString(), QLocale::toString()
    -*/
    -QString QDateTime::toString(QStringView format) const
    -{
    -    return QLocale::system().toString(*this, format); // QLocale::c() ### Qt6
    -}
    -
    -#if QT_STRINGVIEW_LEVEL < 2
    -QString QDateTime::toString(const QString &format) const
    -{
    -    return toString(qToStringViewIgnoringNull(format));
    -}
    -#endif
    -
    -#endif // datestring
    -
    -static inline void massageAdjustedDateTime(const QDateTimeData &d, QDate *date, QTime *time)
    -{
    -    /*
    -      If we have just adjusted to a day with a DST transition, our given time
    -      may lie in the transition hour (either missing or duplicated).  For any
    -      other time, telling mktime (deep in the bowels of localMSecsToEpochMSecs)
    -      we don't know its DST-ness will produce no adjustment (just a decision as
    -      to its DST-ness); but for a time in spring's missing hour it'll adjust the
    -      time while picking a DST-ness.  (Handling of autumn is trickier, as either
    -      DST-ness is valid, without adjusting the time.  We might want to propagate
    -      the daylight status in that case, but it's hard to do so without breaking
    -      (far more common) other cases; and it makes little difference, as the two
    -      answers do then differ only in DST-ness.)
    -    */
    -    auto spec = getSpec(d);
    -    if (spec == Qt::LocalTime) {
    -        QDateTimePrivate::DaylightStatus status = QDateTimePrivate::UnknownDaylightTime;
    -        localMSecsToEpochMSecs(timeToMSecs(*date, *time), &status, date, time);
    -#if QT_CONFIG(timezone)
    -    } else if (spec == Qt::TimeZone) {
    -        QDateTimePrivate::zoneMSecsToEpochMSecs(timeToMSecs(*date, *time),
    -                                                d->m_timeZone,
    -                                                QDateTimePrivate::UnknownDaylightTime,
    -                                                date, time);
    -#endif // timezone
    -    }
    -}
    -
    -/*!
    -    Returns a QDateTime object containing a datetime \a ndays days
    -    later than the datetime of this object (or earlier if \a ndays is
    -    negative).
    -
    -    If the timeSpec() is Qt::LocalTime and the resulting
    -    date and time fall in the Standard Time to Daylight-Saving Time transition
    -    hour then the result will be adjusted accordingly, i.e. if the transition
    -    is at 2am and the clock goes forward to 3am and the result falls between
    -    2am and 3am then the result will be adjusted to fall after 3am.
    -
    -    \sa daysTo(), addMonths(), addYears(), addSecs()
    -*/
    -
    -QDateTime QDateTime::addDays(qint64 ndays) const
    -{
    -    QDateTime dt(*this);
    -    QPair p = getDateTime(d);
    -    QDate &date = p.first;
    -    QTime &time = p.second;
    -    date = date.addDays(ndays);
    -    massageAdjustedDateTime(dt.d, &date, &time);
    -    setDateTime(dt.d, date, time);
    -    return dt;
    -}
    -
    -/*!
    -    Returns a QDateTime object containing a datetime \a nmonths months
    -    later than the datetime of this object (or earlier if \a nmonths
    -    is negative).
    -
    -    If the timeSpec() is Qt::LocalTime and the resulting
    -    date and time fall in the Standard Time to Daylight-Saving Time transition
    -    hour then the result will be adjusted accordingly, i.e. if the transition
    -    is at 2am and the clock goes forward to 3am and the result falls between
    -    2am and 3am then the result will be adjusted to fall after 3am.
    -
    -    \sa daysTo(), addDays(), addYears(), addSecs()
    -*/
    -
    -QDateTime QDateTime::addMonths(int nmonths) const
    -{
    -    QDateTime dt(*this);
    -    QPair p = getDateTime(d);
    -    QDate &date = p.first;
    -    QTime &time = p.second;
    -    date = date.addMonths(nmonths);
    -    massageAdjustedDateTime(dt.d, &date, &time);
    -    setDateTime(dt.d, date, time);
    -    return dt;
    -}
    -
    -/*!
    -    Returns a QDateTime object containing a datetime \a nyears years
    -    later than the datetime of this object (or earlier if \a nyears is
    -    negative).
    -
    -    If the timeSpec() is Qt::LocalTime and the resulting
    -    date and time fall in the Standard Time to Daylight-Saving Time transition
    -    hour then the result will be adjusted accordingly, i.e. if the transition
    -    is at 2am and the clock goes forward to 3am and the result falls between
    -    2am and 3am then the result will be adjusted to fall after 3am.
    -
    -    \sa daysTo(), addDays(), addMonths(), addSecs()
    -*/
    -
    -QDateTime QDateTime::addYears(int nyears) const
    -{
    -    QDateTime dt(*this);
    -    QPair p = getDateTime(d);
    -    QDate &date = p.first;
    -    QTime &time = p.second;
    -    date = date.addYears(nyears);
    -    massageAdjustedDateTime(dt.d, &date, &time);
    -    setDateTime(dt.d, date, time);
    -    return dt;
    -}
    -
    -/*!
    -    Returns a QDateTime object containing a datetime \a s seconds
    -    later than the datetime of this object (or earlier if \a s is
    -    negative).
    -
    -    If this datetime is invalid, an invalid datetime will be returned.
    -
    -    \sa addMSecs(), secsTo(), addDays(), addMonths(), addYears()
    -*/
    -
    -QDateTime QDateTime::addSecs(qint64 s) const
    -{
    -    return addMSecs(s * 1000);
    -}
    -
    -/*!
    -    Returns a QDateTime object containing a datetime \a msecs miliseconds
    -    later than the datetime of this object (or earlier if \a msecs is
    -    negative).
    -
    -    If this datetime is invalid, an invalid datetime will be returned.
    -
    -    \sa addSecs(), msecsTo(), addDays(), addMonths(), addYears()
    -*/
    -QDateTime QDateTime::addMSecs(qint64 msecs) const
    -{
    -    if (!isValid())
    -        return QDateTime();
    -
    -    QDateTime dt(*this);
    -    auto spec = getSpec(d);
    -    if (spec == Qt::LocalTime || spec == Qt::TimeZone) {
    -        // Convert to real UTC first in case crosses DST transition
    -        dt.setMSecsSinceEpoch(toMSecsSinceEpoch() + msecs);
    -    } else {
    -        // No need to convert, just add on
    -        if (d.isShort()) {
    -            // need to check if we need to enlarge first
    -            msecs += dt.d.data.msecs;
    -            if (msecsCanBeSmall(msecs)) {
    -                dt.d.data.msecs = qintptr(msecs);
    -            } else {
    -                dt.d.detach();
    -                dt.d->m_msecs = msecs;
    -            }
    -        } else {
    -            dt.d.detach();
    -            dt.d->m_msecs += msecs;
    -        }
    -    }
    -    return dt;
    -}
    -
    -/*!
    -    Returns the number of days from this datetime to the \a other
    -    datetime. The number of days is counted as the number of times
    -    midnight is reached between this datetime to the \a other
    -    datetime. This means that a 10 minute difference from 23:55 to
    -    0:05 the next day counts as one day.
    -
    -    If the \a other datetime is earlier than this datetime,
    -    the value returned is negative.
    -
    -    Example:
    -    \snippet code/src_corelib_tools_qdatetime.cpp 15
    -
    -    \sa addDays(), secsTo(), msecsTo()
    -*/
    -
    -qint64 QDateTime::daysTo(const QDateTime &other) const
    -{
    -    return date().daysTo(other.date());
    -}
    -
    -/*!
    -    Returns the number of seconds from this datetime to the \a other
    -    datetime. If the \a other datetime is earlier than this datetime,
    -    the value returned is negative.
    -
    -    Before performing the comparison, the two datetimes are converted
    -    to Qt::UTC to ensure that the result is correct if daylight-saving
    -    (DST) applies to one of the two datetimes but not the other.
    -
    -    Returns 0 if either datetime is invalid.
    -
    -    Example:
    -    \snippet code/src_corelib_tools_qdatetime.cpp 11
    -
    -    \sa addSecs(), daysTo(), QTime::secsTo()
    -*/
    -
    -qint64 QDateTime::secsTo(const QDateTime &other) const
    -{
    -    return (msecsTo(other) / 1000);
    -}
    -
    -/*!
    -    Returns the number of milliseconds from this datetime to the \a other
    -    datetime. If the \a other datetime is earlier than this datetime,
    -    the value returned is negative.
    -
    -    Before performing the comparison, the two datetimes are converted
    -    to Qt::UTC to ensure that the result is correct if daylight-saving
    -    (DST) applies to one of the two datetimes and but not the other.
    -
    -    Returns 0 if either datetime is invalid.
    -
    -    \sa addMSecs(), daysTo(), QTime::msecsTo()
    -*/
    -
    -qint64 QDateTime::msecsTo(const QDateTime &other) const
    -{
    -    if (!isValid() || !other.isValid())
    -        return 0;
    -
    -    return other.toMSecsSinceEpoch() - toMSecsSinceEpoch();
    -}
    -
    -/*!
    -    \fn QDateTime QDateTime::toTimeSpec(Qt::TimeSpec spec) const
    -
    -    Returns a copy of this datetime converted to the given time
    -    \a spec.
    -
    -    If \a spec is Qt::OffsetFromUTC then it is set to Qt::UTC.  To set to a
    -    spec of Qt::OffsetFromUTC use toOffsetFromUtc().
    -
    -    If \a spec is Qt::TimeZone then it is set to Qt::LocalTime,
    -    i.e. the local Time Zone.
    -
    -    Example:
    -    \snippet code/src_corelib_tools_qdatetime.cpp 16
    -
    -    \sa timeSpec(), toTimeZone(), toUTC(), toLocalTime()
    -*/
    -
    -QDateTime QDateTime::toTimeSpec(Qt::TimeSpec spec) const
    -{
    -    if (getSpec(d) == spec && (spec == Qt::UTC || spec == Qt::LocalTime))
    -        return *this;
    -
    -    if (!isValid()) {
    -        QDateTime ret = *this;
    -        ret.setTimeSpec(spec);
    -        return ret;
    -    }
    -
    -    return fromMSecsSinceEpoch(toMSecsSinceEpoch(), spec, 0);
    -}
    -
    -/*!
    -    \since 5.2
    -
    -    \fn QDateTime QDateTime::toOffsetFromUtc(int offsetSeconds) const
    -
    -    Returns a copy of this datetime converted to a spec of Qt::OffsetFromUTC
    -    with the given \a offsetSeconds.
    -
    -    If the \a offsetSeconds equals 0 then a UTC datetime will be returned
    -
    -    \sa setOffsetFromUtc(), offsetFromUtc(), toTimeSpec()
    -*/
    -
    -QDateTime QDateTime::toOffsetFromUtc(int offsetSeconds) const
    -{
    -    if (getSpec(d) == Qt::OffsetFromUTC
    -            && d->m_offsetFromUtc == offsetSeconds)
    -        return *this;
    -
    -    if (!isValid()) {
    -        QDateTime ret = *this;
    -        ret.setOffsetFromUtc(offsetSeconds);
    -        return ret;
    -    }
    -
    -    return fromMSecsSinceEpoch(toMSecsSinceEpoch(), Qt::OffsetFromUTC, offsetSeconds);
    -}
    -
    -#if QT_CONFIG(timezone)
    -/*!
    -    \since 5.2
    -
    -    Returns a copy of this datetime converted to the given \a timeZone
    -
    -    \sa timeZone(), toTimeSpec()
    -*/
    -
    -QDateTime QDateTime::toTimeZone(const QTimeZone &timeZone) const
    -{
    -    if (getSpec(d) == Qt::TimeZone && d->m_timeZone == timeZone)
    -        return *this;
    -
    -    if (!isValid()) {
    -        QDateTime ret = *this;
    -        ret.setTimeZone(timeZone);
    -        return ret;
    -    }
    -
    -    return fromMSecsSinceEpoch(toMSecsSinceEpoch(), timeZone);
    -}
    -#endif // timezone
    -
    -/*!
    -    Returns \c true if this datetime is equal to the \a other datetime;
    -    otherwise returns \c false.
    -
    -    \sa operator!=()
    -*/
    -
    -bool QDateTime::operator==(const QDateTime &other) const
    -{
    -    if (getSpec(d) == Qt::LocalTime
    -        && getStatus(d) == getStatus(other.d)) {
    -        return getMSecs(d) == getMSecs(other.d);
    -    }
    -    // Convert to UTC and compare
    -    return (toMSecsSinceEpoch() == other.toMSecsSinceEpoch());
    -}
    -
    -/*!
    -    \fn bool QDateTime::operator!=(const QDateTime &other) const
    -
    -    Returns \c true if this datetime is different from the \a other
    -    datetime; otherwise returns \c false.
    -
    -    Two datetimes are different if either the date, the time, or the
    -    time zone components are different.
    -
    -    \sa operator==()
    -*/
    -
    -/*!
    -    Returns \c true if this datetime is earlier than the \a other
    -    datetime; otherwise returns \c false.
    -*/
    -
    -bool QDateTime::operator<(const QDateTime &other) const
    -{
    -    if (getSpec(d) == Qt::LocalTime
    -        && getStatus(d) == getStatus(other.d)) {
    -        return getMSecs(d) < getMSecs(other.d);
    -    }
    -    // Convert to UTC and compare
    -    return (toMSecsSinceEpoch() < other.toMSecsSinceEpoch());
    -}
    -
    -/*!
    -    \fn bool QDateTime::operator<=(const QDateTime &other) const
    -
    -    Returns \c true if this datetime is earlier than or equal to the
    -    \a other datetime; otherwise returns \c false.
    -*/
    -
    -/*!
    -    \fn bool QDateTime::operator>(const QDateTime &other) const
    -
    -    Returns \c true if this datetime is later than the \a other datetime;
    -    otherwise returns \c false.
    -*/
    -
    -/*!
    -    \fn bool QDateTime::operator>=(const QDateTime &other) const
    -
    -    Returns \c true if this datetime is later than or equal to the
    -    \a other datetime; otherwise returns \c false.
    -*/
    -
    -/*!
    -    \fn QDateTime QDateTime::currentDateTime()
    -    Returns the current datetime, as reported by the system clock, in
    -    the local time zone.
    -
    -    \sa currentDateTimeUtc(), QDate::currentDate(), QTime::currentTime(), toTimeSpec()
    -*/
    -
    -/*!
    -    \fn QDateTime QDateTime::currentDateTimeUtc()
    -    \since 4.7
    -    Returns the current datetime, as reported by the system clock, in
    -    UTC.
    -
    -    \sa currentDateTime(), QDate::currentDate(), QTime::currentTime(), toTimeSpec()
    -*/
    -
    -/*!
    -    \fn qint64 QDateTime::currentMSecsSinceEpoch()
    -    \since 4.7
    -
    -    Returns the number of milliseconds since 1970-01-01T00:00:00 Universal
    -    Coordinated Time. This number is like the POSIX time_t variable, but
    -    expressed in milliseconds instead.
    -
    -    \sa currentDateTime(), currentDateTimeUtc(), toTime_t(), toTimeSpec()
    -*/
    -
    -/*!
    -    \fn qint64 QDateTime::currentSecsSinceEpoch()
    -    \since 5.8
    -
    -    Returns the number of seconds since 1970-01-01T00:00:00 Universal
    -    Coordinated Time.
    -
    -    \sa currentMSecsSinceEpoch()
    -*/
    -
    -#if defined(Q_OS_WIN)
    -static inline uint msecsFromDecomposed(int hour, int minute, int sec, int msec = 0)
    -{
    -    return MSECS_PER_HOUR * hour + MSECS_PER_MIN * minute + 1000 * sec + msec;
    -}
    -
    -QDate QDate::currentDate()
    -{
    -    QDate d;
    -    SYSTEMTIME st;
    -    memset(&st, 0, sizeof(SYSTEMTIME));
    -    GetLocalTime(&st);
    -    d.jd = julianDayFromDate(st.wYear, st.wMonth, st.wDay);
    -    return d;
    -}
    -
    -QTime QTime::currentTime()
    -{
    -    QTime ct;
    -    SYSTEMTIME st;
    -    memset(&st, 0, sizeof(SYSTEMTIME));
    -    GetLocalTime(&st);
    -    ct.setHMS(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
    -    return ct;
    -}
    -
    -QDateTime QDateTime::currentDateTime()
    -{
    -    QDate d;
    -    QTime t;
    -    SYSTEMTIME st;
    -    memset(&st, 0, sizeof(SYSTEMTIME));
    -    GetLocalTime(&st);
    -    d.jd = julianDayFromDate(st.wYear, st.wMonth, st.wDay);
    -    t.mds = msecsFromDecomposed(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
    -    return QDateTime(d, t);
    -}
    -
    -QDateTime QDateTime::currentDateTimeUtc()
    -{
    -    QDate d;
    -    QTime t;
    -    SYSTEMTIME st;
    -    memset(&st, 0, sizeof(SYSTEMTIME));
    -    GetSystemTime(&st);
    -    d.jd = julianDayFromDate(st.wYear, st.wMonth, st.wDay);
    -    t.mds = msecsFromDecomposed(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
    -    return QDateTime(d, t, Qt::UTC);
    -}
    -
    -qint64 QDateTime::currentMSecsSinceEpoch() noexcept
    -{
    -    SYSTEMTIME st;
    -    memset(&st, 0, sizeof(SYSTEMTIME));
    -    GetSystemTime(&st);
    -
    -    return msecsFromDecomposed(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds) +
    -            qint64(julianDayFromDate(st.wYear, st.wMonth, st.wDay)
    -                   - julianDayFromDate(1970, 1, 1)) * Q_INT64_C(86400000);
    -}
    -
    -qint64 QDateTime::currentSecsSinceEpoch() noexcept
    -{
    -    SYSTEMTIME st;
    -    memset(&st, 0, sizeof(SYSTEMTIME));
    -    GetSystemTime(&st);
    -
    -    return st.wHour * SECS_PER_HOUR + st.wMinute * SECS_PER_MIN + st.wSecond +
    -            qint64(julianDayFromDate(st.wYear, st.wMonth, st.wDay)
    -                   - julianDayFromDate(1970, 1, 1)) * Q_INT64_C(86400);
    -}
    -
    -#elif defined(Q_OS_UNIX)
    -QDate QDate::currentDate()
    -{
    -    return QDateTime::currentDateTime().date();
    -}
    -
    -QTime QTime::currentTime()
    -{
    -    return QDateTime::currentDateTime().time();
    -}
    -
    -QDateTime QDateTime::currentDateTime()
    -{
    -    return fromMSecsSinceEpoch(currentMSecsSinceEpoch(), Qt::LocalTime);
    -}
    -
    -QDateTime QDateTime::currentDateTimeUtc()
    -{
    -    return fromMSecsSinceEpoch(currentMSecsSinceEpoch(), Qt::UTC);
    -}
    -
    -qint64 QDateTime::currentMSecsSinceEpoch() noexcept
    -{
    -    // posix compliant system
    -    // we have milliseconds
    -    struct timeval tv;
    -    gettimeofday(&tv, 0);
    -    return qint64(tv.tv_sec) * Q_INT64_C(1000) + tv.tv_usec / 1000;
    -}
    -
    -qint64 QDateTime::currentSecsSinceEpoch() noexcept
    -{
    -    struct timeval tv;
    -    gettimeofday(&tv, 0);
    -    return qint64(tv.tv_sec);
    -}
    -#else
    -#error "What system is this?"
    -#endif
    -
    -#if QT_DEPRECATED_SINCE(5, 8)
    -/*!
    -  \since 4.2
    -  \deprecated
    -
    -  Returns a datetime whose date and time are the number of \a seconds
    -  that have passed since 1970-01-01T00:00:00, Coordinated Universal
    -  Time (Qt::UTC) and converted to Qt::LocalTime.  On systems that do not
    -  support time zones, the time will be set as if local time were Qt::UTC.
    -
    -  \note This function is deprecated. Please use fromSecsSinceEpoch() in new
    -  code.
    -
    -  \sa toTime_t(), setTime_t()
    -*/
    -QDateTime QDateTime::fromTime_t(uint seconds)
    -{
    -    return fromMSecsSinceEpoch((qint64)seconds * 1000, Qt::LocalTime);
    -}
    -
    -/*!
    -  \since 5.2
    -  \deprecated
    -
    -  Returns a datetime whose date and time are the number of \a seconds
    -  that have passed since 1970-01-01T00:00:00, Coordinated Universal
    -  Time (Qt::UTC) and converted to the given \a spec.
    -
    -  If the \a spec is not Qt::OffsetFromUTC then the \a offsetSeconds will be
    -  ignored.  If the \a spec is Qt::OffsetFromUTC and the \a offsetSeconds is 0
    -  then the spec will be set to Qt::UTC, i.e. an offset of 0 seconds.
    -
    -  \note This function is deprecated. Please use fromSecsSinceEpoch() in new
    -  code.
    -
    -  \sa toTime_t(), setTime_t()
    -*/
    -QDateTime QDateTime::fromTime_t(uint seconds, Qt::TimeSpec spec, int offsetSeconds)
    -{
    -    return fromMSecsSinceEpoch((qint64)seconds * 1000, spec, offsetSeconds);
    -}
    -
    -#if QT_CONFIG(timezone)
    -/*!
    -    \since 5.2
    -    \deprecated
    -
    -    Returns a datetime whose date and time are the number of \a seconds
    -    that have passed since 1970-01-01T00:00:00, Coordinated Universal
    -    Time (Qt::UTC) and with the given \a timeZone.
    -
    -    \note This function is deprecated. Please use fromSecsSinceEpoch() in new
    -    code.
    -
    -    \sa toTime_t(), setTime_t()
    -*/
    -QDateTime QDateTime::fromTime_t(uint seconds, const QTimeZone &timeZone)
    -{
    -    return fromMSecsSinceEpoch((qint64)seconds * 1000, timeZone);
    -}
    -#endif
    -#endif // QT_DEPRECATED_SINCE(5, 8)
    -
    -/*!
    -  \since 4.7
    -
    -  Returns a datetime whose date and time are the number of milliseconds, \a msecs,
    -  that have passed since 1970-01-01T00:00:00.000, Coordinated Universal
    -  Time (Qt::UTC), and converted to Qt::LocalTime.  On systems that do not
    -  support time zones, the time will be set as if local time were Qt::UTC.
    -
    -  Note that there are possible values for \a msecs that lie outside the valid
    -  range of QDateTime, both negative and positive. The behavior of this
    -  function is undefined for those values.
    -
    -  \sa toMSecsSinceEpoch(), setMSecsSinceEpoch()
    -*/
    -QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs)
    -{
    -    return fromMSecsSinceEpoch(msecs, Qt::LocalTime);
    -}
    -
    -/*!
    -  \since 5.2
    -
    -  Returns a datetime whose date and time are the number of milliseconds \a msecs
    -  that have passed since 1970-01-01T00:00:00.000, Coordinated Universal
    -  Time (Qt::UTC) and converted to the given \a spec.
    -
    -  Note that there are possible values for \a msecs that lie outside the valid
    -  range of QDateTime, both negative and positive. The behavior of this
    -  function is undefined for those values.
    -
    -  If the \a spec is not Qt::OffsetFromUTC then the \a offsetSeconds will be
    -  ignored.  If the \a spec is Qt::OffsetFromUTC and the \a offsetSeconds is 0
    -  then the spec will be set to Qt::UTC, i.e. an offset of 0 seconds.
    -
    -  If \a spec is Qt::TimeZone then the spec will be set to Qt::LocalTime,
    -  i.e. the current system time zone.
    -
    -  \sa toMSecsSinceEpoch(), setMSecsSinceEpoch()
    -*/
    -QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs, Qt::TimeSpec spec, int offsetSeconds)
    -{
    -    QDateTime dt;
    -    QT_PREPEND_NAMESPACE(setTimeSpec(dt.d, spec, offsetSeconds));
    -    dt.setMSecsSinceEpoch(msecs);
    -    return dt;
    -}
    -
    -/*!
    -  \since 5.8
    -
    -  Returns a datetime whose date and time are the number of seconds \a secs
    -  that have passed since 1970-01-01T00:00:00.000, Coordinated Universal
    -  Time (Qt::UTC) and converted to the given \a spec.
    -
    -  Note that there are possible values for \a secs that lie outside the valid
    -  range of QDateTime, both negative and positive. The behavior of this
    -  function is undefined for those values.
    -
    -  If the \a spec is not Qt::OffsetFromUTC then the \a offsetSeconds will be
    -  ignored.  If the \a spec is Qt::OffsetFromUTC and the \a offsetSeconds is 0
    -  then the spec will be set to Qt::UTC, i.e. an offset of 0 seconds.
    -
    -  If \a spec is Qt::TimeZone then the spec will be set to Qt::LocalTime,
    -  i.e. the current system time zone.
    -
    -  \sa toSecsSinceEpoch(), setSecsSinceEpoch()
    -*/
    -QDateTime QDateTime::fromSecsSinceEpoch(qint64 secs, Qt::TimeSpec spec, int offsetSeconds)
    -{
    -    return fromMSecsSinceEpoch(secs * 1000, spec, offsetSeconds);
    -}
    -
    -#if QT_CONFIG(timezone)
    -/*!
    -    \since 5.2
    -
    -    Returns a datetime whose date and time are the number of milliseconds \a msecs
    -    that have passed since 1970-01-01T00:00:00.000, Coordinated Universal
    -    Time (Qt::UTC) and with the given \a timeZone.
    -
    -    \sa fromSecsSinceEpoch()
    -*/
    -QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs, const QTimeZone &timeZone)
    -{
    -    QDateTime dt;
    -    dt.setTimeZone(timeZone);
    -    dt.setMSecsSinceEpoch(msecs);
    -    return dt;
    -}
    -
    -/*!
    -    \since 5.8
    -
    -    Returns a datetime whose date and time are the number of seconds \a secs
    -    that have passed since 1970-01-01T00:00:00.000, Coordinated Universal
    -    Time (Qt::UTC) and with the given \a timeZone.
    -
    -    \sa fromMSecsSinceEpoch()
    -*/
    -QDateTime QDateTime::fromSecsSinceEpoch(qint64 secs, const QTimeZone &timeZone)
    -{
    -    return fromMSecsSinceEpoch(secs * 1000, timeZone);
    -}
    -#endif
    -
    -#if QT_DEPRECATED_SINCE(5, 2)
    -/*!
    -    \since 4.4
    -    \internal
    -    \obsolete
    -
    -    This method was added in 4.4 but never documented as public. It was replaced
    -    in 5.2 with public method setOffsetFromUtc() for consistency with QTimeZone.
    -
    -    This method should never be made public.
    -
    -    \sa setOffsetFromUtc()
    - */
    -void QDateTime::setUtcOffset(int seconds)
    -{
    -    setOffsetFromUtc(seconds);
    -}
    -
    -/*!
    -    \since 4.4
    -    \internal
    -    \obsolete
    -
    -    This method was added in 4.4 but never documented as public. It was replaced
    -    in 5.1 with public method offsetFromUTC() for consistency with QTimeZone.
    -
    -    This method should never be made public.
    -
    -    \sa offsetFromUTC()
    -*/
    -int QDateTime::utcOffset() const
    -{
    -    return offsetFromUtc();
    -}
    -#endif // QT_DEPRECATED_SINCE
    -
    -#if QT_CONFIG(datestring)
    -
    -/*!
    -    Returns the QDateTime represented by the \a string, using the
    -    \a format given, or an invalid datetime if this is not possible.
    -
    -    Note for Qt::TextDate: It is recommended that you use the
    -    English short month names (e.g. "Jan"). Although localized month
    -    names can also be used, they depend on the user's locale settings.
    -
    -    \sa toString(), QLocale::toDateTime()
    -*/
    -QDateTime QDateTime::fromString(const QString &string, Qt::DateFormat format)
    -{
    -    if (string.isEmpty())
    -        return QDateTime();
    -
    -    switch (format) {
    -    case Qt::SystemLocaleDate:
    -    case Qt::SystemLocaleShortDate:
    -        return QLocale::system().toDateTime(string, QLocale::ShortFormat);
    -    case Qt::SystemLocaleLongDate:
    -        return QLocale::system().toDateTime(string, QLocale::LongFormat);
    -    case Qt::LocaleDate:
    -    case Qt::DefaultLocaleShortDate:
    -        return QLocale().toDateTime(string, QLocale::ShortFormat);
    -    case Qt::DefaultLocaleLongDate:
    -        return QLocale().toDateTime(string, QLocale::LongFormat);
    -    case Qt::RFC2822Date: {
    -        const ParsedRfcDateTime rfc = rfcDateImpl(string);
    -
    -        if (!rfc.date.isValid() || !rfc.time.isValid())
    -            return QDateTime();
    -
    -        QDateTime dateTime(rfc.date, rfc.time, Qt::UTC);
    -        dateTime.setOffsetFromUtc(rfc.utcOffset);
    -        return dateTime;
    -    }
    -    case Qt::ISODate:
    -    case Qt::ISODateWithMs: {
    -        const int size = string.size();
    -        if (size < 10)
    -            return QDateTime();
    -
    -        QDate date = QDate::fromString(string.left(10), Qt::ISODate);
    -        if (!date.isValid())
    -            return QDateTime();
    -        if (size == 10)
    -            return QDateTime(date);
    -
    -        Qt::TimeSpec spec = Qt::LocalTime;
    -        QStringRef isoString(&string);
    -        isoString = isoString.mid(10); // trim "yyyy-MM-dd"
    -
    -        // Must be left with T and at least one digit for the hour:
    -        if (isoString.size() < 2
    -            || !(isoString.startsWith(QLatin1Char('T'))
    -                 // FIXME: QSql relies on QVariant::toDateTime() accepting a space here:
    -                 || isoString.startsWith(QLatin1Char(' ')))) {
    -            return QDateTime();
    -        }
    -        isoString = isoString.mid(1); // trim 'T' (or space)
    -
    -        int offset = 0;
    -        // Check end of string for Time Zone definition, either Z for UTC or [+-]HH:mm for Offset
    -        if (isoString.endsWith(QLatin1Char('Z'))) {
    -            spec = Qt::UTC;
    -            isoString.chop(1); // trim 'Z'
    -        } else {
    -            // the loop below is faster but functionally equal to:
    -            // const int signIndex = isoString.indexOf(QRegExp(QStringLiteral("[+-]")));
    -            int signIndex = isoString.size() - 1;
    -            Q_ASSERT(signIndex >= 0);
    -            bool found = false;
    -            {
    -                const QChar plus = QLatin1Char('+');
    -                const QChar minus = QLatin1Char('-');
    -                do {
    -                    QChar character(isoString.at(signIndex));
    -                    found = character == plus || character == minus;
    -                } while (!found && --signIndex >= 0);
    -            }
    -
    -            if (found) {
    -                bool ok;
    -                offset = fromOffsetString(isoString.mid(signIndex), &ok);
    -                if (!ok)
    -                    return QDateTime();
    -                isoString = isoString.left(signIndex);
    -                spec = Qt::OffsetFromUTC;
    -            }
    -        }
    -
    -        // Might be end of day (24:00, including variants), which QTime considers invalid.
    -        // ISO 8601 (section 4.2.3) says that 24:00 is equivalent to 00:00 the next day.
    -        bool isMidnight24 = false;
    -        QTime time = fromIsoTimeString(isoString, format, &isMidnight24);
    -        if (!time.isValid())
    -            return QDateTime();
    -        if (isMidnight24)
    -            date = date.addDays(1);
    -        return QDateTime(date, time, spec, offset);
    -    }
    -#if QT_CONFIG(textdate)
    -    case Qt::TextDate: {
    -        QVector parts = string.splitRef(QLatin1Char(' '), QString::SkipEmptyParts);
    -
    -        if ((parts.count() < 5) || (parts.count() > 6))
    -            return QDateTime();
    -
    -        // Accept "Sun Dec 1 13:02:00 1974" and "Sun 1. Dec 13:02:00 1974"
    -        int month = 0;
    -        int day = 0;
    -        bool ok = false;
    -
    -        // First try month then day
    -        month = fromShortMonthName(parts.at(1));
    -        if (month)
    -            day = parts.at(2).toInt();
    -
    -        // If failed try day then month
    -        if (!month || !day) {
    -            month = fromShortMonthName(parts.at(2));
    -            if (month) {
    -                QStringRef dayStr = parts.at(1);
    -                if (dayStr.endsWith(QLatin1Char('.'))) {
    -                    dayStr = dayStr.left(dayStr.size() - 1);
    -                    day = dayStr.toInt();
    -                }
    -            }
    -        }
    -
    -        // If both failed, give up
    -        if (!month || !day)
    -            return QDateTime();
    -
    -        // Year can be before or after time, "Sun Dec 1 1974 13:02:00" or "Sun Dec 1 13:02:00 1974"
    -        // Guess which by looking for ':' in the time
    -        int year = 0;
    -        int yearPart = 0;
    -        int timePart = 0;
    -        if (parts.at(3).contains(QLatin1Char(':'))) {
    -            yearPart = 4;
    -            timePart = 3;
    -        } else if (parts.at(4).contains(QLatin1Char(':'))) {
    -            yearPart = 3;
    -            timePart = 4;
    -        } else {
    -            return QDateTime();
    -        }
    -
    -        year = parts.at(yearPart).toInt(&ok);
    -        if (!ok)
    -            return QDateTime();
    -
    -        QDate date(year, month, day);
    -        if (!date.isValid())
    -            return QDateTime();
    -
    -        QVector timeParts = parts.at(timePart).split(QLatin1Char(':'));
    -        if (timeParts.count() < 2 || timeParts.count() > 3)
    -            return QDateTime();
    -
    -        int hour = timeParts.at(0).toInt(&ok);
    -        if (!ok)
    -            return QDateTime();
    -
    -        int minute = timeParts.at(1).toInt(&ok);
    -        if (!ok)
    -            return QDateTime();
    -
    -        int second = 0;
    -        int millisecond = 0;
    -        if (timeParts.count() > 2) {
    -            const QVector secondParts = timeParts.at(2).split(QLatin1Char('.'));
    -            if (secondParts.size() > 2) {
    -                return QDateTime();
    -            }
    -
    -            second = secondParts.first().toInt(&ok);
    -            if (!ok) {
    -                return QDateTime();
    -            }
    -
    -            if (secondParts.size() > 1) {
    -                millisecond = secondParts.last().toInt(&ok);
    -                if (!ok) {
    -                    return QDateTime();
    -                }
    -            }
    -        }
    -
    -        QTime time(hour, minute, second, millisecond);
    -        if (!time.isValid())
    -            return QDateTime();
    -
    -        if (parts.count() == 5)
    -            return QDateTime(date, time, Qt::LocalTime);
    -
    -        QStringRef tz = parts.at(5);
    -        if (!tz.startsWith(QLatin1String("GMT"), Qt::CaseInsensitive))
    -            return QDateTime();
    -        tz = tz.mid(3);
    -        if (!tz.isEmpty()) {
    -            int offset = fromOffsetString(tz, &ok);
    -            if (!ok)
    -                return QDateTime();
    -            return QDateTime(date, time, Qt::OffsetFromUTC, offset);
    -        } else {
    -            return QDateTime(date, time, Qt::UTC);
    -        }
    -    }
    -#endif // textdate
    -    }
    -
    -    return QDateTime();
    -}
    -
    -/*!
    -    Returns the QDateTime represented by the \a string, using the \a
    -    format given, or an invalid datetime if the string cannot be parsed.
    -
    -    These expressions may be used for the date part of the format string:
    -
    -    \table
    -    \header \li Expression \li Output
    -    \row \li d \li the day as number without a leading zero (1 to 31)
    -    \row \li dd \li the day as number with a leading zero (01 to 31)
    -    \row \li ddd
    -            \li the abbreviated localized day name (e.g. 'Mon' to 'Sun').
    -            Uses QDate::shortDayName().
    -    \row \li dddd
    -            \li the long localized day name (e.g. 'Monday' to 'Sunday').
    -            Uses QDate::longDayName().
    -    \row \li M \li the month as number without a leading zero (1-12)
    -    \row \li MM \li the month as number with a leading zero (01-12)
    -    \row \li MMM
    -            \li the abbreviated localized month name (e.g. 'Jan' to 'Dec').
    -            Uses QDate::shortMonthName().
    -    \row \li MMMM
    -            \li the long localized month name (e.g. 'January' to 'December').
    -            Uses QDate::longMonthName().
    -    \row \li yy \li the year as two digit number (00-99)
    -    \row \li yyyy \li the year as four digit number
    -    \endtable
    -
    -    \note Unlike the other version of this function, day and month names must
    -    be given in the user's local language. It is only possible to use the English
    -    names if the user's language is English.
    -
    -    These expressions may be used for the time part of the format string:
    -
    -    \table
    -    \header \li Expression \li Output
    -    \row \li h
    -            \li the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
    -    \row \li hh
    -            \li the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
    -    \row \li H
    -            \li the hour without a leading zero (0 to 23, even with AM/PM display)
    -    \row \li HH
    -            \li the hour with a leading zero (00 to 23, even with AM/PM display)
    -    \row \li m \li the minute without a leading zero (0 to 59)
    -    \row \li mm \li the minute with a leading zero (00 to 59)
    -    \row \li s \li the whole second without a leading zero (0 to 59)
    -    \row \li ss \li the whole second with a leading zero where applicable (00 to 59)
    -    \row \li z \li the fractional part of the second, to go after a decimal
    -                point, without trailing zeroes (0 to 999).  Thus "\c{s.z}"
    -                reports the seconds to full available (millisecond) precision
    -                without trailing zeroes.
    -    \row \li zzz \li the fractional part of the second, to millisecond
    -                precision, including trailing zeroes where applicable (000 to 999).
    -    \row \li AP or A
    -         \li interpret as an AM/PM time. \e AP must be either "AM" or "PM".
    -    \row \li ap or a
    -         \li Interpret as an AM/PM time. \e ap must be either "am" or "pm".
    -    \endtable
    -
    -    All other input characters will be treated as text. Any sequence
    -    of characters that are enclosed in single quotes will also be
    -    treated as text and not be used as an expression.
    -
    -    \snippet code/src_corelib_tools_qdatetime.cpp 12
    -
    -    If the format is not satisfied, an invalid QDateTime is returned.
    -    The expressions that don't have leading zeroes (d, M, h, m, s, z) will be
    -    greedy. This means that they will use two digits even if this will
    -    put them outside the range and/or leave too few digits for other
    -    sections.
    -
    -    \snippet code/src_corelib_tools_qdatetime.cpp 13
    -
    -    This could have meant 1 January 00:30.00 but the M will grab
    -    two digits.
    -
    -    Incorrectly specified fields of the \a string will cause an invalid
    -    QDateTime to be returned. For example, consider the following code,
    -    where the two digit year 12 is read as 1912 (see the table below for all
    -    field defaults); the resulting datetime is invalid because 23 April 1912
    -    was a Tuesday, not a Monday:
    -
    -    \snippet code/src_corelib_tools_qdatetime.cpp 20
    -
    -    The correct code is:
    -
    -    \snippet code/src_corelib_tools_qdatetime.cpp 21
    -
    -    For any field that is not represented in the format, the following
    -    defaults are used:
    -
    -    \table
    -    \header \li Field  \li Default value
    -    \row    \li Year   \li 1900
    -    \row    \li Month  \li 1 (January)
    -    \row    \li Day    \li 1
    -    \row    \li Hour   \li 0
    -    \row    \li Minute \li 0
    -    \row    \li Second \li 0
    -    \endtable
    -
    -    For example:
    -
    -    \snippet code/src_corelib_tools_qdatetime.cpp 14
    -
    -    \sa toString(), QDate::fromString(), QTime::fromString(),
    -    QLocale::toDateTime()
    -*/
    -
    -QDateTime QDateTime::fromString(const QString &string, const QString &format)
    -{
    -#if QT_CONFIG(datetimeparser)
    -    QTime time;
    -    QDate date;
    -
    -    QDateTimeParser dt(QVariant::DateTime, QDateTimeParser::FromString);
    -    // dt.setDefaultLocale(QLocale::c()); ### Qt 6
    -    if (dt.parseFormat(format) && dt.fromString(string, &date, &time))
    -        return QDateTime(date, time);
    -#else
    -    Q_UNUSED(string);
    -    Q_UNUSED(format);
    -#endif
    -    return QDateTime();
    -}
    -
    -#endif // datestring
    -/*!
    -    \fn QDateTime QDateTime::toLocalTime() const
    -
    -    Returns a datetime containing the date and time information in
    -    this datetime, but specified using the Qt::LocalTime definition.
    -
    -    Example:
    -
    -    \snippet code/src_corelib_tools_qdatetime.cpp 17
    -
    -    \sa toTimeSpec()
    -*/
    -
    -/*!
    -    \fn QDateTime QDateTime::toUTC() const
    -
    -    Returns a datetime containing the date and time information in
    -    this datetime, but specified using the Qt::UTC definition.
    -
    -    Example:
    -
    -    \snippet code/src_corelib_tools_qdatetime.cpp 18
    -
    -    \sa toTimeSpec()
    -*/
    -
    -/*****************************************************************************
    -  Date/time stream functions
    - *****************************************************************************/
    -
    -#ifndef QT_NO_DATASTREAM
    -/*!
    -    \relates QDate
    -
    -    Writes the \a date to stream \a out.
    -
    -    \sa {Serializing Qt Data Types}
    -*/
    -
    -QDataStream &operator<<(QDataStream &out, const QDate &date)
    -{
    -    if (out.version() < QDataStream::Qt_5_0)
    -        return out << quint32(date.jd);
    -    else
    -        return out << qint64(date.jd);
    -}
    -
    -/*!
    -    \relates QDate
    -
    -    Reads a date from stream \a in into the \a date.
    -
    -    \sa {Serializing Qt Data Types}
    -*/
    -
    -QDataStream &operator>>(QDataStream &in, QDate &date)
    -{
    -    if (in.version() < QDataStream::Qt_5_0) {
    -        quint32 jd;
    -        in >> jd;
    -        // Older versions consider 0 an invalid jd.
    -        date.jd = (jd != 0 ? jd : QDate::nullJd());
    -    } else {
    -        qint64 jd;
    -        in >> jd;
    -        date.jd = jd;
    -    }
    -
    -    return in;
    -}
    -
    -/*!
    -    \relates QTime
    -
    -    Writes \a time to stream \a out.
    -
    -    \sa {Serializing Qt Data Types}
    -*/
    -
    -QDataStream &operator<<(QDataStream &out, const QTime &time)
    -{
    -    if (out.version() >= QDataStream::Qt_4_0) {
    -        return out << quint32(time.mds);
    -    } else {
    -        // Qt3 had no support for reading -1, QTime() was valid and serialized as 0
    -        return out << quint32(time.isNull() ? 0 : time.mds);
    -    }
    -}
    -
    -/*!
    -    \relates QTime
    -
    -    Reads a time from stream \a in into the given \a time.
    -
    -    \sa {Serializing Qt Data Types}
    -*/
    -
    -QDataStream &operator>>(QDataStream &in, QTime &time)
    -{
    -    quint32 ds;
    -    in >> ds;
    -    if (in.version() >= QDataStream::Qt_4_0) {
    -        time.mds = int(ds);
    -    } else {
    -        // Qt3 would write 0 for a null time
    -        time.mds = (ds == 0) ? QTime::NullTime : int(ds);
    -    }
    -    return in;
    -}
    -
    -/*!
    -    \relates QDateTime
    -
    -    Writes \a dateTime to the \a out stream.
    -
    -    \sa {Serializing Qt Data Types}
    -*/
    -QDataStream &operator<<(QDataStream &out, const QDateTime &dateTime)
    -{
    -    QPair dateAndTime;
    -
    -    if (out.version() >= QDataStream::Qt_5_2) {
    -
    -        // In 5.2 we switched to using Qt::TimeSpec and added offset support
    -        dateAndTime = getDateTime(dateTime.d);
    -        out << dateAndTime << qint8(dateTime.timeSpec());
    -        if (dateTime.timeSpec() == Qt::OffsetFromUTC)
    -            out << qint32(dateTime.offsetFromUtc());
    -#if QT_CONFIG(timezone)
    -        else if (dateTime.timeSpec() == Qt::TimeZone)
    -            out << dateTime.timeZone();
    -#endif // timezone
    -
    -    } else if (out.version() == QDataStream::Qt_5_0) {
    -
    -        // In Qt 5.0 we incorrectly serialised all datetimes as UTC.
    -        // This approach is wrong and should not be used again; it breaks
    -        // the guarantee that a deserialised local datetime is the same time
    -        // of day, regardless of which timezone it was serialised in.
    -        dateAndTime = getDateTime((dateTime.isValid() ? dateTime.toUTC() : dateTime).d);
    -        out << dateAndTime << qint8(dateTime.timeSpec());
    -
    -    } else if (out.version() >= QDataStream::Qt_4_0) {
    -
    -        // From 4.0 to 5.1 (except 5.0) we used QDateTimePrivate::Spec
    -        dateAndTime = getDateTime(dateTime.d);
    -        out << dateAndTime;
    -        switch (dateTime.timeSpec()) {
    -        case Qt::UTC:
    -            out << (qint8)QDateTimePrivate::UTC;
    -            break;
    -        case Qt::OffsetFromUTC:
    -            out << (qint8)QDateTimePrivate::OffsetFromUTC;
    -            break;
    -        case Qt::TimeZone:
    -            out << (qint8)QDateTimePrivate::TimeZone;
    -            break;
    -        case Qt::LocalTime:
    -            out << (qint8)QDateTimePrivate::LocalUnknown;
    -            break;
    -        }
    -
    -    } else { // version < QDataStream::Qt_4_0
    -
    -        // Before 4.0 there was no TimeSpec, only Qt::LocalTime was supported
    -        dateAndTime = getDateTime(dateTime.d);
    -        out << dateAndTime;
    -
    -    }
    -
    -    return out;
    -}
    -
    -/*!
    -    \relates QDateTime
    -
    -    Reads a datetime from the stream \a in into \a dateTime.
    -
    -    \sa {Serializing Qt Data Types}
    -*/
    -
    -QDataStream &operator>>(QDataStream &in, QDateTime &dateTime)
    -{
    -    QDate dt;
    -    QTime tm;
    -    qint8 ts = 0;
    -    Qt::TimeSpec spec = Qt::LocalTime;
    -    qint32 offset = 0;
    -#if QT_CONFIG(timezone)
    -    QTimeZone tz;
    -#endif // timezone
    -
    -    if (in.version() >= QDataStream::Qt_5_2) {
    -
    -        // In 5.2 we switched to using Qt::TimeSpec and added offset support
    -        in >> dt >> tm >> ts;
    -        spec = static_cast(ts);
    -        if (spec == Qt::OffsetFromUTC) {
    -            in >> offset;
    -            dateTime = QDateTime(dt, tm, spec, offset);
    -#if QT_CONFIG(timezone)
    -        } else if (spec == Qt::TimeZone) {
    -            in >> tz;
    -            dateTime = QDateTime(dt, tm, tz);
    -#endif // timezone
    -        } else {
    -            dateTime = QDateTime(dt, tm, spec);
    -        }
    -
    -    } else if (in.version() == QDataStream::Qt_5_0) {
    -
    -        // In Qt 5.0 we incorrectly serialised all datetimes as UTC
    -        in >> dt >> tm >> ts;
    -        spec = static_cast(ts);
    -        dateTime = QDateTime(dt, tm, Qt::UTC);
    -        dateTime = dateTime.toTimeSpec(spec);
    -
    -    } else if (in.version() >= QDataStream::Qt_4_0) {
    -
    -        // From 4.0 to 5.1 (except 5.0) we used QDateTimePrivate::Spec
    -        in >> dt >> tm >> ts;
    -        switch ((QDateTimePrivate::Spec)ts) {
    -        case QDateTimePrivate::UTC:
    -            spec = Qt::UTC;
    -            break;
    -        case QDateTimePrivate::OffsetFromUTC:
    -            spec = Qt::OffsetFromUTC;
    -            break;
    -        case QDateTimePrivate::TimeZone:
    -            spec = Qt::TimeZone;
    -#if QT_CONFIG(timezone)
    -            // FIXME: need to use a different constructor !
    -#endif
    -            break;
    -        case QDateTimePrivate::LocalUnknown:
    -        case QDateTimePrivate::LocalStandard:
    -        case QDateTimePrivate::LocalDST:
    -            spec = Qt::LocalTime;
    -            break;
    -        }
    -        dateTime = QDateTime(dt, tm, spec, offset);
    -
    -    } else { // version < QDataStream::Qt_4_0
    -
    -        // Before 4.0 there was no TimeSpec, only Qt::LocalTime was supported
    -        in >> dt >> tm;
    -        dateTime = QDateTime(dt, tm, spec, offset);
    -
    -    }
    -
    -    return in;
    -}
    -#endif // QT_NO_DATASTREAM
    -
    -/*****************************************************************************
    -  Date / Time Debug Streams
    -*****************************************************************************/
    -
    -#if !defined(QT_NO_DEBUG_STREAM) && QT_CONFIG(datestring)
    -QDebug operator<<(QDebug dbg, const QDate &date)
    -{
    -    QDebugStateSaver saver(dbg);
    -    dbg.nospace() << "QDate(";
    -    if (date.isValid())
    -        dbg.nospace() << date.toString(Qt::ISODate);
    -    else
    -        dbg.nospace() << "Invalid";
    -    dbg.nospace() << ')';
    -    return dbg;
    -}
    -
    -QDebug operator<<(QDebug dbg, const QTime &time)
    -{
    -    QDebugStateSaver saver(dbg);
    -    dbg.nospace() << "QTime(";
    -    if (time.isValid())
    -        dbg.nospace() << time.toString(QStringViewLiteral("HH:mm:ss.zzz"));
    -    else
    -        dbg.nospace() << "Invalid";
    -    dbg.nospace() << ')';
    -    return dbg;
    -}
    -
    -QDebug operator<<(QDebug dbg, const QDateTime &date)
    -{
    -    QDebugStateSaver saver(dbg);
    -    dbg.nospace() << "QDateTime(";
    -    if (date.isValid()) {
    -        const Qt::TimeSpec ts = date.timeSpec();
    -        dbg.noquote() << date.toString(QStringViewLiteral("yyyy-MM-dd HH:mm:ss.zzz t"))
    -                      << ' ' << ts;
    -        switch (ts) {
    -        case Qt::UTC:
    -            break;
    -        case Qt::OffsetFromUTC:
    -            dbg.space() << date.offsetFromUtc() << 's';
    -            break;
    -        case Qt::TimeZone:
    -#if QT_CONFIG(timezone)
    -            dbg.space() << date.timeZone().id();
    -#endif // timezone
    -            break;
    -        case Qt::LocalTime:
    -            break;
    -        }
    -    } else {
    -        dbg.nospace() << "Invalid";
    -    }
    -    return dbg.nospace() << ')';
    -}
    -#endif // debug_stream && datestring
    -
    -/*! \fn uint qHash(const QDateTime &key, uint seed = 0)
    -    \relates QHash
    -    \since 5.0
    -
    -    Returns the hash value for the \a key, using \a seed to seed the calculation.
    -*/
    -uint qHash(const QDateTime &key, uint seed)
    -{
    -    // Use to toMSecsSinceEpoch instead of individual qHash functions for
    -    // QDate/QTime/spec/offset because QDateTime::operator== converts both arguments
    -    // to the same timezone. If we don't, qHash would return different hashes for
    -    // two QDateTimes that are equivalent once converted to the same timezone.
    -    return qHash(key.toMSecsSinceEpoch(), seed);
    -}
    -
    -/*! \fn uint qHash(const QDate &key, uint seed = 0)
    -    \relates QHash
    -    \since 5.0
    -
    -    Returns the hash value for the \a key, using \a seed to seed the calculation.
    -*/
    -uint qHash(const QDate &key, uint seed) noexcept
    -{
    -    return qHash(key.toJulianDay(), seed);
    -}
    -
    -/*! \fn uint qHash(const QTime &key, uint seed = 0)
    -    \relates QHash
    -    \since 5.0
    -
    -    Returns the hash value for the \a key, using \a seed to seed the calculation.
    -*/
    -uint qHash(const QTime &key, uint seed) noexcept
    -{
    -    return qHash(key.msecsSinceStartOfDay(), seed);
    -}
    -
    -QT_END_NAMESPACE
    diff --git a/src/corelib/tools/qdatetime.h b/src/corelib/tools/qdatetime.h
    deleted file mode 100644
    index 3e3b953b52..0000000000
    --- a/src/corelib/tools/qdatetime.h
    +++ /dev/null
    @@ -1,426 +0,0 @@
    -/****************************************************************************
    -**
    -** Copyright (C) 2019 The Qt Company Ltd.
    -** Copyright (C) 2016 Intel Corporation.
    -** Contact: https://www.qt.io/licensing/
    -**
    -** This file is part of the QtCore module of the Qt Toolkit.
    -**
    -** $QT_BEGIN_LICENSE:LGPL$
    -** Commercial License Usage
    -** Licensees holding valid commercial Qt licenses may use this file in
    -** accordance with the commercial license agreement provided with the
    -** Software or, alternatively, in accordance with the terms contained in
    -** a written agreement between you and The Qt Company. For licensing terms
    -** and conditions see https://www.qt.io/terms-conditions. For further
    -** information use the contact form at https://www.qt.io/contact-us.
    -**
    -** GNU Lesser General Public License Usage
    -** Alternatively, this file may be used under the terms of the GNU Lesser
    -** General Public License version 3 as published by the Free Software
    -** Foundation and appearing in the file LICENSE.LGPL3 included in the
    -** packaging of this file. Please review the following information to
    -** ensure the GNU Lesser General Public License version 3 requirements
    -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
    -**
    -** GNU General Public License Usage
    -** Alternatively, this file may be used under the terms of the GNU
    -** General Public License version 2.0 or (at your option) the GNU General
    -** Public license version 3 or any later version approved by the KDE Free
    -** Qt Foundation. The licenses are as published by the Free Software
    -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
    -** included in the packaging of this file. Please review the following
    -** information to ensure the GNU General Public License requirements will
    -** be met: https://www.gnu.org/licenses/gpl-2.0.html and
    -** https://www.gnu.org/licenses/gpl-3.0.html.
    -**
    -** $QT_END_LICENSE$
    -**
    -****************************************************************************/
    -
    -#ifndef QDATETIME_H
    -#define QDATETIME_H
    -
    -#include 
    -#include 
    -#include 
    -
    -#include 
    -
    -#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
    -Q_FORWARD_DECLARE_CF_TYPE(CFDate);
    -Q_FORWARD_DECLARE_OBJC_CLASS(NSDate);
    -#endif
    -
    -QT_BEGIN_NAMESPACE
    -
    -class QTimeZone;
    -class QDateTime;
    -
    -class Q_CORE_EXPORT QDate
    -{
    -public:
    -    enum MonthNameType { // ### Qt 6: remove, along with methods using it
    -        DateFormat = 0,
    -        StandaloneFormat
    -    };
    -private:
    -    explicit Q_DECL_CONSTEXPR QDate(qint64 julianDay) : jd(julianDay) {}
    -public:
    -    Q_DECL_CONSTEXPR QDate() : jd(nullJd()) {}
    -    QDate(int y, int m, int d);
    -
    -    Q_DECL_CONSTEXPR bool isNull() const { return !isValid(); }
    -    Q_DECL_CONSTEXPR bool isValid() const { return jd >= minJd() && jd <= maxJd(); }
    -
    -    int year() const;
    -    int month() const;
    -    int day() const;
    -    int dayOfWeek() const;
    -    int dayOfYear() const;
    -    int daysInMonth() const;
    -    int daysInYear() const;
    -    int weekNumber(int *yearNum = nullptr) const;
    -
    -    QDateTime startOfDay(Qt::TimeSpec spec = Qt::LocalTime, int offsetSeconds = 0) const;
    -    QDateTime endOfDay(Qt::TimeSpec spec = Qt::LocalTime, int offsetSeconds = 0) const;
    -#if QT_CONFIG(timezone)
    -    QDateTime startOfDay(const QTimeZone &zone) const;
    -    QDateTime endOfDay(const QTimeZone &zone) const;
    -#endif
    -
    -#if QT_DEPRECATED_SINCE(5, 10) && QT_CONFIG(textdate)
    -    QT_DEPRECATED_X("Use QLocale::monthName or QLocale::standaloneMonthName")
    -        static QString shortMonthName(int month, MonthNameType type = DateFormat);
    -    QT_DEPRECATED_X("Use QLocale::dayName or QLocale::standaloneDayName")
    -        static QString shortDayName(int weekday, MonthNameType type = DateFormat);
    -    QT_DEPRECATED_X("Use QLocale::monthName or QLocale::standaloneMonthName")
    -        static QString longMonthName(int month, MonthNameType type = DateFormat);
    -    QT_DEPRECATED_X("Use QLocale::dayName or QLocale::standaloneDayName")
    -        static QString longDayName(int weekday, MonthNameType type = DateFormat);
    -#endif // textdate && deprecated
    -#if QT_CONFIG(datestring)
    -    QString toString(Qt::DateFormat f = Qt::TextDate) const;
    -#if QT_STRINGVIEW_LEVEL < 2
    -    QString toString(const QString &format) const;
    -#endif
    -    QString toString(QStringView format) const;
    -#endif
    -#if QT_DEPRECATED_SINCE(5,0)
    -    QT_DEPRECATED_X("Use setDate() instead") inline bool setYMD(int y, int m, int d)
    -    { if (uint(y) <= 99) y += 1900; return setDate(y, m, d); }
    -#endif
    -
    -    bool setDate(int year, int month, int day);
    -
    -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    -    void getDate(int *year, int *month, int *day); // ### Qt 6: remove
    -#endif // < Qt 6
    -    void getDate(int *year, int *month, int *day) const;
    -
    -    Q_REQUIRED_RESULT QDate addDays(qint64 days) const;
    -    Q_REQUIRED_RESULT QDate addMonths(int months) const;
    -    Q_REQUIRED_RESULT QDate addYears(int years) const;
    -    qint64 daysTo(const QDate &) const;
    -
    -    Q_DECL_CONSTEXPR bool operator==(const QDate &other) const { return jd == other.jd; }
    -    Q_DECL_CONSTEXPR bool operator!=(const QDate &other) const { return jd != other.jd; }
    -    Q_DECL_CONSTEXPR bool operator< (const QDate &other) const { return jd <  other.jd; }
    -    Q_DECL_CONSTEXPR bool operator<=(const QDate &other) const { return jd <= other.jd; }
    -    Q_DECL_CONSTEXPR bool operator> (const QDate &other) const { return jd >  other.jd; }
    -    Q_DECL_CONSTEXPR bool operator>=(const QDate &other) const { return jd >= other.jd; }
    -
    -    static QDate currentDate();
    -#if QT_CONFIG(datestring)
    -    static QDate fromString(const QString &s, Qt::DateFormat f = Qt::TextDate);
    -    static QDate fromString(const QString &s, const QString &format);
    -#endif
    -    static bool isValid(int y, int m, int d);
    -    static bool isLeapYear(int year);
    -
    -    static Q_DECL_CONSTEXPR inline QDate fromJulianDay(qint64 jd_)
    -    { return jd_ >= minJd() && jd_ <= maxJd() ? QDate(jd_) : QDate() ; }
    -    Q_DECL_CONSTEXPR inline qint64 toJulianDay() const { return jd; }
    -
    -private:
    -    // using extra parentheses around min to avoid expanding it if it is a macro
    -    static Q_DECL_CONSTEXPR inline qint64 nullJd() { return (std::numeric_limits::min)(); }
    -    static Q_DECL_CONSTEXPR inline qint64 minJd() { return Q_INT64_C(-784350574879); }
    -    static Q_DECL_CONSTEXPR inline qint64 maxJd() { return Q_INT64_C( 784354017364); }
    -
    -    qint64 jd;
    -
    -    friend class QDateTime;
    -    friend class QDateTimePrivate;
    -#ifndef QT_NO_DATASTREAM
    -    friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QDate &);
    -    friend Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QDate &);
    -#endif
    -};
    -Q_DECLARE_TYPEINFO(QDate, Q_MOVABLE_TYPE);
    -
    -class Q_CORE_EXPORT QTime
    -{
    -    explicit Q_DECL_CONSTEXPR QTime(int ms) : mds(ms)
    -    {}
    -public:
    -    Q_DECL_CONSTEXPR QTime(): mds(NullTime)
    -    {}
    -    QTime(int h, int m, int s = 0, int ms = 0);
    -
    -    Q_DECL_CONSTEXPR bool isNull() const { return mds == NullTime; }
    -    bool isValid() const;
    -
    -    int hour() const;
    -    int minute() const;
    -    int second() const;
    -    int msec() const;
    -#if QT_CONFIG(datestring)
    -    QString toString(Qt::DateFormat f = Qt::TextDate) const;
    -#if QT_STRINGVIEW_LEVEL < 2
    -    QString toString(const QString &format) const;
    -#endif
    -    QString toString(QStringView format) const;
    -#endif
    -    bool setHMS(int h, int m, int s, int ms = 0);
    -
    -    Q_REQUIRED_RESULT QTime addSecs(int secs) const;
    -    int secsTo(const QTime &) const;
    -    Q_REQUIRED_RESULT QTime addMSecs(int ms) const;
    -    int msecsTo(const QTime &) const;
    -
    -    Q_DECL_CONSTEXPR bool operator==(const QTime &other) const { return mds == other.mds; }
    -    Q_DECL_CONSTEXPR bool operator!=(const QTime &other) const { return mds != other.mds; }
    -    Q_DECL_CONSTEXPR bool operator< (const QTime &other) const { return mds <  other.mds; }
    -    Q_DECL_CONSTEXPR bool operator<=(const QTime &other) const { return mds <= other.mds; }
    -    Q_DECL_CONSTEXPR bool operator> (const QTime &other) const { return mds >  other.mds; }
    -    Q_DECL_CONSTEXPR bool operator>=(const QTime &other) const { return mds >= other.mds; }
    -
    -    static Q_DECL_CONSTEXPR inline QTime fromMSecsSinceStartOfDay(int msecs) { return QTime(msecs); }
    -    Q_DECL_CONSTEXPR inline int msecsSinceStartOfDay() const { return mds == NullTime ? 0 : mds; }
    -
    -    static QTime currentTime();
    -#if QT_CONFIG(datestring)
    -    static QTime fromString(const QString &s, Qt::DateFormat f = Qt::TextDate);
    -    static QTime fromString(const QString &s, const QString &format);
    -#endif
    -    static bool isValid(int h, int m, int s, int ms = 0);
    -
    -#if QT_DEPRECATED_SINCE(5, 14) // ### Qt 6: remove
    -    QT_DEPRECATED_X("Use QElapsedTimer instead") void start();
    -    QT_DEPRECATED_X("Use QElapsedTimer instead") int restart();
    -    QT_DEPRECATED_X("Use QElapsedTimer instead") int elapsed() const;
    -#endif
    -private:
    -    enum TimeFlag { NullTime = -1 };
    -    Q_DECL_CONSTEXPR inline int ds() const { return mds == -1 ? 0 : mds; }
    -    int mds;
    -
    -    friend class QDateTime;
    -    friend class QDateTimePrivate;
    -#ifndef QT_NO_DATASTREAM
    -    friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QTime &);
    -    friend Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QTime &);
    -#endif
    -};
    -Q_DECLARE_TYPEINFO(QTime, Q_MOVABLE_TYPE);
    -
    -class QDateTimePrivate;
    -
    -class Q_CORE_EXPORT QDateTime
    -{
    -    // ### Qt 6: revisit the optimization
    -    struct ShortData {
    -#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
    -        quintptr status : 8;
    -#endif
    -        // note: this is only 24 bits on 32-bit systems...
    -        qintptr msecs : sizeof(void *) * 8 - 8;
    -
    -#if Q_BYTE_ORDER == Q_BIG_ENDIAN
    -        quintptr status : 8;
    -#endif
    -    };
    -
    -    union Data {
    -        enum {
    -            // To be of any use, we need at least 60 years around 1970, which
    -            // is 1,893,456,000,000 ms. That requires 41 bits to store, plus
    -            // the sign bit. With the status byte, the minimum size is 50 bits.
    -            CanBeSmall = sizeof(ShortData) * 8 > 50
    -        };
    -
    -        Data();
    -        Data(Qt::TimeSpec);
    -        Data(const Data &other);
    -        Data(Data &&other);
    -        Data &operator=(const Data &other);
    -        ~Data();
    -
    -        bool isShort() const;
    -        void detach();
    -
    -        const QDateTimePrivate *operator->() const;
    -        QDateTimePrivate *operator->();
    -
    -        QDateTimePrivate *d;
    -        ShortData data;
    -    };
    -
    -public:
    -    QDateTime() noexcept(Data::CanBeSmall);
    -    explicit QDateTime(const QDate &);
    -    QDateTime(const QDate &, const QTime &, Qt::TimeSpec spec = Qt::LocalTime);
    -    // ### Qt 6: Merge with above with default offsetSeconds = 0
    -    QDateTime(const QDate &date, const QTime &time, Qt::TimeSpec spec, int offsetSeconds);
    -#if QT_CONFIG(timezone)
    -    QDateTime(const QDate &date, const QTime &time, const QTimeZone &timeZone);
    -#endif // timezone
    -    QDateTime(const QDateTime &other) noexcept;
    -    QDateTime(QDateTime &&other) noexcept;
    -    ~QDateTime();
    -
    -    QDateTime &operator=(QDateTime &&other) noexcept { swap(other); return *this; }
    -    QDateTime &operator=(const QDateTime &other) noexcept;
    -
    -    void swap(QDateTime &other) noexcept { qSwap(d.d, other.d.d); }
    -
    -    bool isNull() const;
    -    bool isValid() const;
    -
    -    QDate date() const;
    -    QTime time() const;
    -    Qt::TimeSpec timeSpec() const;
    -    int offsetFromUtc() const;
    -#if QT_CONFIG(timezone)
    -    QTimeZone timeZone() const;
    -#endif // timezone
    -    QString timeZoneAbbreviation() const;
    -    bool isDaylightTime() const;
    -
    -    qint64 toMSecsSinceEpoch() const;
    -    qint64 toSecsSinceEpoch() const;
    -
    -    void setDate(const QDate &date);
    -    void setTime(const QTime &time);
    -    void setTimeSpec(Qt::TimeSpec spec);
    -    void setOffsetFromUtc(int offsetSeconds);
    -#if QT_CONFIG(timezone)
    -    void setTimeZone(const QTimeZone &toZone);
    -#endif // timezone
    -    void setMSecsSinceEpoch(qint64 msecs);
    -    void setSecsSinceEpoch(qint64 secs);
    -
    -#if QT_CONFIG(datestring)
    -    QString toString(Qt::DateFormat f = Qt::TextDate) const;
    -#if QT_STRINGVIEW_LEVEL < 2
    -    QString toString(const QString &format) const;
    -#endif
    -    QString toString(QStringView format) const;
    -#endif
    -    Q_REQUIRED_RESULT QDateTime addDays(qint64 days) const;
    -    Q_REQUIRED_RESULT QDateTime addMonths(int months) const;
    -    Q_REQUIRED_RESULT QDateTime addYears(int years) const;
    -    Q_REQUIRED_RESULT QDateTime addSecs(qint64 secs) const;
    -    Q_REQUIRED_RESULT QDateTime addMSecs(qint64 msecs) const;
    -
    -    QDateTime toTimeSpec(Qt::TimeSpec spec) const;
    -    inline QDateTime toLocalTime() const { return toTimeSpec(Qt::LocalTime); }
    -    inline QDateTime toUTC() const { return toTimeSpec(Qt::UTC); }
    -    QDateTime toOffsetFromUtc(int offsetSeconds) const;
    -#if QT_CONFIG(timezone)
    -    QDateTime toTimeZone(const QTimeZone &toZone) const;
    -#endif // timezone
    -
    -    qint64 daysTo(const QDateTime &) const;
    -    qint64 secsTo(const QDateTime &) const;
    -    qint64 msecsTo(const QDateTime &) const;
    -
    -    bool operator==(const QDateTime &other) const;
    -    inline bool operator!=(const QDateTime &other) const { return !(*this == other); }
    -    bool operator<(const QDateTime &other) const;
    -    inline bool operator<=(const QDateTime &other) const { return !(other < *this); }
    -    inline bool operator>(const QDateTime &other) const { return other < *this; }
    -    inline bool operator>=(const QDateTime &other) const { return !(*this < other); }
    -
    -#if QT_DEPRECATED_SINCE(5, 2) // ### Qt 6: remove
    -    QT_DEPRECATED_X("Use setOffsetFromUtc() instead") void setUtcOffset(int seconds);
    -    QT_DEPRECATED_X("Use offsetFromUtc() instead") int utcOffset() const;
    -#endif // QT_DEPRECATED_SINCE
    -
    -    static QDateTime currentDateTime();
    -    static QDateTime currentDateTimeUtc();
    -#if QT_CONFIG(datestring)
    -    static QDateTime fromString(const QString &s, Qt::DateFormat f = Qt::TextDate);
    -    static QDateTime fromString(const QString &s, const QString &format);
    -#endif
    -
    -#if QT_DEPRECATED_SINCE(5, 8)
    -    uint toTime_t() const;
    -    void setTime_t(uint secsSince1Jan1970UTC);
    -    static QDateTime fromTime_t(uint secsSince1Jan1970UTC);
    -    static QDateTime fromTime_t(uint secsSince1Jan1970UTC, Qt::TimeSpec spec,
    -                                int offsetFromUtc = 0);
    -    static QDateTime fromTime_t(uint secsSince1Jan1970UTC, const QTimeZone &timeZone);
    -#endif
    -
    -    static QDateTime fromMSecsSinceEpoch(qint64 msecs);
    -    // ### Qt 6: Merge with above with default spec = Qt::LocalTime
    -    static QDateTime fromMSecsSinceEpoch(qint64 msecs, Qt::TimeSpec spec, int offsetFromUtc = 0);
    -    static QDateTime fromSecsSinceEpoch(qint64 secs, Qt::TimeSpec spe = Qt::LocalTime, int offsetFromUtc = 0);
    -
    -#if QT_CONFIG(timezone)
    -    static QDateTime fromMSecsSinceEpoch(qint64 msecs, const QTimeZone &timeZone);
    -    static QDateTime fromSecsSinceEpoch(qint64 secs, const QTimeZone &timeZone);
    -#endif
    -
    -    static qint64 currentMSecsSinceEpoch() noexcept;
    -    static qint64 currentSecsSinceEpoch() noexcept;
    -
    -#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
    -    static QDateTime fromCFDate(CFDateRef date);
    -    CFDateRef toCFDate() const Q_DECL_CF_RETURNS_RETAINED;
    -    static QDateTime fromNSDate(const NSDate *date);
    -    NSDate *toNSDate() const Q_DECL_NS_RETURNS_AUTORELEASED;
    -#endif
    -
    -private:
    -    friend class QDateTimePrivate;
    -
    -    Data d;
    -
    -#ifndef QT_NO_DATASTREAM
    -    friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QDateTime &);
    -    friend Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QDateTime &);
    -#endif
    -
    -#if !defined(QT_NO_DEBUG_STREAM) && QT_CONFIG(datestring)
    -    friend Q_CORE_EXPORT QDebug operator<<(QDebug, const QDateTime &);
    -#endif
    -};
    -Q_DECLARE_SHARED(QDateTime)
    -
    -#ifndef QT_NO_DATASTREAM
    -Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QDate &);
    -Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QDate &);
    -Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QTime &);
    -Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QTime &);
    -Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QDateTime &);
    -Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QDateTime &);
    -#endif // QT_NO_DATASTREAM
    -
    -#if !defined(QT_NO_DEBUG_STREAM) && QT_CONFIG(datestring)
    -Q_CORE_EXPORT QDebug operator<<(QDebug, const QDate &);
    -Q_CORE_EXPORT QDebug operator<<(QDebug, const QTime &);
    -Q_CORE_EXPORT QDebug operator<<(QDebug, const QDateTime &);
    -#endif
    -
    -// QDateTime is not noexcept for now -- to be revised once
    -// timezone and calendaring support is added
    -Q_CORE_EXPORT uint qHash(const QDateTime &key, uint seed = 0);
    -Q_CORE_EXPORT uint qHash(const QDate &key, uint seed = 0) noexcept;
    -Q_CORE_EXPORT uint qHash(const QTime &key, uint seed = 0) noexcept;
    -
    -QT_END_NAMESPACE
    -
    -#endif // QDATETIME_H
    diff --git a/src/corelib/tools/qdatetime_p.h b/src/corelib/tools/qdatetime_p.h
    deleted file mode 100644
    index 6018f8f7b0..0000000000
    --- a/src/corelib/tools/qdatetime_p.h
    +++ /dev/null
    @@ -1,151 +0,0 @@
    -/****************************************************************************
    -**
    -** Copyright (C) 2016 The Qt Company Ltd.
    -** Copyright (C) 2016 Intel Corporation.
    -** Contact: https://www.qt.io/licensing/
    -**
    -** This file is part of the QtCore module of the Qt Toolkit.
    -**
    -** $QT_BEGIN_LICENSE:LGPL$
    -** Commercial License Usage
    -** Licensees holding valid commercial Qt licenses may use this file in
    -** accordance with the commercial license agreement provided with the
    -** Software or, alternatively, in accordance with the terms contained in
    -** a written agreement between you and The Qt Company. For licensing terms
    -** and conditions see https://www.qt.io/terms-conditions. For further
    -** information use the contact form at https://www.qt.io/contact-us.
    -**
    -** GNU Lesser General Public License Usage
    -** Alternatively, this file may be used under the terms of the GNU Lesser
    -** General Public License version 3 as published by the Free Software
    -** Foundation and appearing in the file LICENSE.LGPL3 included in the
    -** packaging of this file. Please review the following information to
    -** ensure the GNU Lesser General Public License version 3 requirements
    -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
    -**
    -** GNU General Public License Usage
    -** Alternatively, this file may be used under the terms of the GNU
    -** General Public License version 2.0 or (at your option) the GNU General
    -** Public license version 3 or any later version approved by the KDE Free
    -** Qt Foundation. The licenses are as published by the Free Software
    -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
    -** included in the packaging of this file. Please review the following
    -** information to ensure the GNU General Public License requirements will
    -** be met: https://www.gnu.org/licenses/gpl-2.0.html and
    -** https://www.gnu.org/licenses/gpl-3.0.html.
    -**
    -** $QT_END_LICENSE$
    -**
    -****************************************************************************/
    -
    -#ifndef QDATETIME_P_H
    -#define QDATETIME_P_H
    -
    -//
    -//  W A R N I N G
    -//  -------------
    -//
    -// This file is not part of the Qt API.  It exists purely as an
    -// implementation detail.  This header file may change from version to
    -// version without notice, or even be removed.
    -//
    -// We mean it.
    -//
    -
    -#include 
    -#include "qplatformdefs.h"
    -#include "QtCore/qatomic.h"
    -#include "QtCore/qdatetime.h"
    -#include "QtCore/qpair.h"
    -
    -#if QT_CONFIG(timezone)
    -#include "qtimezone.h"
    -#endif
    -
    -QT_BEGIN_NAMESPACE
    -
    -class QDateTimePrivate
    -{
    -public:
    -    // forward the declarations from QDateTime (this makes them public)
    -    typedef QDateTime::ShortData QDateTimeShortData;
    -    typedef QDateTime::Data QDateTimeData;
    -
    -    // Never change or delete this enum, it is required for backwards compatible
    -    // serialization of QDateTime before 5.2, so is essentially public API
    -    enum Spec {
    -        LocalUnknown = -1,
    -        LocalStandard = 0,
    -        LocalDST = 1,
    -        UTC = 2,
    -        OffsetFromUTC = 3,
    -        TimeZone = 4
    -    };
    -
    -    // Daylight Time Status
    -    enum DaylightStatus {
    -        UnknownDaylightTime = -1,
    -        StandardTime = 0,
    -        DaylightTime = 1
    -    };
    -
    -    // Status of date/time
    -    enum StatusFlag {
    -        ShortData           = 0x01,
    -
    -        ValidDate           = 0x02,
    -        ValidTime           = 0x04,
    -        ValidDateTime       = 0x08,
    -
    -        TimeSpecMask        = 0x30,
    -
    -        SetToStandardTime   = 0x40,
    -        SetToDaylightTime   = 0x80
    -    };
    -    Q_DECLARE_FLAGS(StatusFlags, StatusFlag)
    -
    -    enum {
    -        TimeSpecShift = 4,
    -        ValidityMask        = ValidDate | ValidTime | ValidDateTime,
    -        DaylightMask        = SetToStandardTime | SetToDaylightTime
    -    };
    -
    -    QDateTimePrivate() : m_msecs(0),
    -                         m_status(StatusFlag(Qt::LocalTime << TimeSpecShift)),
    -                         m_offsetFromUtc(0),
    -                         ref(0)
    -    {
    -    }
    -
    -    static QDateTime::Data create(const QDate &toDate, const QTime &toTime, Qt::TimeSpec toSpec,
    -                                  int offsetSeconds);
    -
    -#if QT_CONFIG(timezone)
    -    static QDateTime::Data create(const QDate &toDate, const QTime &toTime, const QTimeZone & timeZone);
    -#endif // timezone
    -
    -    qint64 m_msecs;
    -    StatusFlags m_status;
    -    int m_offsetFromUtc;
    -    mutable QAtomicInt ref;
    -#if QT_CONFIG(timezone)
    -    QTimeZone m_timeZone;
    -#endif // timezone
    -
    -#if QT_CONFIG(timezone)
    -    static qint64 zoneMSecsToEpochMSecs(qint64 msecs, const QTimeZone &zone,
    -                                        DaylightStatus hint = UnknownDaylightTime,
    -                                        QDate *localDate = nullptr, QTime *localTime = nullptr);
    -
    -    // Inlined for its one caller in qdatetime.cpp
    -    inline void setUtcOffsetByTZ(qint64 atMSecsSinceEpoch);
    -#endif // timezone
    -
    -    // ### Qt 5.14: expose publicly in QDateTime
    -    // The first and last years of which QDateTime can represent some part:
    -    enum class YearRange : qint32 { First = -292275056,  Last = +292278994 };
    -};
    -
    -QT_END_NAMESPACE
    -
    -#endif // QDATETIME_P_H
    diff --git a/src/corelib/tools/qdatetimeparser.cpp b/src/corelib/tools/qdatetimeparser.cpp
    deleted file mode 100644
    index 728b066db1..0000000000
    --- a/src/corelib/tools/qdatetimeparser.cpp
    +++ /dev/null
    @@ -1,2047 +0,0 @@
    -/****************************************************************************
    -**
    -** Copyright (C) 2016 The Qt Company Ltd.
    -** Contact: https://www.qt.io/licensing/
    -**
    -** This file is part of the QtCore module of the Qt Toolkit.
    -**
    -** $QT_BEGIN_LICENSE:LGPL$
    -** Commercial License Usage
    -** Licensees holding valid commercial Qt licenses may use this file in
    -** accordance with the commercial license agreement provided with the
    -** Software or, alternatively, in accordance with the terms contained in
    -** a written agreement between you and The Qt Company. For licensing terms
    -** and conditions see https://www.qt.io/terms-conditions. For further
    -** information use the contact form at https://www.qt.io/contact-us.
    -**
    -** GNU Lesser General Public License Usage
    -** Alternatively, this file may be used under the terms of the GNU Lesser
    -** General Public License version 3 as published by the Free Software
    -** Foundation and appearing in the file LICENSE.LGPL3 included in the
    -** packaging of this file. Please review the following information to
    -** ensure the GNU Lesser General Public License version 3 requirements
    -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
    -**
    -** GNU General Public License Usage
    -** Alternatively, this file may be used under the terms of the GNU
    -** General Public License version 2.0 or (at your option) the GNU General
    -** Public license version 3 or any later version approved by the KDE Free
    -** Qt Foundation. The licenses are as published by the Free Software
    -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
    -** included in the packaging of this file. Please review the following
    -** information to ensure the GNU General Public License requirements will
    -** be met: https://www.gnu.org/licenses/gpl-2.0.html and
    -** https://www.gnu.org/licenses/gpl-3.0.html.
    -**
    -** $QT_END_LICENSE$
    -**
    -****************************************************************************/
    -
    -#include "qplatformdefs.h"
    -#include "private/qdatetimeparser_p.h"
    -
    -#include "qdatastream.h"
    -#include "qset.h"
    -#include "qlocale.h"
    -#include "qdatetime.h"
    -#if QT_CONFIG(timezone)
    -#include "qtimezone.h"
    -#endif
    -#include "qdebug.h"
    -
    -//#define QDATETIMEPARSER_DEBUG
    -#if defined (QDATETIMEPARSER_DEBUG) && !defined(QT_NO_DEBUG_STREAM)
    -#  define QDTPDEBUG qDebug()
    -#  define QDTPDEBUGN qDebug
    -#else
    -#  define QDTPDEBUG if (false) qDebug()
    -#  define QDTPDEBUGN if (false) qDebug
    -#endif
    -
    -QT_BEGIN_NAMESPACE
    -
    -QDateTimeParser::~QDateTimeParser()
    -{
    -}
    -
    -/*!
    -  \internal
    -  Gets the digit from a datetime. E.g.
    -
    -  QDateTime var(QDate(2004, 02, 02));
    -  int digit = getDigit(var, Year);
    -  // digit = 2004
    -*/
    -
    -int QDateTimeParser::getDigit(const QDateTime &t, int index) const
    -{
    -    if (index < 0 || index >= sectionNodes.size()) {
    -#if QT_CONFIG(datestring)
    -        qWarning("QDateTimeParser::getDigit() Internal error (%ls %d)",
    -                 qUtf16Printable(t.toString()), index);
    -#else
    -        qWarning("QDateTimeParser::getDigit() Internal error (%d)", index);
    -#endif
    -        return -1;
    -    }
    -    const SectionNode &node = sectionNodes.at(index);
    -    switch (node.type) {
    -    case TimeZoneSection: return t.offsetFromUtc();
    -    case Hour24Section: case Hour12Section: return t.time().hour();
    -    case MinuteSection: return t.time().minute();
    -    case SecondSection: return t.time().second();
    -    case MSecSection: return t.time().msec();
    -    case YearSection2Digits:
    -    case YearSection: return t.date().year();
    -    case MonthSection: return t.date().month();
    -    case DaySection: return t.date().day();
    -    case DayOfWeekSectionShort:
    -    case DayOfWeekSectionLong: return t.date().day();
    -    case AmPmSection: return t.time().hour() > 11 ? 1 : 0;
    -
    -    default: break;
    -    }
    -
    -#if QT_CONFIG(datestring)
    -    qWarning("QDateTimeParser::getDigit() Internal error 2 (%ls %d)",
    -             qUtf16Printable(t.toString()), index);
    -#else
    -    qWarning("QDateTimeParser::getDigit() Internal error 2 (%d)", index);
    -#endif
    -    return -1;
    -}
    -
    -/*!
    -  \internal
    -  Sets a digit in a datetime. E.g.
    -
    -  QDateTime var(QDate(2004, 02, 02));
    -  int digit = getDigit(var, Year);
    -  // digit = 2004
    -  setDigit(&var, Year, 2005);
    -  digit = getDigit(var, Year);
    -  // digit = 2005
    -*/
    -
    -bool QDateTimeParser::setDigit(QDateTime &v, int index, int newVal) const
    -{
    -    if (index < 0 || index >= sectionNodes.size()) {
    -#if QT_CONFIG(datestring)
    -        qWarning("QDateTimeParser::setDigit() Internal error (%ls %d %d)",
    -                 qUtf16Printable(v.toString()), index, newVal);
    -#else
    -        qWarning("QDateTimeParser::setDigit() Internal error (%d %d)", index, newVal);
    -#endif
    -        return false;
    -    }
    -    const SectionNode &node = sectionNodes.at(index);
    -
    -    const QDate date = v.date();
    -    const QTime time = v.time();
    -    int year = date.year();
    -    int month = date.month();
    -    int day = date.day();
    -    int hour = time.hour();
    -    int minute = time.minute();
    -    int second = time.second();
    -    int msec = time.msec();
    -    Qt::TimeSpec tspec = v.timeSpec();
    -    // Only offset from UTC is amenable to setting an int value:
    -    int offset = tspec == Qt::OffsetFromUTC ? v.offsetFromUtc() : 0;
    -
    -    switch (node.type) {
    -    case Hour24Section: case Hour12Section: hour = newVal; break;
    -    case MinuteSection: minute = newVal; break;
    -    case SecondSection: second = newVal; break;
    -    case MSecSection: msec = newVal; break;
    -    case YearSection2Digits:
    -    case YearSection: year = newVal; break;
    -    case MonthSection: month = newVal; break;
    -    case DaySection:
    -    case DayOfWeekSectionShort:
    -    case DayOfWeekSectionLong:
    -        if (newVal > 31) {
    -            // have to keep legacy behavior. setting the
    -            // date to 32 should return false. Setting it
    -            // to 31 for february should return true
    -            return false;
    -        }
    -        day = newVal;
    -        break;
    -    case TimeZoneSection:
    -        if (newVal < absoluteMin(index) || newVal > absoluteMax(index))
    -            return false;
    -        tspec = Qt::OffsetFromUTC;
    -        offset = newVal;
    -        break;
    -    case AmPmSection: hour = (newVal == 0 ? hour % 12 : (hour % 12) + 12); break;
    -    default:
    -        qWarning("QDateTimeParser::setDigit() Internal error (%ls)",
    -                 qUtf16Printable(node.name()));
    -        break;
    -    }
    -
    -    if (!(node.type & DaySectionMask)) {
    -        if (day < cachedDay)
    -            day = cachedDay;
    -        const int max = QDate(year, month, 1).daysInMonth();
    -        if (day > max) {
    -            day = max;
    -        }
    -    }
    -
    -    const QDate newDate(year, month, day);
    -    const QTime newTime(hour, minute, second, msec);
    -    if (!newDate.isValid() || !newTime.isValid())
    -        return false;
    -
    -    // Preserve zone:
    -    v =
    -#if QT_CONFIG(timezone)
    -         tspec == Qt::TimeZone ? QDateTime(newDate, newTime, v.timeZone()) :
    -#endif
    -         QDateTime(newDate, newTime, tspec, offset);
    -    return true;
    -}
    -
    -
    -
    -/*!
    -  \internal
    -
    -  Returns the absolute maximum for a section
    -*/
    -
    -int QDateTimeParser::absoluteMax(int s, const QDateTime &cur) const
    -{
    -    const SectionNode &sn = sectionNode(s);
    -    switch (sn.type) {
    -#if QT_CONFIG(timezone)
    -    case TimeZoneSection: return QTimeZone::MaxUtcOffsetSecs;
    -#endif
    -    case Hour24Section:
    -    case Hour12Section: return 23; // this is special-cased in
    -                                   // parseSection. We want it to be
    -                                   // 23 for the stepBy case.
    -    case MinuteSection:
    -    case SecondSection: return 59;
    -    case MSecSection: return 999;
    -    case YearSection2Digits:
    -    case YearSection: return 9999; // sectionMaxSize will prevent
    -                                   // people from typing in a larger
    -                                   // number in count == 2 sections.
    -                                   // stepBy() will work on real years anyway
    -    case MonthSection: return 12;
    -    case DaySection:
    -    case DayOfWeekSectionShort:
    -    case DayOfWeekSectionLong: return cur.isValid() ? cur.date().daysInMonth() : 31;
    -    case AmPmSection: return 1;
    -    default: break;
    -    }
    -    qWarning("QDateTimeParser::absoluteMax() Internal error (%ls)",
    -             qUtf16Printable(sn.name()));
    -    return -1;
    -}
    -
    -/*!
    -  \internal
    -
    -  Returns the absolute minimum for a section
    -*/
    -
    -int QDateTimeParser::absoluteMin(int s) const
    -{
    -    const SectionNode &sn = sectionNode(s);
    -    switch (sn.type) {
    -#if QT_CONFIG(timezone)
    -    case TimeZoneSection: return QTimeZone::MinUtcOffsetSecs;
    -#endif
    -    case Hour24Section:
    -    case Hour12Section:
    -    case MinuteSection:
    -    case SecondSection:
    -    case MSecSection:
    -    case YearSection2Digits:
    -    case YearSection: return 0;
    -    case MonthSection:
    -    case DaySection:
    -    case DayOfWeekSectionShort:
    -    case DayOfWeekSectionLong: return 1;
    -    case AmPmSection: return 0;
    -    default: break;
    -    }
    -    qWarning("QDateTimeParser::absoluteMin() Internal error (%ls, %0x)",
    -             qUtf16Printable(sn.name()), sn.type);
    -    return -1;
    -}
    -
    -/*!
    -  \internal
    -
    -  Returns the sectionNode for the Section \a s.
    -*/
    -
    -const QDateTimeParser::SectionNode &QDateTimeParser::sectionNode(int sectionIndex) const
    -{
    -    if (sectionIndex < 0) {
    -        switch (sectionIndex) {
    -        case FirstSectionIndex:
    -            return first;
    -        case LastSectionIndex:
    -            return last;
    -        case NoSectionIndex:
    -            return none;
    -        }
    -    } else if (sectionIndex < sectionNodes.size()) {
    -        return sectionNodes.at(sectionIndex);
    -    }
    -
    -    qWarning("QDateTimeParser::sectionNode() Internal error (%d)",
    -             sectionIndex);
    -    return none;
    -}
    -
    -QDateTimeParser::Section QDateTimeParser::sectionType(int sectionIndex) const
    -{
    -    return sectionNode(sectionIndex).type;
    -}
    -
    -
    -/*!
    -  \internal
    -
    -  Returns the starting position for section \a s.
    -*/
    -
    -int QDateTimeParser::sectionPos(int sectionIndex) const
    -{
    -    return sectionPos(sectionNode(sectionIndex));
    -}
    -
    -int QDateTimeParser::sectionPos(const SectionNode &sn) const
    -{
    -    switch (sn.type) {
    -    case FirstSection: return 0;
    -    case LastSection: return displayText().size() - 1;
    -    default: break;
    -    }
    -    if (sn.pos == -1) {
    -        qWarning("QDateTimeParser::sectionPos Internal error (%ls)", qUtf16Printable(sn.name()));
    -        return -1;
    -    }
    -    return sn.pos;
    -}
    -
    -
    -/*!
    -  \internal
    -
    -  helper function for parseFormat. removes quotes that are
    -  not escaped and removes the escaping on those that are escaped
    -
    -*/
    -
    -static QString unquote(const QStringRef &str)
    -{
    -    const QChar quote(QLatin1Char('\''));
    -    const QChar slash(QLatin1Char('\\'));
    -    const QChar zero(QLatin1Char('0'));
    -    QString ret;
    -    QChar status(zero);
    -    const int max = str.size();
    -    for (int i=0; iappend(lastQuote >= from ? unquote(separator) : separator.toString());
    -}
    -
    -
    -bool QDateTimeParser::parseFormat(const QString &newFormat)
    -{
    -    const QLatin1Char quote('\'');
    -    const QLatin1Char slash('\\');
    -    const QLatin1Char zero('0');
    -    if (newFormat == displayFormat && !newFormat.isEmpty()) {
    -        return true;
    -    }
    -
    -    QDTPDEBUGN("parseFormat: %s", newFormat.toLatin1().constData());
    -
    -    QVector newSectionNodes;
    -    Sections newDisplay = 0;
    -    QStringList newSeparators;
    -    int i, index = 0;
    -    int add = 0;
    -    QChar status(zero);
    -    const int max = newFormat.size();
    -    int lastQuote = -1;
    -    for (i = 0; i 0 && newFormat.at(i - 1) != slash) {
    -                status = zero;
    -            }
    -        } else if (status != quote) {
    -            const char sect = newFormat.at(i).toLatin1();
    -            switch (sect) {
    -            case 'H':
    -            case 'h':
    -                if (parserType != QVariant::Date) {
    -                    const Section hour = (sect == 'h') ? Hour12Section : Hour24Section;
    -                    const SectionNode sn = { hour, i - add, countRepeat(newFormat, i, 2), 0 };
    -                    newSectionNodes.append(sn);
    -                    appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
    -                    i += sn.count - 1;
    -                    index = i + 1;
    -                    newDisplay |= hour;
    -                }
    -                break;
    -            case 'm':
    -                if (parserType != QVariant::Date) {
    -                    const SectionNode sn = { MinuteSection, i - add, countRepeat(newFormat, i, 2), 0 };
    -                    newSectionNodes.append(sn);
    -                    appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
    -                    i += sn.count - 1;
    -                    index = i + 1;
    -                    newDisplay |= MinuteSection;
    -                }
    -                break;
    -            case 's':
    -                if (parserType != QVariant::Date) {
    -                    const SectionNode sn = { SecondSection, i - add, countRepeat(newFormat, i, 2), 0 };
    -                    newSectionNodes.append(sn);
    -                    appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
    -                    i += sn.count - 1;
    -                    index = i + 1;
    -                    newDisplay |= SecondSection;
    -                }
    -                break;
    -
    -            case 'z':
    -                if (parserType != QVariant::Date) {
    -                    const SectionNode sn = { MSecSection, i - add, countRepeat(newFormat, i, 3) < 3 ? 1 : 3, 0 };
    -                    newSectionNodes.append(sn);
    -                    appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
    -                    i += sn.count - 1;
    -                    index = i + 1;
    -                    newDisplay |= MSecSection;
    -                }
    -                break;
    -            case 'A':
    -            case 'a':
    -                if (parserType != QVariant::Date) {
    -                    const bool cap = (sect == 'A');
    -                    const SectionNode sn = { AmPmSection, i - add, (cap ? 1 : 0), 0 };
    -                    newSectionNodes.append(sn);
    -                    appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
    -                    newDisplay |= AmPmSection;
    -                    if (i + 1 < newFormat.size()
    -                        && newFormat.at(i+1) == (cap ? QLatin1Char('P') : QLatin1Char('p'))) {
    -                        ++i;
    -                    }
    -                    index = i + 1;
    -                }
    -                break;
    -            case 'y':
    -                if (parserType != QVariant::Time) {
    -                    const int repeat = countRepeat(newFormat, i, 4);
    -                    if (repeat >= 2) {
    -                        const SectionNode sn = { repeat == 4 ? YearSection : YearSection2Digits,
    -                                                 i - add, repeat == 4 ? 4 : 2, 0 };
    -                        newSectionNodes.append(sn);
    -                        appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
    -                        i += sn.count - 1;
    -                        index = i + 1;
    -                        newDisplay |= sn.type;
    -                    }
    -                }
    -                break;
    -            case 'M':
    -                if (parserType != QVariant::Time) {
    -                    const SectionNode sn = { MonthSection, i - add, countRepeat(newFormat, i, 4), 0 };
    -                    newSectionNodes.append(sn);
    -                    newSeparators.append(unquote(newFormat.midRef(index, i - index)));
    -                    i += sn.count - 1;
    -                    index = i + 1;
    -                    newDisplay |= MonthSection;
    -                }
    -                break;
    -            case 'd':
    -                if (parserType != QVariant::Time) {
    -                    const int repeat = countRepeat(newFormat, i, 4);
    -                    const Section sectionType = (repeat == 4 ? DayOfWeekSectionLong
    -                        : (repeat == 3 ? DayOfWeekSectionShort : DaySection));
    -                    const SectionNode sn = { sectionType, i - add, repeat, 0 };
    -                    newSectionNodes.append(sn);
    -                    appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
    -                    i += sn.count - 1;
    -                    index = i + 1;
    -                    newDisplay |= sn.type;
    -                }
    -                break;
    -            case 't':
    -                if (parserType != QVariant::Time) {
    -                    const SectionNode sn = { TimeZoneSection, i - add, countRepeat(newFormat, i, 4), 0 };
    -                    newSectionNodes.append(sn);
    -                    appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
    -                    i += sn.count - 1;
    -                    index = i + 1;
    -                    newDisplay |= TimeZoneSection;
    -                }
    -                break;
    -            default:
    -                break;
    -            }
    -        }
    -    }
    -    if (newSectionNodes.isEmpty() && context == DateTimeEdit) {
    -        return false;
    -    }
    -
    -    if ((newDisplay & (AmPmSection|Hour12Section)) == Hour12Section) {
    -        const int count = newSectionNodes.size();
    -        for (int i = 0; i < count; ++i) {
    -            SectionNode &node = newSectionNodes[i];
    -            if (node.type == Hour12Section)
    -                node.type = Hour24Section;
    -        }
    -    }
    -
    -    if (index < max) {
    -        appendSeparator(&newSeparators, newFormat, index, index - max, lastQuote);
    -    } else {
    -        newSeparators.append(QString());
    -    }
    -
    -    displayFormat = newFormat;
    -    separators = newSeparators;
    -    sectionNodes = newSectionNodes;
    -    display = newDisplay;
    -    last.pos = -1;
    -
    -//     for (int i=0; i= sectionNodes.size()) {
    -        qWarning("QDateTimeParser::sectionSize Internal error (%d)", sectionIndex);
    -        return -1;
    -    }
    -
    -    if (sectionIndex == sectionNodes.size() - 1) {
    -        // In some cases there is a difference between displayText() and text.
    -        // e.g. when text is 2000/01/31 and displayText() is "2000/2/31" - text
    -        // is the previous value and displayText() is the new value.
    -        // The size difference is always due to leading zeroes.
    -        int sizeAdjustment = 0;
    -        const int displayTextSize = displayText().size();
    -        if (displayTextSize != text.size()) {
    -            // Any zeroes added before this section will affect our size.
    -            int preceedingZeroesAdded = 0;
    -            if (sectionNodes.size() > 1 && context == DateTimeEdit) {
    -                const auto begin = sectionNodes.cbegin();
    -                const auto end = begin + sectionIndex;
    -                for (auto sectionIt = begin; sectionIt != end; ++sectionIt)
    -                    preceedingZeroesAdded += sectionIt->zeroesAdded;
    -            }
    -            sizeAdjustment = preceedingZeroesAdded;
    -        }
    -
    -        return displayTextSize + sizeAdjustment - sectionPos(sectionIndex) - separators.last().size();
    -    } else {
    -        return sectionPos(sectionIndex + 1) - sectionPos(sectionIndex)
    -            - separators.at(sectionIndex + 1).size();
    -    }
    -}
    -
    -
    -int QDateTimeParser::sectionMaxSize(Section s, int count) const
    -{
    -#if QT_CONFIG(textdate)
    -    int mcount = 12;
    -#endif
    -
    -    switch (s) {
    -    case FirstSection:
    -    case NoSection:
    -    case LastSection: return 0;
    -
    -    case AmPmSection: {
    -        const int lowerMax = qMin(getAmPmText(AmText, LowerCase).size(),
    -                                  getAmPmText(PmText, LowerCase).size());
    -        const int upperMax = qMin(getAmPmText(AmText, UpperCase).size(),
    -                                  getAmPmText(PmText, UpperCase).size());
    -        return qMin(4, qMin(lowerMax, upperMax));
    -    }
    -
    -    case Hour24Section:
    -    case Hour12Section:
    -    case MinuteSection:
    -    case SecondSection:
    -    case DaySection: return 2;
    -    case DayOfWeekSectionShort:
    -    case DayOfWeekSectionLong:
    -#if !QT_CONFIG(textdate)
    -        return 2;
    -#else
    -        mcount = 7;
    -        Q_FALLTHROUGH();
    -#endif
    -    case MonthSection:
    -#if !QT_CONFIG(textdate)
    -        return 2;
    -#else
    -        if (count <= 2)
    -            return 2;
    -
    -        {
    -            int ret = 0;
    -            const QLocale l = locale();
    -            const QLocale::FormatType format = count == 4 ? QLocale::LongFormat : QLocale::ShortFormat;
    -            for (int i=1; i<=mcount; ++i) {
    -                const QString str = (s == MonthSection
    -                                     ? l.monthName(i, format)
    -                                     : l.dayName(i, format));
    -                ret = qMax(str.size(), ret);
    -            }
    -            return ret;
    -        }
    -#endif
    -    case MSecSection: return 3;
    -    case YearSection: return 4;
    -    case YearSection2Digits: return 2;
    -        // Arbitrarily many tokens (each up to 14 bytes) joined with / separators:
    -    case TimeZoneSection: return std::numeric_limits::max();
    -
    -    case CalendarPopupSection:
    -    case Internal:
    -    case TimeSectionMask:
    -    case DateSectionMask:
    -    case HourSectionMask:
    -    case YearSectionMask:
    -    case DayOfWeekSectionMask:
    -    case DaySectionMask:
    -        qWarning("QDateTimeParser::sectionMaxSize: Invalid section %s",
    -                 SectionNode::name(s).toLatin1().constData());
    -
    -    case NoSectionIndex:
    -    case FirstSectionIndex:
    -    case LastSectionIndex:
    -    case CalendarPopupIndex:
    -        // these cases can't happen
    -        break;
    -    }
    -    return -1;
    -}
    -
    -
    -int QDateTimeParser::sectionMaxSize(int index) const
    -{
    -    const SectionNode &sn = sectionNode(index);
    -    return sectionMaxSize(sn.type, sn.count);
    -}
    -
    -/*!
    -  \internal
    -
    -  Returns the text of section \a s. This function operates on the
    -  arg text rather than edit->text().
    -*/
    -
    -
    -QString QDateTimeParser::sectionText(const QString &text, int sectionIndex, int index) const
    -{
    -    const SectionNode &sn = sectionNode(sectionIndex);
    -    switch (sn.type) {
    -    case NoSectionIndex:
    -    case FirstSectionIndex:
    -    case LastSectionIndex:
    -        return QString();
    -    default: break;
    -    }
    -
    -    return text.mid(index, sectionSize(sectionIndex));
    -}
    -
    -QString QDateTimeParser::sectionText(int sectionIndex) const
    -{
    -    const SectionNode &sn = sectionNode(sectionIndex);
    -    return sectionText(displayText(), sectionIndex, sn.pos);
    -}
    -
    -
    -#if QT_CONFIG(datestring)
    -
    -QDateTimeParser::ParsedSection
    -QDateTimeParser::parseSection(const QDateTime ¤tValue, int sectionIndex,
    -                              int offset, QString *text) const
    -{
    -    ParsedSection result; // initially Invalid
    -    const SectionNode &sn = sectionNode(sectionIndex);
    -    if (sn.type & Internal) {
    -        qWarning("QDateTimeParser::parseSection Internal error (%ls %d)",
    -                 qUtf16Printable(sn.name()), sectionIndex);
    -        return result;
    -    }
    -
    -    const int sectionmaxsize = sectionMaxSize(sectionIndex);
    -    QStringRef sectionTextRef = text->midRef(offset, sectionmaxsize);
    -
    -    QDTPDEBUG << "sectionValue for" << sn.name()
    -              << "with text" << *text << "and (at" << offset
    -              << ") st:" << sectionTextRef;
    -
    -    switch (sn.type) {
    -    case AmPmSection: {
    -        QString sectiontext = sectionTextRef.toString();
    -        int used;
    -        const int ampm = findAmPm(sectiontext, sectionIndex, &used);
    -        switch (ampm) {
    -        case AM: // sectiontext == AM
    -        case PM: // sectiontext == PM
    -            result = ParsedSection(Acceptable, ampm, used);
    -            break;
    -        case PossibleAM: // sectiontext => AM
    -        case PossiblePM: // sectiontext => PM
    -            result = ParsedSection(Intermediate, ampm - 2, used);
    -            break;
    -        case PossibleBoth: // sectiontext => AM|PM
    -            result = ParsedSection(Intermediate, 0, used);
    -            break;
    -        case Neither:
    -            QDTPDEBUG << "invalid because findAmPm(" << sectiontext << ") returned -1";
    -            break;
    -        default:
    -            QDTPDEBUGN("This should never happen (findAmPm returned %d)", ampm);
    -            break;
    -        }
    -        if (result.state != Invalid)
    -            text->replace(offset, used, sectiontext.constData(), used);
    -        break; }
    -    case TimeZoneSection:
    -#if QT_CONFIG(timezone)
    -        result = findTimeZone(sectionTextRef, currentValue,
    -                              absoluteMax(sectionIndex),
    -                              absoluteMin(sectionIndex));
    -#endif
    -        break;
    -    case MonthSection:
    -    case DayOfWeekSectionShort:
    -    case DayOfWeekSectionLong:
    -        if (sn.count >= 3) {
    -            QString sectiontext = sectionTextRef.toString();
    -            int num = 0, used = 0;
    -            if (sn.type == MonthSection) {
    -                const QDate minDate = getMinimum().date();
    -                const int min = (currentValue.date().year() == minDate.year())
    -                    ? minDate.month() : 1;
    -                num = findMonth(sectiontext.toLower(), min, sectionIndex, §iontext, &used);
    -            } else {
    -                num = findDay(sectiontext.toLower(), 1, sectionIndex, §iontext, &used);
    -            }
    -
    -            result = ParsedSection(Intermediate, num, used);
    -            if (num != -1) {
    -                text->replace(offset, used, sectiontext.constData(), used);
    -                if (used == sectiontext.size())
    -                    result = ParsedSection(Acceptable, num, used);
    -            }
    -            break;
    -        }
    -        Q_FALLTHROUGH();
    -        // All numeric:
    -    case DaySection:
    -    case YearSection:
    -    case YearSection2Digits:
    -    case Hour12Section:
    -    case Hour24Section:
    -    case MinuteSection:
    -    case SecondSection:
    -    case MSecSection: {
    -        int sectiontextSize = sectionTextRef.size();
    -        if (sectiontextSize == 0) {
    -            result = ParsedSection(Intermediate);
    -        } else {
    -            for (int i = 0; i < sectiontextSize; ++i) {
    -                if (sectionTextRef.at(i).isSpace())
    -                    sectiontextSize = i; // which exits the loop
    -            }
    -
    -            const int absMax = absoluteMax(sectionIndex);
    -            QLocale loc;
    -            bool ok = true;
    -            int last = -1, used = -1;
    -
    -            Q_ASSERT(sectiontextSize <= sectionmaxsize);
    -            QStringRef digitsStr = sectionTextRef.left(sectiontextSize);
    -            for (int digits = sectiontextSize; digits >= 1; --digits) {
    -                digitsStr.truncate(digits);
    -                int tmp = (int)loc.toUInt(digitsStr, &ok);
    -                if (ok && sn.type == Hour12Section) {
    -                    if (tmp > 12) {
    -                        tmp = -1;
    -                        ok = false;
    -                    } else if (tmp == 12) {
    -                        tmp = 0;
    -                    }
    -                }
    -                if (ok && tmp <= absMax) {
    -                    QDTPDEBUG << sectionTextRef.left(digits) << tmp << digits;
    -                    last = tmp;
    -                    used = digits;
    -                    break;
    -                }
    -            }
    -
    -            if (last == -1) {
    -                QChar first(sectionTextRef.at(0));
    -                if (separators.at(sectionIndex + 1).startsWith(first))
    -                    result = ParsedSection(Intermediate, 0, used);
    -                else
    -                    QDTPDEBUG << "invalid because" << sectionTextRef << "can't become a uint" << last << ok;
    -            } else {
    -                const FieldInfo fi = fieldInfo(sectionIndex);
    -                const bool unfilled = used < sectionmaxsize;
    -                if (unfilled && fi & Fraction) { // typing 2 in a zzz field should be .200, not .002
    -                    for (int i = used; i < sectionmaxsize; ++i)
    -                        last *= 10;
    -                }
    -                // Even those *= 10s can't take last above absMax:
    -                Q_ASSERT(last <= absMax);
    -                const int absMin = absoluteMin(sectionIndex);
    -                if (last < absMin) {
    -                    if (unfilled)
    -                        result = ParsedSection(Intermediate, last, used);
    -                    else
    -                        QDTPDEBUG << "invalid because" << last << "is less than absoluteMin" << absMin;
    -                } else if (unfilled && (fi & (FixedWidth|Numeric)) == (FixedWidth|Numeric)) {
    -                    if (skipToNextSection(sectionIndex, currentValue, digitsStr)) {
    -                        const int missingZeroes = sectionmaxsize - digitsStr.size();
    -                        result = ParsedSection(Acceptable, last, sectionmaxsize, missingZeroes);
    -                        text->insert(offset, QString(missingZeroes, QLatin1Char('0')));
    -                        ++(const_cast(this)->sectionNodes[sectionIndex].zeroesAdded);
    -                    } else {
    -                        result = ParsedSection(Intermediate, last, used);;
    -                    }
    -                } else {
    -                    result = ParsedSection(Acceptable, last, used);
    -                }
    -            }
    -        }
    -        break; }
    -    default:
    -        qWarning("QDateTimeParser::parseSection Internal error (%ls %d)",
    -                 qUtf16Printable(sn.name()), sectionIndex);
    -        return result;
    -    }
    -    Q_ASSERT(result.state != Invalid || result.value == -1);
    -
    -    return result;
    -}
    -
    -/*!
    -  \internal
    -
    -  Returns a date consistent with the given data on parts specified by known,
    -  while staying as close to the given data as it can.  Returns an invalid date
    -  when on valid date is consistent with the data.
    -*/
    -
    -static QDate actualDate(QDateTimeParser::Sections known, int year, int year2digits,
    -                        int month, int day, int dayofweek)
    -{
    -    QDate actual(year, month, day);
    -    if (actual.isValid() && year % 100 == year2digits && actual.dayOfWeek() == dayofweek)
    -        return actual; // The obvious candidate is fine :-)
    -
    -    if (dayofweek < 1 || dayofweek > 7) // Invalid: ignore
    -        known &= ~QDateTimeParser::DayOfWeekSectionMask;
    -
    -    // Assuming year > 0 ...
    -    if (year % 100 != year2digits) {
    -        if (known & QDateTimeParser::YearSection2Digits) {
    -            // Over-ride year, even if specified:
    -            year += year2digits - year % 100;
    -            known &= ~QDateTimeParser::YearSection;
    -        } else {
    -            year2digits = year % 100;
    -        }
    -    }
    -    Q_ASSERT(year % 100 == year2digits);
    -
    -    if (month < 1) { // If invalid, clip to nearest valid and ignore in known.
    -        month = 1;
    -        known &= ~QDateTimeParser::MonthSection;
    -    } else if (month > 12) {
    -        month = 12;
    -        known &= ~QDateTimeParser::MonthSection;
    -    }
    -
    -    QDate first(year, month, 1);
    -    int last = known & QDateTimeParser::YearSection && known & QDateTimeParser::MonthSection
    -        ? first.daysInMonth() : 0;
    -    // If we also know day-of-week, tweak last to the last in the month that matches it:
    -    if (last && known & QDateTimeParser::DayOfWeekSectionMask) {
    -        int diff = (dayofweek - first.dayOfWeek() - last) % 7;
    -        Q_ASSERT(diff <= 0); // C++11 specifies (-ve) % (+ve) to be <= 0.
    -        last += diff;
    -    }
    -    if (day < 1) {
    -        if (known & QDateTimeParser::DayOfWeekSectionMask && last) {
    -            day = 1 + dayofweek - first.dayOfWeek();
    -            if (day < 1)
    -                day += 7;
    -        } else {
    -            day = 1;
    -        }
    -        known &= ~QDateTimeParser::DaySection;
    -    } else if (day > 31) {
    -        day = last;
    -        known &= ~QDateTimeParser::DaySection;
    -    } else if (last && day > last && (known & QDateTimeParser::DaySection) == 0) {
    -        day = last;
    -    }
    -
    -    actual = QDate(year, month, day);
    -    if (!actual.isValid() // We can't do better than we have, in this case
    -        || (known & QDateTimeParser::DaySection
    -            && known & QDateTimeParser::MonthSection
    -            && known & QDateTimeParser::YearSection) // ditto
    -        || actual.dayOfWeek() == dayofweek // Good enough, use it.
    -        || (known & QDateTimeParser::DayOfWeekSectionMask) == 0) { // No contradiction, use it.
    -        return actual;
    -    }
    -
    -    /*
    -      Now it gets trickier.
    -
    -      We have some inconsistency in our data; we've been told day of week, but
    -      it doesn't fit with our year, month and day.  At least one of these is
    -      unknown, though: so we can fix day of week by tweaking it.
    -    */
    -
    -    if ((known & QDateTimeParser::DaySection) == 0) {
    -        // Relatively easy to fix.
    -        day += dayofweek - actual.dayOfWeek();
    -        if (day < 1)
    -            day += 7;
    -        else if (day > actual.daysInMonth())
    -            day -= 7;
    -        actual = QDate(year, month, day);
    -        return actual;
    -    }
    -
    -    if ((known & QDateTimeParser::MonthSection) == 0) {
    -        /*
    -          Try possible month-offsets, m, preferring small; at least one (present
    -          month doesn't work) and at most 11 (max month, 12, minus min, 1); try
    -          in both directions, ignoring any offset that takes us out of range.
    -        */
    -        for (int m = 1; m < 12; m++) {
    -            if (m < month) {
    -                actual = QDate(year, month - m, day);
    -                if (actual.dayOfWeek() == dayofweek)
    -                    return actual;
    -            }
    -            if (m + month <= 12) {
    -                actual = QDate(year, month + m, day);
    -                if (actual.dayOfWeek() == dayofweek)
    -                    return actual;
    -            }
    -        }
    -        // Should only get here in corner cases; e.g. day == 31
    -        actual = QDate(year, month, day); // Restore from trial values.
    -    }
    -
    -    if ((known & QDateTimeParser::YearSection) == 0) {
    -        if (known & QDateTimeParser::YearSection2Digits) {
    -            /*
    -              Two-digit year and month are specified; choice of century can only
    -              fix this if diff is in one of {1, 2, 5} or {2, 4, 6}; but not if
    -              diff is in the other.  It's also only reasonable to consider
    -              adjacent century, e.g. if year thinks it's 2012 and two-digit year
    -              is '97, it makes sense to consider 1997.  If either adjacent
    -              century does work, the other won't.
    -            */
    -            actual = QDate(year + 100, month, day);
    -            if (actual.dayOfWeek() == dayofweek)
    -                return actual;
    -            actual = QDate(year - 100, month, day);
    -            if (actual.dayOfWeek() == dayofweek)
    -                return actual;
    -        } else {
    -            // Offset by 7 is usually enough, but rare cases may need more:
    -            for (int y = 1; y < 12; y++) {
    -                actual = QDate(year - y, month, day);
    -                if (actual.dayOfWeek() == dayofweek)
    -                    return actual;
    -                actual = QDate(year + y, month, day);
    -                if (actual.dayOfWeek() == dayofweek)
    -                    return actual;
    -            }
    -        }
    -        actual = QDate(year, month, day); // Restore from trial values.
    -    }
    -
    -    return actual; // It'll just have to do :-(
    -}
    -
    -/*!
    -  \internal
    -*/
    -
    -static QTime actualTime(QDateTimeParser::Sections known,
    -                        int hour, int hour12, int ampm,
    -                        int minute, int second, int msec)
    -{
    -    // If we have no conflict, or don't know enough to diagonose one, use this:
    -    QTime actual(hour, minute, second, msec);
    -    if (hour12 < 0 || hour12 > 12) { // ignore bogus value
    -        known &= ~QDateTimeParser::Hour12Section;
    -        hour12 = hour % 12;
    -    }
    -
    -    if (ampm == -1 || (known & QDateTimeParser::AmPmSection) == 0) {
    -        if ((known & QDateTimeParser::Hour12Section) == 0 || hour % 12 == hour12)
    -            return actual;
    -
    -        if ((known & QDateTimeParser::Hour24Section) == 0)
    -            hour = hour12 + (hour > 12 ? 12 : 0);
    -    } else {
    -        Q_ASSERT(ampm == 0 || ampm == 1);
    -        if (hour - hour12 == ampm * 12)
    -            return actual;
    -
    -        if ((known & QDateTimeParser::Hour24Section) == 0
    -            && known & QDateTimeParser::Hour12Section) {
    -            hour = hour12 + ampm * 12;
    -        }
    -    }
    -    actual = QTime(hour, minute, second, msec);
    -    return actual;
    -}
    -
    -/*!
    -  \internal
    -*/
    -QDateTimeParser::StateNode
    -QDateTimeParser::scanString(const QDateTime &defaultValue,
    -                            bool fixup, QString *input) const
    -{
    -    State state = Acceptable;
    -    bool conflicts = false;
    -    const int sectionNodesCount = sectionNodes.size();
    -    int padding = 0;
    -    int pos = 0;
    -    int year, month, day;
    -    const QDate defaultDate = defaultValue.date();
    -    const QTime defaultTime = defaultValue.time();
    -    defaultDate.getDate(&year, &month, &day);
    -    int year2digits = year % 100;
    -    int hour = defaultTime.hour();
    -    int hour12 = -1;
    -    int minute = defaultTime.minute();
    -    int second = defaultTime.second();
    -    int msec = defaultTime.msec();
    -    int dayofweek = defaultDate.dayOfWeek();
    -    Qt::TimeSpec tspec = defaultValue.timeSpec();
    -    int zoneOffset = 0; // In seconds; local - UTC
    -#if QT_CONFIG(timezone)
    -    QTimeZone timeZone;
    -#endif
    -    switch (tspec) {
    -    case Qt::OffsetFromUTC: // timeZone is ignored
    -        zoneOffset = defaultValue.offsetFromUtc();
    -        break;
    -#if QT_CONFIG(timezone)
    -    case Qt::TimeZone:
    -        timeZone = defaultValue.timeZone();
    -        if (timeZone.isValid())
    -            zoneOffset = timeZone.offsetFromUtc(defaultValue);
    -        // else: is there anything we can do about this ?
    -        break;
    -#endif
    -    default: // zoneOffset and timeZone are ignored
    -        break;
    -    }
    -
    -    int ampm = -1;
    -    Sections isSet = NoSection;
    -
    -    for (int index = 0; index < sectionNodesCount; ++index) {
    -        Q_ASSERT(state != Invalid);
    -        const QString &separator = separators.at(index);
    -        if (input->midRef(pos, separator.size()) != separator) {
    -            QDTPDEBUG << "invalid because" << input->midRef(pos, separator.size())
    -                      << "!=" << separator
    -                      << index << pos << currentSectionIndex;
    -            return StateNode();
    -        }
    -        pos += separator.size();
    -        sectionNodes[index].pos = pos;
    -        int *current = 0;
    -        const SectionNode sn = sectionNodes.at(index);
    -        ParsedSection sect;
    -
    -        {
    -            const QDate date = actualDate(isSet, year, year2digits, month, day, dayofweek);
    -            const QTime time = actualTime(isSet, hour, hour12, ampm, minute, second, msec);
    -            sect = parseSection(
    -#if QT_CONFIG(timezone)
    -                                tspec == Qt::TimeZone ? QDateTime(date, time, timeZone) :
    -#endif
    -                                QDateTime(date, time, tspec, zoneOffset),
    -                                index, pos, input);
    -        }
    -
    -        QDTPDEBUG << "sectionValue" << sn.name() << *input
    -                  << "pos" << pos << "used" << sect.used << stateName(sect.state);
    -
    -        padding += sect.zeroes;
    -        if (fixup && sect.state == Intermediate && sect.used < sn.count) {
    -            const FieldInfo fi = fieldInfo(index);
    -            if ((fi & (Numeric|FixedWidth)) == (Numeric|FixedWidth)) {
    -                const QString newText = QString::fromLatin1("%1").arg(sect.value, sn.count, 10, QLatin1Char('0'));
    -                input->replace(pos, sect.used, newText);
    -                sect.used = sn.count;
    -            }
    -        }
    -
    -        state = qMin(state, sect.state);
    -        // QDateTimeEdit can fix Intermediate and zeroes, but input needing that didn't match format:
    -        if (state == Invalid || (context == FromString && (state == Intermediate || sect.zeroes)))
    -            return StateNode();
    -
    -        switch (sn.type) {
    -        case TimeZoneSection:
    -            current = &zoneOffset;
    -            if (sect.used > 0) {
    -#if QT_CONFIG(timezone) // Synchronize with what findTimeZone() found:
    -                QStringRef zoneName = input->midRef(pos, sect.used);
    -                Q_ASSERT(!zoneName.isEmpty()); // sect.used > 0
    -                const QByteArray latinZone(zoneName == QLatin1String("Z")
    -                                           ? QByteArray("UTC") : zoneName.toLatin1());
    -                timeZone = QTimeZone(latinZone);
    -                tspec = timeZone.isValid()
    -                    ? (QTimeZone::isTimeZoneIdAvailable(latinZone)
    -                       ? Qt::TimeZone
    -                       : Qt::OffsetFromUTC)
    -                    : (Q_ASSERT(startsWithLocalTimeZone(zoneName)), Qt::LocalTime);
    -#else
    -                tspec = Qt::LocalTime;
    -#endif
    -            }
    -            break;
    -        case Hour24Section: current = &hour; break;
    -        case Hour12Section: current = &hour12; break;
    -        case MinuteSection: current = &minute; break;
    -        case SecondSection: current = &second; break;
    -        case MSecSection: current = &msec; break;
    -        case YearSection: current = &year; break;
    -        case YearSection2Digits: current = &year2digits; break;
    -        case MonthSection: current = &month; break;
    -        case DayOfWeekSectionShort:
    -        case DayOfWeekSectionLong: current = &dayofweek; break;
    -        case DaySection: current = &day; sect.value = qMax(1, sect.value); break;
    -        case AmPmSection: current = &m; break;
    -        default:
    -            qWarning("QDateTimeParser::parse Internal error (%ls)",
    -                     qUtf16Printable(sn.name()));
    -            break;
    -        }
    -
    -        if (sect.used > 0)
    -            pos += sect.used;
    -        QDTPDEBUG << index << sn.name() << "is set to"
    -                  << pos << "state is" << stateName(state);
    -
    -        if (!current) {
    -            qWarning("QDateTimeParser::parse Internal error 2");
    -            return StateNode();
    -        }
    -        if (isSet & sn.type && *current != sect.value) {
    -            QDTPDEBUG << "CONFLICT " << sn.name() << *current << sect.value;
    -            conflicts = true;
    -            if (index != currentSectionIndex || sect.state == Invalid) {
    -                continue;
    -            }
    -        }
    -        if (sect.state != Invalid)
    -            *current = sect.value;
    -
    -        // Record the present section:
    -        isSet |= sn.type;
    -    }
    -
    -    if (input->midRef(pos) != separators.last()) {
    -        QDTPDEBUG << "invalid because" << input->midRef(pos)
    -                  << "!=" << separators.last() << pos;
    -        return StateNode();
    -    }
    -
    -    if (parserType != QVariant::Time) {
    -        if (year % 100 != year2digits && (isSet & YearSection2Digits)) {
    -            if (!(isSet & YearSection)) {
    -                year = (year / 100) * 100;
    -                year += year2digits;
    -            } else {
    -                conflicts = true;
    -                const SectionNode &sn = sectionNode(currentSectionIndex);
    -                if (sn.type == YearSection2Digits) {
    -                    year = (year / 100) * 100;
    -                    year += year2digits;
    -                }
    -            }
    -        }
    -
    -        const QDate date(year, month, day);
    -        const int diff = dayofweek - date.dayOfWeek();
    -        if (diff != 0 && state == Acceptable && isSet & DayOfWeekSectionMask) {
    -            if (isSet & DaySection)
    -                conflicts = true;
    -            const SectionNode &sn = sectionNode(currentSectionIndex);
    -            if (sn.type & DayOfWeekSectionMask || currentSectionIndex == -1) {
    -                // dayofweek should be preferred
    -                day += diff;
    -                if (day <= 0) {
    -                    day += 7;
    -                } else if (day > date.daysInMonth()) {
    -                    day -= 7;
    -                }
    -                QDTPDEBUG << year << month << day << dayofweek
    -                          << diff << QDate(year, month, day).dayOfWeek();
    -            }
    -        }
    -
    -        bool needfixday = false;
    -        if (sectionType(currentSectionIndex) & DaySectionMask) {
    -            cachedDay = day;
    -        } else if (cachedDay > day) {
    -            day = cachedDay;
    -            needfixday = true;
    -        }
    -
    -        if (!QDate::isValid(year, month, day)) {
    -            if (day < 32) {
    -                cachedDay = day;
    -            }
    -            if (day > 28 && QDate::isValid(year, month, 1)) {
    -                needfixday = true;
    -            }
    -        }
    -        if (needfixday) {
    -            if (context == FromString) {
    -                return StateNode();
    -            }
    -            if (state == Acceptable && fixday) {
    -                day = qMin(day, QDate(year, month, 1).daysInMonth());
    -
    -                const QLocale loc = locale();
    -                for (int i=0; ireplace(sectionPos(sn), sectionSize(i), loc.toString(day));
    -                    } else if (sn.type & DayOfWeekSectionMask) {
    -                        const int dayOfWeek = QDate(year, month, day).dayOfWeek();
    -                        const QLocale::FormatType dayFormat =
    -                            (sn.type == DayOfWeekSectionShort
    -                             ? QLocale::ShortFormat : QLocale::LongFormat);
    -                        const QString dayName(loc.dayName(dayOfWeek, dayFormat));
    -                        input->replace(sectionPos(sn), sectionSize(i), dayName);
    -                    }
    -                }
    -            } else if (state > Intermediate) {
    -                state = Intermediate;
    -            }
    -        }
    -    }
    -
    -    if (parserType != QVariant::Date) {
    -        if (isSet & Hour12Section) {
    -            const bool hasHour = isSet & Hour24Section;
    -            if (ampm == -1) {
    -                if (hasHour) {
    -                    ampm = (hour < 12 ? 0 : 1);
    -                } else {
    -                    ampm = 0; // no way to tell if this is am or pm so I assume am
    -                }
    -            }
    -            hour12 = (ampm == 0 ? hour12 % 12 : (hour12 % 12) + 12);
    -            if (!hasHour) {
    -                hour = hour12;
    -            } else if (hour != hour12) {
    -                conflicts = true;
    -            }
    -        } else if (ampm != -1) {
    -            if (!(isSet & (Hour24Section))) {
    -                hour = (12 * ampm); // special case. Only ap section
    -            } else if ((ampm == 0) != (hour < 12)) {
    -                conflicts = true;
    -            }
    -        }
    -
    -    }
    -
    -    QDTPDEBUG << year << month << day << hour << minute << second << msec;
    -    Q_ASSERT(state != Invalid);
    -
    -    const QDate date(year, month, day);
    -    const QTime time(hour, minute, second, msec);
    -    const QDateTime when =
    -#if QT_CONFIG(timezone)
    -            tspec == Qt::TimeZone ? QDateTime(date, time, timeZone) :
    -#endif
    -            QDateTime(date, time, tspec, zoneOffset);
    -
    -    // If hour wasn't specified, check the default we're using exists on the
    -    // given date (which might be a spring-forward, skipping an hour).
    -    if (parserType == QVariant::DateTime && !(isSet & HourSectionMask) && !when.isValid()) {
    -        qint64 msecs = when.toMSecsSinceEpoch();
    -        // Fortunately, that gets a useful answer ...
    -        const QDateTime replace =
    -#if QT_CONFIG(timezone)
    -            tspec == Qt::TimeZone
    -            ? QDateTime::fromMSecsSinceEpoch(msecs, timeZone) :
    -#endif
    -            QDateTime::fromMSecsSinceEpoch(msecs, tspec, zoneOffset);
    -        const QTime tick = replace.time();
    -        if (replace.date() == date
    -            && (!(isSet & MinuteSection) || tick.minute() == minute)
    -            && (!(isSet & SecondSection) || tick.second() == second)
    -            && (!(isSet & MSecSection)   || tick.msec() == msec)) {
    -            return StateNode(replace, state, padding, conflicts);
    -        }
    -    }
    -
    -    return StateNode(when, state, padding, conflicts);
    -}
    -
    -/*!
    -  \internal
    -*/
    -
    -QDateTimeParser::StateNode
    -QDateTimeParser::parse(QString input, int position, const QDateTime &defaultValue, bool fixup) const
    -{
    -    const QDateTime minimum = getMinimum();
    -    const QDateTime maximum = getMaximum();
    -
    -    QDTPDEBUG << "parse" << input;
    -    StateNode scan = scanString(defaultValue, fixup, &input);
    -    QDTPDEBUGN("'%s' => '%s'(%s)", input.toLatin1().constData(),
    -               scan.value.toString(QLatin1String("yyyy/MM/dd hh:mm:ss.zzz")).toLatin1().constData(),
    -               stateName(scan.state).toLatin1().constData());
    -
    -    if (scan.value.isValid() && scan.state != Invalid) {
    -        if (context != FromString && scan.value < minimum) {
    -            const QLatin1Char space(' ');
    -            if (scan.value >= minimum)
    -                qWarning("QDateTimeParser::parse Internal error 3 (%ls %ls)",
    -                         qUtf16Printable(scan.value.toString()), qUtf16Printable(minimum.toString()));
    -
    -            bool done = false;
    -            scan.state = Invalid;
    -            const int sectionNodesCount = sectionNodes.size();
    -            for (int i=0; i= minimum && copy <= maximum) {
    -                                scan.state = Intermediate;
    -                                done = true;
    -                            }
    -                            break; }
    -                        }
    -                        Q_FALLTHROUGH();
    -                    case MonthSection:
    -                        if (sn.count >= 3) {
    -                            const int finalMonth = scan.value.date().month();
    -                            int tmp = finalMonth;
    -                            // I know the first possible month makes the date too early
    -                            while ((tmp = findMonth(t, tmp + 1, i)) != -1) {
    -                                const QDateTime copy(scan.value.addMonths(tmp - finalMonth));
    -                                if (copy >= minimum && copy <= maximum)
    -                                    break; // break out of while
    -                            }
    -                            if (tmp != -1) {
    -                                scan.state = Intermediate;
    -                                done = true;
    -                            }
    -                            break;
    -                        }
    -                        Q_FALLTHROUGH();
    -                    default: {
    -                        int toMin;
    -                        int toMax;
    -
    -                        if (sn.type & TimeSectionMask) {
    -                            if (scan.value.daysTo(minimum) != 0) {
    -                                break;
    -                            }
    -                            const QTime time = scan.value.time();
    -                            toMin = time.msecsTo(minimum.time());
    -                            if (scan.value.daysTo(maximum) > 0)
    -                                toMax = -1; // can't get to max
    -                            else
    -                                toMax = time.msecsTo(maximum.time());
    -                        } else {
    -                            toMin = scan.value.daysTo(minimum);
    -                            toMax = scan.value.daysTo(maximum);
    -                        }
    -                        const int maxChange = sn.maxChange();
    -                        if (toMin > maxChange) {
    -                            QDTPDEBUG << "invalid because toMin > maxChange" << toMin
    -                                      << maxChange << t << scan.value << minimum;
    -                            scan.state = Invalid;
    -                            done = true;
    -                            break;
    -                        } else if (toMax > maxChange) {
    -                            toMax = -1; // can't get to max
    -                        }
    -
    -                        const int min = getDigit(minimum, i);
    -                        if (min == -1) {
    -                            qWarning("QDateTimeParser::parse Internal error 4 (%ls)",
    -                                     qUtf16Printable(sn.name()));
    -                            scan.state = Invalid;
    -                            done = true;
    -                            break;
    -                        }
    -
    -                        int max = toMax != -1 ? getDigit(maximum, i) : absoluteMax(i, scan.value);
    -                        int pos = position + scan.padded - sn.pos;
    -                        if (pos < 0 || pos >= t.size())
    -                            pos = -1;
    -                        if (!potentialValue(t.simplified(), min, max, i, scan.value, pos)) {
    -                            QDTPDEBUG << "invalid because potentialValue(" << t.simplified() << min << max
    -                                      << sn.name() << "returned" << toMax << toMin << pos;
    -                            scan.state = Invalid;
    -                            done = true;
    -                            break;
    -                        }
    -                        scan.state = Intermediate;
    -                        done = true;
    -                        break; }
    -                    }
    -                }
    -            }
    -        } else {
    -            if (context == FromString) {
    -                // optimization
    -                Q_ASSERT(maximum.date().toJulianDay() == 5373484);
    -                if (scan.value.date().toJulianDay() > 5373484)
    -                    scan.state = Invalid;
    -            } else {
    -                if (scan.value > maximum)
    -                    scan.state = Invalid;
    -            }
    -
    -            QDTPDEBUG << "not checking intermediate because scanned value is" << scan.value << minimum << maximum;
    -        }
    -    }
    -    text = scan.input = input;
    -    // Set spec *after* all checking, so validity is a property of the string:
    -    scan.value = scan.value.toTimeSpec(spec);
    -    return scan;
    -}
    -
    -/*
    -  \internal
    -  \brief Returns the index in \a entries with the best prefix match to \a text
    -
    -  Scans \a entries looking for an entry overlapping \a text as much as possible
    -  (an exact match beats any prefix match; a match of the full entry as prefix of
    -  text beats any entry but one matching a longer prefix; otherwise, the match of
    -  longest prefix wins, earlier entries beating later on a draw).  Records the
    -  length of overlap in *used (if \a used is non-NULL) and the first entry that
    -  overlapped this much in *usedText (if \a usedText is non-NULL).
    - */
    -static int findTextEntry(const QString &text, const QVector &entries, QString *usedText, int *used)
    -{
    -    if (text.isEmpty())
    -        return -1;
    -
    -    int bestMatch = -1;
    -    int bestCount = 0;
    -    for (int n = 0; n < entries.size(); ++n)
    -    {
    -        const QString &name = entries.at(n);
    -
    -        const int limit = qMin(text.size(), name.size());
    -        int i = 0;
    -        while (i < limit && text.at(i) == name.at(i).toLower())
    -            ++i;
    -        // Full match beats an equal prefix match:
    -        if (i > bestCount || (i == bestCount && i == name.size())) {
    -            bestCount = i;
    -            bestMatch = n;
    -            if (i == name.size() && i == text.size())
    -                break; // Exact match, name == text, wins.
    -        }
    -    }
    -    if (usedText && bestMatch != -1)
    -        *usedText = entries.at(bestMatch);
    -    if (used)
    -        *used = bestCount;
    -
    -    return bestMatch;
    -}
    -
    -/*!
    -  \internal
    -  finds the first possible monthname that \a str1 can
    -  match. Starting from \a index; str should already by lowered
    -*/
    -
    -int QDateTimeParser::findMonth(const QString &str1, int startMonth, int sectionIndex,
    -                               QString *usedMonth, int *used) const
    -{
    -    const SectionNode &sn = sectionNode(sectionIndex);
    -    if (sn.type != MonthSection) {
    -        qWarning("QDateTimeParser::findMonth Internal error");
    -        return -1;
    -    }
    -
    -    QLocale::FormatType type = sn.count == 3 ? QLocale::ShortFormat : QLocale::LongFormat;
    -    QLocale l = locale();
    -    QVector monthNames;
    -    monthNames.reserve(13 - startMonth);
    -    for (int month = startMonth; month <= 12; ++month)
    -        monthNames.append(l.monthName(month, type));
    -
    -    const int index = findTextEntry(str1, monthNames, usedMonth, used);
    -    return index < 0 ? index : index + startMonth;
    -}
    -
    -int QDateTimeParser::findDay(const QString &str1, int startDay, int sectionIndex, QString *usedDay, int *used) const
    -{
    -    const SectionNode &sn = sectionNode(sectionIndex);
    -    if (!(sn.type & DaySectionMask)) {
    -        qWarning("QDateTimeParser::findDay Internal error");
    -        return -1;
    -    }
    -
    -    QLocale::FormatType type = sn.count == 4 ? QLocale::LongFormat : QLocale::ShortFormat;
    -    QLocale l = locale();
    -    QVector daysOfWeek;
    -    daysOfWeek.reserve(8 - startDay);
    -    for (int day = startDay; day <= 7; ++day)
    -        daysOfWeek.append(l.dayName(day, type));
    -
    -    const int index = findTextEntry(str1, daysOfWeek, usedDay, used);
    -    return index < 0 ? index : index + startDay;
    -}
    -
    -/*!
    -  \internal
    -
    -  Return's .value is zone's offset, zone time - UTC time, in seconds.
    -  See QTimeZonePrivate::isValidId() for the format of zone names.
    - */
    -QDateTimeParser::ParsedSection
    -QDateTimeParser::findTimeZone(QStringRef str, const QDateTime &when,
    -                              int maxVal, int minVal) const
    -{
    -#if QT_CONFIG(timezone)
    -    int index = startsWithLocalTimeZone(str);
    -    int offset;
    -
    -    if (index > 0) {
    -        // We won't actually use this, but we need a valid return:
    -        offset = QDateTime(when.date(), when.time(), Qt::LocalTime).offsetFromUtc();
    -    } else {
    -        int size = str.length();
    -        offset = std::numeric_limits::max(); // deliberately out of range
    -        Q_ASSERT(offset > QTimeZone::MaxUtcOffsetSecs); // cf. absoluteMax()
    -
    -        // Collect up plausibly-valid characters; let QTimeZone work out what's truly valid.
    -        while (index < size) {
    -            QChar here = str[index];
    -            if (here < 127
    -                && (here.isLetterOrNumber()
    -                    || here == '/' || here == '-'
    -                    || here == '_' || here == '.'
    -                    || here == '+' || here == ':'))
    -                index++;
    -            else
    -                break;
    -        }
    -
    -        while (index > 0) {
    -            str.truncate(index);
    -            if (str == QLatin1String("Z")) {
    -                offset = 0; // "Zulu" time - a.k.a. UTC
    -                break;
    -            }
    -            QTimeZone zone(str.toLatin1());
    -            if (zone.isValid()) {
    -                offset = zone.offsetFromUtc(when);
    -                break;
    -            }
    -            index--; // maybe we collected too much ...
    -        }
    -    }
    -
    -    if (index > 0 && maxVal >= offset && offset >= minVal)
    -        return ParsedSection(Acceptable, offset, index);
    -
    -#endif // timezone
    -    return ParsedSection();
    -}
    -
    -/*!
    -  \internal
    -
    -  Returns
    -  AM if str == tr("AM")
    -  PM if str == tr("PM")
    -  PossibleAM if str can become tr("AM")
    -  PossiblePM if str can become tr("PM")
    -  PossibleBoth if str can become tr("PM") and can become tr("AM")
    -  Neither if str can't become anything sensible
    -*/
    -QDateTimeParser::AmPmFinder QDateTimeParser::findAmPm(QString &str, int sectionIndex, int *used) const
    -{
    -    const SectionNode &s = sectionNode(sectionIndex);
    -    if (s.type != AmPmSection) {
    -        qWarning("QDateTimeParser::findAmPm Internal error");
    -        return Neither;
    -    }
    -    if (used)
    -        *used = str.size();
    -    if (QStringRef(&str).trimmed().isEmpty()) {
    -        return PossibleBoth;
    -    }
    -    const QLatin1Char space(' ');
    -    int size = sectionMaxSize(sectionIndex);
    -
    -    enum {
    -        amindex = 0,
    -        pmindex = 1
    -    };
    -    QString ampm[2];
    -    ampm[amindex] = getAmPmText(AmText, s.count == 1 ? UpperCase : LowerCase);
    -    ampm[pmindex] = getAmPmText(PmText, s.count == 1 ? UpperCase : LowerCase);
    -    for (int i=0; i<2; ++i)
    -        ampm[i].truncate(size);
    -
    -    QDTPDEBUG << "findAmPm" << str << ampm[0] << ampm[1];
    -
    -    if (str.indexOf(ampm[amindex], 0, Qt::CaseInsensitive) == 0) {
    -        str = ampm[amindex];
    -        return AM;
    -    } else if (str.indexOf(ampm[pmindex], 0, Qt::CaseInsensitive) == 0) {
    -        str = ampm[pmindex];
    -        return PM;
    -    } else if (context == FromString || (str.count(space) == 0 && str.size() >= size)) {
    -        return Neither;
    -    }
    -    size = qMin(size, str.size());
    -
    -    bool broken[2] = {false, false};
    -    for (int i=0; i= min && val <= max && str.size() == size) {
    -        return true;
    -    } else if (val > max) {
    -        return false;
    -    } else if (str.size() == size && val < min) {
    -        return false;
    -    }
    -
    -    const int len = size - str.size();
    -    for (int i=0; i= 0) {
    -                const QString tmp = str.left(insert) + QLatin1Char('0' + j) + str.mid(insert);
    -                if (potentialValue(tmp, min, max, index, currentValue, insert))
    -                    return true;
    -            }
    -        }
    -    }
    -
    -    return false;
    -}
    -
    -/*!
    -  \internal
    -*/
    -bool QDateTimeParser::skipToNextSection(int index, const QDateTime ¤t, const QStringRef &text) const
    -{
    -    Q_ASSERT(text.size() < sectionMaxSize(index));
    -    const SectionNode &node = sectionNode(index);
    -    int min = absoluteMin(index);
    -    int max = absoluteMax(index, current);
    -    // Time-zone field is only numeric if given as offset from UTC:
    -    if (node.type != TimeZoneSection || current.timeSpec() == Qt::OffsetFromUTC) {
    -        const QDateTime maximum = getMaximum();
    -        const QDateTime minimum = getMinimum();
    -        Q_ASSERT(current >= minimum && current <= maximum);
    -
    -        QDateTime tmp = current;
    -        if (!setDigit(tmp, index, min) || tmp < minimum)
    -            min = getDigit(minimum, index);
    -
    -        if (!setDigit(tmp, index, max) || tmp > maximum)
    -            max = getDigit(maximum, index);
    -    }
    -    int pos = cursorPosition() - node.pos;
    -    if (pos < 0 || pos >= text.size())
    -        pos = -1;
    -
    -    /*
    -      If the value potentially can become another valid entry we don't want to
    -      skip to the next. E.g. In a M field (month without leading 0) if you type
    -      1 we don't want to autoskip (there might be [012] following) but if you
    -      type 3 we do.
    -    */
    -    return !potentialValue(text, min, max, index, current, pos);
    -}
    -
    -/*!
    -  \internal
    -  For debugging. Returns the name of the section \a s.
    -*/
    -
    -QString QDateTimeParser::SectionNode::name(QDateTimeParser::Section s)
    -{
    -    switch (s) {
    -    case QDateTimeParser::AmPmSection: return QLatin1String("AmPmSection");
    -    case QDateTimeParser::DaySection: return QLatin1String("DaySection");
    -    case QDateTimeParser::DayOfWeekSectionShort: return QLatin1String("DayOfWeekSectionShort");
    -    case QDateTimeParser::DayOfWeekSectionLong: return QLatin1String("DayOfWeekSectionLong");
    -    case QDateTimeParser::Hour24Section: return QLatin1String("Hour24Section");
    -    case QDateTimeParser::Hour12Section: return QLatin1String("Hour12Section");
    -    case QDateTimeParser::MSecSection: return QLatin1String("MSecSection");
    -    case QDateTimeParser::MinuteSection: return QLatin1String("MinuteSection");
    -    case QDateTimeParser::MonthSection: return QLatin1String("MonthSection");
    -    case QDateTimeParser::SecondSection: return QLatin1String("SecondSection");
    -    case QDateTimeParser::TimeZoneSection: return QLatin1String("TimeZoneSection");
    -    case QDateTimeParser::YearSection: return QLatin1String("YearSection");
    -    case QDateTimeParser::YearSection2Digits: return QLatin1String("YearSection2Digits");
    -    case QDateTimeParser::NoSection: return QLatin1String("NoSection");
    -    case QDateTimeParser::FirstSection: return QLatin1String("FirstSection");
    -    case QDateTimeParser::LastSection: return QLatin1String("LastSection");
    -    default: return QLatin1String("Unknown section ") + QString::number(int(s));
    -    }
    -}
    -
    -/*!
    -  \internal
    -  For debugging. Returns the name of the state \a s.
    -*/
    -
    -QString QDateTimeParser::stateName(State s) const
    -{
    -    switch (s) {
    -    case Invalid: return QLatin1String("Invalid");
    -    case Intermediate: return QLatin1String("Intermediate");
    -    case Acceptable: return QLatin1String("Acceptable");
    -    default: return QLatin1String("Unknown state ") + QString::number(s);
    -    }
    -}
    -
    -#if QT_CONFIG(datestring)
    -bool QDateTimeParser::fromString(const QString &t, QDate *date, QTime *time) const
    -{
    -    QDateTime val(QDate(1900, 1, 1).startOfDay());
    -    const StateNode tmp = parse(t, -1, val, false);
    -    if (tmp.state != Acceptable || tmp.conflicts) {
    -        return false;
    -    }
    -    if (time) {
    -        const QTime t = tmp.value.time();
    -        if (!t.isValid()) {
    -            return false;
    -        }
    -        *time = t;
    -    }
    -
    -    if (date) {
    -        const QDate d = tmp.value.date();
    -        if (!d.isValid()) {
    -            return false;
    -        }
    -        *date = d;
    -    }
    -    return true;
    -}
    -#endif // datestring
    -
    -QDateTime QDateTimeParser::getMinimum() const
    -{
    -    // Cache the most common case
    -    if (spec == Qt::LocalTime) {
    -        static const QDateTime localTimeMin(QDATETIMEEDIT_DATE_MIN.startOfDay(Qt::LocalTime));
    -        return localTimeMin;
    -    }
    -    return QDateTime(QDATETIMEEDIT_DATE_MIN.startOfDay(spec));
    -}
    -
    -QDateTime QDateTimeParser::getMaximum() const
    -{
    -    // Cache the most common case
    -    if (spec == Qt::LocalTime) {
    -        static const QDateTime localTimeMax(QDATETIMEEDIT_DATE_MAX.endOfDay(Qt::LocalTime));
    -        return localTimeMax;
    -    }
    -    return QDateTime(QDATETIMEEDIT_DATE_MAX.endOfDay(spec));
    -}
    -
    -QString QDateTimeParser::getAmPmText(AmPm ap, Case cs) const
    -{
    -    const QLocale loc = locale();
    -    QString raw = ap == AmText ? loc.amText() : loc.pmText();
    -    return cs == UpperCase ? raw.toUpper() : raw.toLower();
    -}
    -
    -/*
    -  \internal
    -
    -  I give arg2 preference because arg1 is always a QDateTime.
    -*/
    -
    -bool operator==(const QDateTimeParser::SectionNode &s1, const QDateTimeParser::SectionNode &s2)
    -{
    -    return (s1.type == s2.type) && (s1.pos == s2.pos) && (s1.count == s2.count);
    -}
    -
    -QT_END_NAMESPACE
    diff --git a/src/corelib/tools/qdatetimeparser_p.h b/src/corelib/tools/qdatetimeparser_p.h
    deleted file mode 100644
    index d9e39f0795..0000000000
    --- a/src/corelib/tools/qdatetimeparser_p.h
    +++ /dev/null
    @@ -1,310 +0,0 @@
    -/****************************************************************************
    -**
    -** Copyright (C) 2016 The Qt Company Ltd.
    -** Contact: https://www.qt.io/licensing/
    -**
    -** This file is part of the QtCore module of the Qt Toolkit.
    -**
    -** $QT_BEGIN_LICENSE:LGPL$
    -** Commercial License Usage
    -** Licensees holding valid commercial Qt licenses may use this file in
    -** accordance with the commercial license agreement provided with the
    -** Software or, alternatively, in accordance with the terms contained in
    -** a written agreement between you and The Qt Company. For licensing terms
    -** and conditions see https://www.qt.io/terms-conditions. For further
    -** information use the contact form at https://www.qt.io/contact-us.
    -**
    -** GNU Lesser General Public License Usage
    -** Alternatively, this file may be used under the terms of the GNU Lesser
    -** General Public License version 3 as published by the Free Software
    -** Foundation and appearing in the file LICENSE.LGPL3 included in the
    -** packaging of this file. Please review the following information to
    -** ensure the GNU Lesser General Public License version 3 requirements
    -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
    -**
    -** GNU General Public License Usage
    -** Alternatively, this file may be used under the terms of the GNU
    -** General Public License version 2.0 or (at your option) the GNU General
    -** Public license version 3 or any later version approved by the KDE Free
    -** Qt Foundation. The licenses are as published by the Free Software
    -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
    -** included in the packaging of this file. Please review the following
    -** information to ensure the GNU General Public License requirements will
    -** be met: https://www.gnu.org/licenses/gpl-2.0.html and
    -** https://www.gnu.org/licenses/gpl-3.0.html.
    -**
    -** $QT_END_LICENSE$
    -**
    -****************************************************************************/
    -
    -#ifndef QDATETIMEPARSER_P_H
    -#define QDATETIMEPARSER_P_H
    -
    -//
    -//  W A R N I N G
    -//  -------------
    -//
    -// This file is not part of the Qt API.  It exists purely as an
    -// implementation detail.  This header file may change from version to
    -// version without notice, or even be removed.
    -//
    -// We mean it.
    -//
    -
    -#include 
    -#include "qplatformdefs.h"
    -#include "QtCore/qatomic.h"
    -#include "QtCore/qdatetime.h"
    -#include "QtCore/qstringlist.h"
    -#include "QtCore/qlocale.h"
    -#ifndef QT_BOOTSTRAPPED
    -# include "QtCore/qvariant.h"
    -#endif
    -#include "QtCore/qvector.h"
    -#include "QtCore/qcoreapplication.h"
    -
    -QT_REQUIRE_CONFIG(datetimeparser);
    -
    -#define QDATETIMEEDIT_TIME_MIN QTime(0, 0) // Prefer QDate::startOfDay()
    -#define QDATETIMEEDIT_TIME_MAX QTime(23, 59, 59, 999) // Prefer QDate::endOfDay()
    -#define QDATETIMEEDIT_DATE_MIN QDate(100, 1, 1)
    -#define QDATETIMEEDIT_COMPAT_DATE_MIN QDate(1752, 9, 14)
    -#define QDATETIMEEDIT_DATE_MAX QDate(9999, 12, 31)
    -#define QDATETIMEEDIT_DATE_INITIAL QDate(2000, 1, 1)
    -
    -QT_BEGIN_NAMESPACE
    -
    -class Q_CORE_EXPORT QDateTimeParser
    -{
    -    Q_DECLARE_TR_FUNCTIONS(QDateTimeParser)
    -public:
    -    enum Context {
    -        FromString,
    -        DateTimeEdit
    -    };
    -    QDateTimeParser(QVariant::Type t, Context ctx)
    -        : currentSectionIndex(-1), display(nullptr), cachedDay(-1), parserType(t),
    -        fixday(false), spec(Qt::LocalTime), context(ctx)
    -    {
    -        defaultLocale = QLocale::system();
    -        first.type = FirstSection;
    -        first.pos = -1;
    -        first.count = -1;
    -        first.zeroesAdded = 0;
    -        last.type = LastSection;
    -        last.pos = -1;
    -        last.count = -1;
    -        last.zeroesAdded = 0;
    -        none.type = NoSection;
    -        none.pos = -1;
    -        none.count = -1;
    -        none.zeroesAdded = 0;
    -    }
    -    virtual ~QDateTimeParser();
    -
    -    enum Section {
    -        NoSection     = 0x00000,
    -        AmPmSection   = 0x00001,
    -        MSecSection   = 0x00002,
    -        SecondSection = 0x00004,
    -        MinuteSection = 0x00008,
    -        Hour12Section   = 0x00010,
    -        Hour24Section   = 0x00020,
    -        TimeZoneSection = 0x00040,
    -        HourSectionMask = (Hour12Section | Hour24Section),
    -        TimeSectionMask = (MSecSection | SecondSection | MinuteSection |
    -                           HourSectionMask | AmPmSection | TimeZoneSection),
    -
    -        DaySection         = 0x00100,
    -        MonthSection       = 0x00200,
    -        YearSection        = 0x00400,
    -        YearSection2Digits = 0x00800,
    -        YearSectionMask = YearSection | YearSection2Digits,
    -        DayOfWeekSectionShort = 0x01000,
    -        DayOfWeekSectionLong  = 0x02000,
    -        DayOfWeekSectionMask = DayOfWeekSectionShort | DayOfWeekSectionLong,
    -        DaySectionMask = DaySection | DayOfWeekSectionMask,
    -        DateSectionMask = DaySectionMask | MonthSection | YearSectionMask,
    -
    -        Internal             = 0x10000,
    -        FirstSection         = 0x20000 | Internal,
    -        LastSection          = 0x40000 | Internal,
    -        CalendarPopupSection = 0x80000 | Internal,
    -
    -        NoSectionIndex = -1,
    -        FirstSectionIndex = -2,
    -        LastSectionIndex = -3,
    -        CalendarPopupIndex = -4
    -    }; // extending qdatetimeedit.h's equivalent
    -    Q_DECLARE_FLAGS(Sections, Section)
    -
    -    struct Q_CORE_EXPORT SectionNode {
    -        Section type;
    -        mutable int pos;
    -        int count;
    -        int zeroesAdded;
    -
    -        static QString name(Section s);
    -        QString name() const { return name(type); }
    -        QString format() const;
    -        int maxChange() const;
    -    };
    -
    -    enum State { // duplicated from QValidator
    -        Invalid,
    -        Intermediate,
    -        Acceptable
    -    };
    -
    -    struct StateNode {
    -        StateNode() : state(Invalid), padded(0), conflicts(false) {}
    -        StateNode(const QDateTime &val, State ok=Acceptable, int pad=0, bool bad=false)
    -            : value(val), state(ok), padded(pad), conflicts(bad) {}
    -        QString input;
    -        QDateTime value;
    -        State state;
    -        int padded;
    -        bool conflicts;
    -    };
    -
    -    enum AmPm {
    -        AmText,
    -        PmText
    -    };
    -
    -    enum Case {
    -        UpperCase,
    -        LowerCase
    -    };
    -
    -#if QT_CONFIG(datestring)
    -    StateNode parse(QString input, int position, const QDateTime &defaultValue, bool fixup) const;
    -    bool fromString(const QString &text, QDate *date, QTime *time) const;
    -#endif
    -    bool parseFormat(const QString &format);
    -
    -    enum FieldInfoFlag {
    -        Numeric = 0x01,
    -        FixedWidth = 0x02,
    -        AllowPartial = 0x04,
    -        Fraction = 0x08
    -    };
    -    Q_DECLARE_FLAGS(FieldInfo, FieldInfoFlag)
    -
    -    FieldInfo fieldInfo(int index) const;
    -
    -    void setDefaultLocale(const QLocale &loc) { defaultLocale = loc; }
    -    virtual QString displayText() const { return text; }
    -
    -private:
    -    int sectionMaxSize(Section s, int count) const;
    -    QString sectionText(const QString &text, int sectionIndex, int index) const;
    -#if QT_CONFIG(datestring)
    -    StateNode scanString(const QDateTime &defaultValue,
    -                         bool fixup, QString *input) const;
    -    struct ParsedSection {
    -        int value;
    -        int used;
    -        int zeroes;
    -        State state;
    -        Q_DECL_CONSTEXPR ParsedSection(State ok = Invalid,
    -                                       int val = 0, int read = 0, int zs = 0)
    -            : value(ok == Invalid ? -1 : val), used(read), zeroes(zs), state(ok)
    -            {}
    -    };
    -    ParsedSection parseSection(const QDateTime ¤tValue, int sectionIndex,
    -                               int offset, QString *text) const;
    -    int findMonth(const QString &str1, int monthstart, int sectionIndex,
    -                  QString *monthName = nullptr, int *used = nullptr) const;
    -    int findDay(const QString &str1, int intDaystart, int sectionIndex,
    -                QString *dayName = nullptr, int *used = nullptr) const;
    -    ParsedSection findTimeZone(QStringRef str, const QDateTime &when,
    -                               int maxVal, int minVal) const;
    -#if QT_CONFIG(timezone)
    -    // Implemented in qdatetime.cpp:
    -    static int startsWithLocalTimeZone(const QStringRef name);
    -#endif
    -
    -    enum AmPmFinder {
    -        Neither = -1,
    -        AM = 0,
    -        PM = 1,
    -        PossibleAM = 2,
    -        PossiblePM = 3,
    -        PossibleBoth = 4
    -    };
    -    AmPmFinder findAmPm(QString &str, int index, int *used = nullptr) const;
    -#endif // datestring
    -
    -    bool potentialValue(const QStringRef &str, int min, int max, int index,
    -                        const QDateTime ¤tValue, int insert) const;
    -    bool potentialValue(const QString &str, int min, int max, int index,
    -                        const QDateTime ¤tValue, int insert) const
    -    {
    -        return potentialValue(QStringRef(&str), min, max, index, currentValue, insert);
    -    }
    -
    -protected: // for the benefit of QDateTimeEditPrivate
    -    int sectionSize(int index) const;
    -    int sectionMaxSize(int index) const;
    -    int sectionPos(int index) const;
    -    int sectionPos(const SectionNode &sn) const;
    -
    -    const SectionNode §ionNode(int index) const;
    -    Section sectionType(int index) const;
    -    QString sectionText(int sectionIndex) const;
    -    int getDigit(const QDateTime &dt, int index) const;
    -    bool setDigit(QDateTime &t, int index, int newval) const;
    -
    -    int absoluteMax(int index, const QDateTime &value = QDateTime()) const;
    -    int absoluteMin(int index) const;
    -
    -    bool skipToNextSection(int section, const QDateTime ¤t, const QStringRef §ionText) const;
    -    bool skipToNextSection(int section, const QDateTime ¤t, const QString §ionText) const
    -    {
    -        return skipToNextSection(section, current, QStringRef(§ionText));
    -    }
    -    QString stateName(State s) const;
    -    virtual QDateTime getMinimum() const;
    -    virtual QDateTime getMaximum() const;
    -    virtual int cursorPosition() const { return -1; }
    -    virtual QString getAmPmText(AmPm ap, Case cs) const;
    -    virtual QLocale locale() const { return defaultLocale; }
    -
    -    mutable int currentSectionIndex;
    -    Sections display;
    -    /*
    -        This stores the most recently selected day.
    -        It is useful when considering the following scenario:
    -
    -        1. Date is: 31/01/2000
    -        2. User increments month: 29/02/2000
    -        3. User increments month: 31/03/2000
    -
    -        At step 1, cachedDay stores 31. At step 2, the 31 is invalid for February, so the cachedDay is not updated.
    -        At step 3, the month is changed to March, for which 31 is a valid day. Since 29 < 31, the day is set to cachedDay.
    -        This is good for when users have selected their desired day and are scrolling up or down in the month or year section
    -        and do not want smaller months (or non-leap years) to alter the day that they chose.
    -    */
    -    mutable int cachedDay;
    -    mutable QString text;
    -    QVector sectionNodes;
    -    SectionNode first, last, none, popup;
    -    QStringList separators;
    -    QString displayFormat;
    -    QLocale defaultLocale;
    -    QVariant::Type parserType;
    -    bool fixday;
    -    Qt::TimeSpec spec; // spec if used by QDateTimeEdit
    -    Context context;
    -};
    -Q_DECLARE_TYPEINFO(QDateTimeParser::SectionNode, Q_PRIMITIVE_TYPE);
    -
    -Q_CORE_EXPORT bool operator==(const QDateTimeParser::SectionNode &s1, const QDateTimeParser::SectionNode &s2);
    -
    -Q_DECLARE_OPERATORS_FOR_FLAGS(QDateTimeParser::Sections)
    -Q_DECLARE_OPERATORS_FOR_FLAGS(QDateTimeParser::FieldInfo)
    -
    -QT_END_NAMESPACE
    -
    -#endif // QDATETIME_P_H
    diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp
    index f6eaa53c3a..c8740e55f3 100644
    --- a/src/corelib/tools/qlocale.cpp
    +++ b/src/corelib/tools/qlocale.cpp
    @@ -55,7 +55,7 @@
     #include "qlocale_p.h"
     #include "qlocale_tools_p.h"
     #if QT_CONFIG(datetimeparser)
    -#include "qdatetimeparser_p.h"
    +#include "private/qdatetimeparser_p.h"
     #endif
     #include "qnamespace.h"
     #include "qdatetime.h"
    diff --git a/src/corelib/tools/qtimezone.cpp b/src/corelib/tools/qtimezone.cpp
    deleted file mode 100644
    index ef323de14a..0000000000
    --- a/src/corelib/tools/qtimezone.cpp
    +++ /dev/null
    @@ -1,997 +0,0 @@
    -/****************************************************************************
    -**
    -** Copyright (C) 2013 John Layt 
    -** Contact: https://www.qt.io/licensing/
    -**
    -** This file is part of the QtCore module of the Qt Toolkit.
    -**
    -** $QT_BEGIN_LICENSE:LGPL$
    -** Commercial License Usage
    -** Licensees holding valid commercial Qt licenses may use this file in
    -** accordance with the commercial license agreement provided with the
    -** Software or, alternatively, in accordance with the terms contained in
    -** a written agreement between you and The Qt Company. For licensing terms
    -** and conditions see https://www.qt.io/terms-conditions. For further
    -** information use the contact form at https://www.qt.io/contact-us.
    -**
    -** GNU Lesser General Public License Usage
    -** Alternatively, this file may be used under the terms of the GNU Lesser
    -** General Public License version 3 as published by the Free Software
    -** Foundation and appearing in the file LICENSE.LGPL3 included in the
    -** packaging of this file. Please review the following information to
    -** ensure the GNU Lesser General Public License version 3 requirements
    -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
    -**
    -** GNU General Public License Usage
    -** Alternatively, this file may be used under the terms of the GNU
    -** General Public License version 2.0 or (at your option) the GNU General
    -** Public license version 3 or any later version approved by the KDE Free
    -** Qt Foundation. The licenses are as published by the Free Software
    -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
    -** included in the packaging of this file. Please review the following
    -** information to ensure the GNU General Public License requirements will
    -** be met: https://www.gnu.org/licenses/gpl-2.0.html and
    -** https://www.gnu.org/licenses/gpl-3.0.html.
    -**
    -** $QT_END_LICENSE$
    -**
    -****************************************************************************/
    -
    -
    -#include "qtimezone.h"
    -#include "qtimezoneprivate_p.h"
    -
    -#include 
    -#include 
    -
    -#include 
    -
    -#include 
    -
    -QT_BEGIN_NAMESPACE
    -
    -// Create default time zone using appropriate backend
    -static QTimeZonePrivate *newBackendTimeZone()
    -{
    -#ifdef QT_NO_SYSTEMLOCALE
    -#if QT_CONFIG(icu)
    -    return new QIcuTimeZonePrivate();
    -#else
    -    return new QUtcTimeZonePrivate();
    -#endif
    -#else
    -#if defined Q_OS_MAC
    -    return new QMacTimeZonePrivate();
    -#elif defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
    -    return new QAndroidTimeZonePrivate();
    -#elif defined(Q_OS_UNIX) || defined(Q_OS_ANDROID_EMBEDDED)
    -    return new QTzTimeZonePrivate();
    -#elif QT_CONFIG(icu)
    -    return new QIcuTimeZonePrivate();
    -#elif defined Q_OS_WIN
    -    return new QWinTimeZonePrivate();
    -#else
    -    return new QUtcTimeZonePrivate();
    -#endif // System Locales
    -#endif // QT_NO_SYSTEMLOCALE
    -}
    -
    -// Create named time zone using appropriate backend
    -static QTimeZonePrivate *newBackendTimeZone(const QByteArray &ianaId)
    -{
    -#ifdef QT_NO_SYSTEMLOCALE
    -#if QT_CONFIG(icu)
    -    return new QIcuTimeZonePrivate(ianaId);
    -#else
    -    return new QUtcTimeZonePrivate(ianaId);
    -#endif
    -#else
    -#if defined Q_OS_MAC
    -    return new QMacTimeZonePrivate(ianaId);
    -#elif defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
    -    return new QAndroidTimeZonePrivate(ianaId);
    -#elif defined(Q_OS_UNIX) || defined(Q_OS_ANDROID_EMBEDDED)
    -    return new QTzTimeZonePrivate(ianaId);
    -#elif QT_CONFIG(icu)
    -    return new QIcuTimeZonePrivate(ianaId);
    -#elif defined Q_OS_WIN
    -    return new QWinTimeZonePrivate(ianaId);
    -#else
    -    return new QUtcTimeZonePrivate(ianaId);
    -#endif // System Locales
    -#endif // QT_NO_SYSTEMLOCALE
    -}
    -
    -class QTimeZoneSingleton
    -{
    -public:
    -    QTimeZoneSingleton() : backend(newBackendTimeZone()) {}
    -
    -    // The backend_tz is the tz to use in static methods such as availableTimeZoneIds() and
    -    // isTimeZoneIdAvailable() and to create named IANA time zones.  This is usually the host
    -    // system, but may be different if the host resources are insufficient or if
    -    // QT_NO_SYSTEMLOCALE is set.  A simple UTC backend is used if no alternative is available.
    -    QSharedDataPointer backend;
    -};
    -
    -Q_GLOBAL_STATIC(QTimeZoneSingleton, global_tz);
    -
    -/*!
    -    \class QTimeZone
    -    \inmodule QtCore
    -    \since 5.2
    -
    -    \brief The QTimeZone class converts between UTC and local time in a specific
    -           time zone.
    -
    -    \threadsafe
    -
    -    This class provides a stateless calculator for time zone conversions
    -    between UTC and the local time in a specific time zone.  By default it uses
    -    the host system time zone data to perform these conversions.
    -
    -    This class is primarily designed for use in QDateTime; most applications
    -    will not need to access this class directly and should instead use
    -    QDateTime with a Qt::TimeSpec of Qt::TimeZone.
    -
    -    \note For consistency with QDateTime, QTimeZone does not account for leap
    -    seconds.
    -
    -    \section1 Remarks
    -
    -    \section2 IANA Time Zone IDs
    -
    -    QTimeZone uses the IANA time zone IDs as defined in the IANA Time Zone
    -    Database (http://www.iana.org/time-zones). This is to ensure a standard ID
    -    across all supported platforms.  Most platforms support the IANA IDs
    -    and the IANA Database natively, but for Windows a mapping is required to
    -    the native IDs.  See below for more details.
    -
    -    The IANA IDs can and do change on a regular basis, and can vary depending
    -    on how recently the host system data was updated.  As such you cannot rely
    -    on any given ID existing on any host system.  You must use
    -    availableTimeZoneIds() to determine what IANA IDs are available.
    -
    -    The IANA IDs and database are also know as the Olson IDs and database,
    -    named after their creator.
    -
    -    \section2 UTC Offset Time Zones
    -
    -    A default UTC time zone backend is provided which is always guaranteed to
    -    be available.  This provides a set of generic Offset From UTC time zones
    -    in the range UTC-14:00 to UTC+14:00.  These time zones can be created
    -    using either the standard ISO format names "UTC+00:00" as listed by
    -    availableTimeZoneIds(), or using the number of offset seconds.
    -
    -    \section2 Windows Time Zones
    -
    -    Windows native time zone support is severely limited compared to the
    -    standard IANA TZ Database.  Windows time zones cover larger geographic
    -    areas and are thus less accurate in their conversions.  They also do not
    -    support as much historic conversion data and so may only be accurate for
    -    the current year.
    -
    -    QTimeZone uses a conversion table derived form the Unicode CLDR data to map
    -    between IANA IDs and Windows IDs.  Depending on your version of Windows
    -    and Qt, this table may not be able to provide a valid conversion, in which
    -    "UTC" will be returned.
    -
    -    QTimeZone provides a public API to use this conversion table.  The Windows ID
    -    used is the Windows Registry Key for the time zone which is also the MS
    -    Exchange EWS ID as well, but is different to the Time Zone Name (TZID) and
    -    COD code used by MS Exchange in versions before 2007.
    -
    -    \section2 System Time Zone
    -
    -    QTimeZone does not support any concept of a system or default time zone.
    -    If you require a QDateTime that uses the current system time zone at any
    -    given moment then you should use a Qt::TimeSpec of Qt::LocalTime.
    -
    -    The method systemTimeZoneId() returns the current system IANA time zone
    -    ID which on Unix-like systems will always be correct.  On Windows this ID is
    -    translated from the Windows system ID using an internal translation
    -    table and the user's selected country.  As a consequence there is a small
    -    chance any Windows install may have IDs not known by Qt, in which case
    -    "UTC" will be returned.
    -
    -    Creating a new QTimeZone instance using the system time zone ID will only
    -    produce a fixed named copy of the time zone, it will not change if the
    -    system time zone changes.
    -
    -    \section2 Time Zone Offsets
    -
    -    The difference between UTC and the local time in a time zone is expressed
    -    as an offset in seconds from UTC, i.e. the number of seconds to add to UTC
    -    to obtain the local time.  The total offset is comprised of two component
    -    parts, the standard time offset and the daylight-saving time offset.  The
    -    standard time offset is the number of seconds to add to UTC to obtain
    -    standard time in the time zone.  The daylight-saving time offset is the
    -    number of seconds to add to the standard time offset to obtain
    -    daylight-saving time (abbreviated DST and sometimes called "daylight time"
    -    or "summer time") in the time zone.
    -
    -    Note that the standard and DST offsets for a time zone may change over time
    -    as countries have changed DST laws or even their standard time offset.
    -
    -    \section2 License
    -
    -    This class includes data obtained from the CLDR data files under the terms
    -    of the Unicode Data Files and Software License. See
    -    \l{Unicode Common Locale Data Repository (CLDR)} for details.
    -
    -    \sa QDateTime
    -*/
    -
    -/*!
    -  \enum QTimeZone::anonymous
    -
    -  Sane UTC offsets range from -14 to +14 hours.
    -  No known zone > 12 hrs West of Greenwich (Baker Island, USA).
    -  No known zone > 14 hrs East of Greenwich (Kiritimati, Christmas Island, Kiribati).
    -
    -  \value MinUtcOffsetSecs
    -          -14 * 3600,
    -
    -  \value MaxUtcOffsetSecs
    -          +14 * 3600
    -*/
    -
    -/*!
    -    \enum QTimeZone::TimeType
    -
    -    The type of time zone time, for example when requesting the name.  In time
    -    zones that do not apply DST, all three values may return the same result.
    -
    -    \value StandardTime
    -           The standard time in a time zone, i.e. when Daylight-Saving is not
    -           in effect.
    -           For example when formatting a display name this will show something
    -           like "Pacific Standard Time".
    -    \value DaylightTime
    -           A time when Daylight-Saving is in effect.
    -           For example when formatting a display name this will show something
    -           like "Pacific daylight-saving time".
    -    \value GenericTime
    -           A time which is not specifically Standard or Daylight-Saving time,
    -           either an unknown time or a neutral form.
    -           For example when formatting a display name this will show something
    -           like "Pacific Time".
    -*/
    -
    -/*!
    -    \enum QTimeZone::NameType
    -
    -    The type of time zone name.
    -
    -    \value DefaultName
    -           The default form of the time zone name, e.g. LongName, ShortName or OffsetName
    -    \value LongName
    -           The long form of the time zone name, e.g. "Central European Time"
    -    \value ShortName
    -           The short form of the time zone name, usually an abbreviation, e.g. "CET"
    -    \value OffsetName
    -           The standard ISO offset form of the time zone name, e.g. "UTC+01:00"
    -*/
    -
    -/*!
    -    \class QTimeZone::OffsetData
    -    \inmodule QtCore
    -
    -    The time zone offset data for a given moment in time, i.e. the time zone
    -    offsets and abbreviation to use at that moment in time.
    -
    -    \list
    -    \li OffsetData::atUtc  The datetime of the offset data in UTC time.
    -    \li OffsetData::offsetFromUtc  The total offset from UTC in effect at the datetime.
    -    \li OffsetData::standardTimeOffset  The standard time offset component of the total offset.
    -    \li OffsetData::daylightTimeOffset  The DST offset component of the total offset.
    -    \li OffsetData::abbreviation  The abbreviation in effect at the datetime.
    -    \endlist
    -
    -    For example, for time zone "Europe/Berlin" the OffsetDate in standard and DST might be:
    -
    -    \list
    -    \li atUtc = QDateTime(QDate(2013, 1, 1), QTime(0, 0, 0), Qt::UTC)
    -    \li offsetFromUtc = 3600
    -    \li standardTimeOffset = 3600
    -    \li daylightTimeOffset = 0
    -    \li abbreviation = "CET"
    -    \endlist
    -
    -    \list
    -    \li atUtc = QDateTime(QDate(2013, 6, 1), QTime(0, 0, 0), Qt::UTC)
    -    \li offsetFromUtc = 7200
    -    \li standardTimeOffset = 3600
    -    \li daylightTimeOffset = 3600
    -    \li abbreviation = "CEST"
    -    \endlist
    -*/
    -
    -/*!
    -    \typedef QTimeZone::OffsetDataList
    -
    -    Synonym for QVector.
    -*/
    -
    -/*!
    -    Create a null/invalid time zone instance.
    -*/
    -
    -QTimeZone::QTimeZone() noexcept
    -    : d(0)
    -{
    -}
    -
    -/*!
    -    Creates an instance of the requested time zone \a ianaId.
    -
    -    The ID must be one of the available system IDs otherwise an invalid
    -    time zone will be returned.
    -
    -    \sa availableTimeZoneIds()
    -*/
    -
    -QTimeZone::QTimeZone(const QByteArray &ianaId)
    -{
    -    // Try and see if it's a valid UTC offset ID, just as quick to try create as look-up
    -    d = new QUtcTimeZonePrivate(ianaId);
    -    // If not a valid UTC offset ID then try create it with the system backend
    -    // Relies on backend not creating valid tz with invalid name
    -    if (!d->isValid())
    -        d = newBackendTimeZone(ianaId);
    -}
    -
    -/*!
    -    Creates an instance of a time zone with the requested Offset from UTC of
    -    \a offsetSeconds.
    -
    -    The \a offsetSeconds from UTC must be in the range -14 hours to +14 hours
    -    otherwise an invalid time zone will be returned.
    -*/
    -
    -QTimeZone::QTimeZone(int offsetSeconds)
    -    : d((offsetSeconds >= MinUtcOffsetSecs && offsetSeconds <= MaxUtcOffsetSecs)
    -        ? new QUtcTimeZonePrivate(offsetSeconds) : nullptr)
    -{
    -}
    -
    -/*!
    -    Creates a custom time zone with an ID of \a ianaId and an offset from UTC
    -    of \a offsetSeconds.  The \a name will be the name used by displayName()
    -    for the LongName, the \a abbreviation will be used by displayName() for the
    -    ShortName and by abbreviation(), and the optional \a country will be used
    -    by country().  The \a comment is an optional note that may be displayed in
    -    a GUI to assist users in selecting a time zone.
    -
    -    The \a ianaId must not be one of the available system IDs returned by
    -    availableTimeZoneIds().  The \a offsetSeconds from UTC must be in the range
    -    -14 hours to +14 hours.
    -
    -    If the custom time zone does not have a specific country then set it to the
    -    default value of QLocale::AnyCountry.
    -*/
    -
    -QTimeZone::QTimeZone(const QByteArray &ianaId, int offsetSeconds, const QString &name,
    -                     const QString &abbreviation, QLocale::Country country, const QString &comment)
    -    : d()
    -{
    -    if (!isTimeZoneIdAvailable(ianaId))
    -        d = new QUtcTimeZonePrivate(ianaId, offsetSeconds, name, abbreviation, country, comment);
    -}
    -
    -/*!
    -    \internal
    -
    -    Private. Create time zone with given private backend
    -*/
    -
    -QTimeZone::QTimeZone(QTimeZonePrivate &dd)
    -    : d(&dd)
    -{
    -}
    -
    -/*!
    -    Copy constructor, copy \a other to this.
    -*/
    -
    -QTimeZone::QTimeZone(const QTimeZone &other)
    -    : d(other.d)
    -{
    -}
    -
    -/*!
    -    Destroys the time zone.
    -*/
    -
    -QTimeZone::~QTimeZone()
    -{
    -}
    -
    -/*!
    -    \fn QTimeZone::swap(QTimeZone &other)
    -
    -    Swaps this time zone instance with \a other. This function is very
    -    fast and never fails.
    -*/
    -
    -/*!
    -    Assignment operator, assign \a other to this.
    -*/
    -
    -QTimeZone &QTimeZone::operator=(const QTimeZone &other)
    -{
    -    d = other.d;
    -    return *this;
    -}
    -
    -/*
    -    \fn void QTimeZone::swap(QTimeZone &other)
    -
    -    Swaps this timezone with \a other. This function is very fast and
    -    never fails.
    -*/
    -
    -/*!
    -    \fn QTimeZone &QTimeZone::operator=(QTimeZone &&other)
    -
    -    Move-assigns \a other to this QTimeZone instance, transferring the
    -    ownership of the managed pointer to this instance.
    -*/
    -
    -/*!
    -    Returns \c true if this time zone is equal to the \a other time zone.
    -*/
    -
    -bool QTimeZone::operator==(const QTimeZone &other) const
    -{
    -    if (d && other.d)
    -        return (*d == *other.d);
    -    else
    -        return (d == other.d);
    -}
    -
    -/*!
    -    Returns \c true if this time zone is not equal to the \a other time zone.
    -*/
    -
    -bool QTimeZone::operator!=(const QTimeZone &other) const
    -{
    -    if (d && other.d)
    -        return (*d != *other.d);
    -    else
    -        return (d != other.d);
    -}
    -
    -/*!
    -    Returns \c true if this time zone is valid.
    -*/
    -
    -bool QTimeZone::isValid() const
    -{
    -    if (d)
    -        return d->isValid();
    -    else
    -        return false;
    -}
    -
    -/*!
    -    Returns the IANA ID for the time zone.
    -
    -    IANA IDs are used on all platforms.  On Windows these are translated
    -    from the Windows ID into the closest IANA ID for the time zone and country.
    -*/
    -
    -QByteArray QTimeZone::id() const
    -{
    -    if (d)
    -        return d->id();
    -    else
    -        return QByteArray();
    -}
    -
    -/*!
    -    Returns the country for the time zone.
    -*/
    -
    -QLocale::Country QTimeZone::country() const
    -{
    -    if (isValid())
    -        return d->country();
    -    else
    -        return QLocale::AnyCountry;
    -}
    -
    -/*!
    -    Returns any comment for the time zone.
    -
    -    A comment may be provided by the host platform to assist users in
    -    choosing the correct time zone.  Depending on the platform this may not
    -    be localized.
    -*/
    -
    -QString QTimeZone::comment() const
    -{
    -    if (isValid())
    -        return d->comment();
    -    else
    -        return QString();
    -}
    -
    -/*!
    -    Returns the localized time zone display name at the given \a atDateTime
    -    for the given \a nameType in the given \a locale.  The \a nameType and
    -    \a locale requested may not be supported on all platforms, in which case
    -    the best available option will be returned.
    -
    -    If the \a locale is not provided then the application default locale will
    -    be used.
    -
    -    The display name may change depending on DST or historical events.
    -
    -    \sa abbreviation()
    -*/
    -
    -QString QTimeZone::displayName(const QDateTime &atDateTime, NameType nameType,
    -                               const QLocale &locale) const
    -{
    -    if (isValid())
    -        return d->displayName(atDateTime.toMSecsSinceEpoch(), nameType, locale);
    -    else
    -        return QString();
    -}
    -
    -/*!
    -    Returns the localized time zone display name for the given \a timeType
    -    and \a nameType in the given \a locale. The \a nameType and \a locale
    -    requested may not be supported on all platforms, in which case the best
    -    available option will be returned.
    -
    -    If the \a locale is not provided then the application default locale will
    -    be used.
    -
    -    Where the time zone display names have changed over time then the most
    -    recent names will be used.
    -
    -    \sa abbreviation()
    -*/
    -
    -QString QTimeZone::displayName(TimeType timeType, NameType nameType,
    -                               const QLocale &locale) const
    -{
    -    if (isValid())
    -        return d->displayName(timeType, nameType, locale);
    -    else
    -        return QString();
    -}
    -
    -/*!
    -    Returns the time zone abbreviation at the given \a atDateTime.  The
    -    abbreviation may change depending on DST or even historical events.
    -
    -    Note that the abbreviation is not guaranteed to be unique to this time zone
    -    and should not be used in place of the ID or display name.
    -
    -    \sa displayName()
    -*/
    -
    -QString QTimeZone::abbreviation(const QDateTime &atDateTime) const
    -{
    -    if (isValid())
    -        return d->abbreviation(atDateTime.toMSecsSinceEpoch());
    -    else
    -        return QString();
    -}
    -
    -/*!
    -    Returns the total effective offset at the given \a atDateTime, i.e. the
    -    number of seconds to add to UTC to obtain the local time.  This includes
    -    any DST offset that may be in effect, i.e. it is the sum of
    -    standardTimeOffset() and daylightTimeOffset() for the given datetime.
    -
    -    For example, for the time zone "Europe/Berlin" the standard time offset is
    -    +3600 seconds and the DST offset is +3600 seconds.  During standard time
    -    offsetFromUtc() will return +3600 (UTC+01:00), and during DST it will
    -    return +7200 (UTC+02:00).
    -
    -    \sa standardTimeOffset(), daylightTimeOffset()
    -*/
    -
    -int QTimeZone::offsetFromUtc(const QDateTime &atDateTime) const
    -{
    -    if (isValid())
    -        return d->offsetFromUtc(atDateTime.toMSecsSinceEpoch());
    -    else
    -        return 0;
    -}
    -
    -/*!
    -    Returns the standard time offset at the given \a atDateTime, i.e. the
    -    number of seconds to add to UTC to obtain the local Standard Time.  This
    -    excludes any DST offset that may be in effect.
    -
    -    For example, for the time zone "Europe/Berlin" the standard time offset is
    -    +3600 seconds.  During both standard and DST offsetFromUtc() will return
    -    +3600 (UTC+01:00).
    -
    -    \sa offsetFromUtc(), daylightTimeOffset()
    -*/
    -
    -int QTimeZone::standardTimeOffset(const QDateTime &atDateTime) const
    -{
    -    if (isValid())
    -        return d->standardTimeOffset(atDateTime.toMSecsSinceEpoch());
    -    else
    -        return 0;
    -}
    -
    -/*!
    -    Returns the daylight-saving time offset at the given \a atDateTime,
    -    i.e. the number of seconds to add to the standard time offset to obtain the
    -    local daylight-saving time.
    -
    -    For example, for the time zone "Europe/Berlin" the DST offset is +3600
    -    seconds.  During standard time daylightTimeOffset() will return 0, and when
    -    daylight-saving is in effect it will return +3600.
    -
    -    \sa offsetFromUtc(), standardTimeOffset()
    -*/
    -
    -int QTimeZone::daylightTimeOffset(const QDateTime &atDateTime) const
    -{
    -    if (hasDaylightTime())
    -        return d->daylightTimeOffset(atDateTime.toMSecsSinceEpoch());
    -    else
    -        return 0;
    -}
    -
    -/*!
    -    Returns \c true if the time zone has practiced daylight-saving at any time.
    -
    -    \sa isDaylightTime(), daylightTimeOffset()
    -*/
    -
    -bool QTimeZone::hasDaylightTime() const
    -{
    -    if (isValid())
    -        return d->hasDaylightTime();
    -    else
    -        return false;
    -}
    -
    -/*!
    -    Returns \c true if daylight-saving was in effect at the given \a atDateTime.
    -
    -    \sa hasDaylightTime(), daylightTimeOffset()
    -*/
    -
    -bool QTimeZone::isDaylightTime(const QDateTime &atDateTime) const
    -{
    -    if (hasDaylightTime())
    -        return d->isDaylightTime(atDateTime.toMSecsSinceEpoch());
    -    else
    -        return false;
    -}
    -
    -/*!
    -    Returns the effective offset details at the given \a forDateTime. This is
    -    the equivalent of calling offsetFromUtc(), abbreviation(), etc individually but is
    -    more efficient.
    -
    -    \sa offsetFromUtc(), standardTimeOffset(), daylightTimeOffset(), abbreviation()
    -*/
    -
    -QTimeZone::OffsetData QTimeZone::offsetData(const QDateTime &forDateTime) const
    -{
    -    if (hasTransitions())
    -        return QTimeZonePrivate::toOffsetData(d->data(forDateTime.toMSecsSinceEpoch()));
    -    else
    -        return QTimeZonePrivate::invalidOffsetData();
    -}
    -
    -/*!
    -    Returns \c true if the system backend supports obtaining transitions.
    -
    -    Transitions are changes in the time-zone: these happen when DST turns on or
    -    off and when authorities alter the offsets for the time-zone.
    -
    -    \sa nextTransition(), previousTransition(), transitions()
    -*/
    -
    -bool QTimeZone::hasTransitions() const
    -{
    -    if (isValid())
    -        return d->hasTransitions();
    -    else
    -        return false;
    -}
    -
    -/*!
    -    Returns the first time zone Transition after the given \a afterDateTime.
    -    This is most useful when you have a Transition time and wish to find the
    -    Transition after it.
    -
    -    If there is no transition after the given \a afterDateTime then an invalid
    -    OffsetData will be returned with an invalid QDateTime.
    -
    -    The given \a afterDateTime is exclusive.
    -
    -    \sa hasTransitions(), previousTransition(), transitions()
    -*/
    -
    -QTimeZone::OffsetData QTimeZone::nextTransition(const QDateTime &afterDateTime) const
    -{
    -    if (hasTransitions())
    -        return QTimeZonePrivate::toOffsetData(d->nextTransition(afterDateTime.toMSecsSinceEpoch()));
    -    else
    -        return QTimeZonePrivate::invalidOffsetData();
    -}
    -
    -/*!
    -    Returns the first time zone Transition before the given \a beforeDateTime.
    -    This is most useful when you have a Transition time and wish to find the
    -    Transition before it.
    -
    -    If there is no transition before the given \a beforeDateTime then an invalid
    -    OffsetData will be returned with an invalid QDateTime.
    -
    -    The given \a beforeDateTime is exclusive.
    -
    -    \sa hasTransitions(), nextTransition(), transitions()
    -*/
    -
    -QTimeZone::OffsetData QTimeZone::previousTransition(const QDateTime &beforeDateTime) const
    -{
    -    if (hasTransitions())
    -        return QTimeZonePrivate::toOffsetData(d->previousTransition(beforeDateTime.toMSecsSinceEpoch()));
    -    else
    -        return QTimeZonePrivate::invalidOffsetData();
    -}
    -
    -/*!
    -    Returns a list of all time zone transitions between the given datetimes.
    -
    -    The given \a fromDateTime and \a toDateTime are inclusive.
    -
    -    \sa hasTransitions(), nextTransition(), previousTransition()
    -*/
    -
    -QTimeZone::OffsetDataList QTimeZone::transitions(const QDateTime &fromDateTime,
    -                                                 const QDateTime &toDateTime) const
    -{
    -    OffsetDataList list;
    -    if (hasTransitions()) {
    -        const QTimeZonePrivate::DataList plist = d->transitions(fromDateTime.toMSecsSinceEpoch(),
    -                                                                toDateTime.toMSecsSinceEpoch());
    -        list.reserve(plist.count());
    -        for (const QTimeZonePrivate::Data &pdata : plist)
    -            list.append(QTimeZonePrivate::toOffsetData(pdata));
    -    }
    -    return list;
    -}
    -
    -// Static methods
    -
    -/*!
    -    Returns the current system time zone IANA ID.
    -
    -    On Windows this ID is translated from the Windows ID using an internal
    -    translation table and the user's selected country.  As a consequence there
    -    is a small chance any Windows install may have IDs not known by Qt, in
    -    which case "UTC" will be returned.
    -*/
    -
    -QByteArray QTimeZone::systemTimeZoneId()
    -{
    -    return global_tz->backend->systemTimeZoneId();
    -}
    -
    -/*!
    -    \since 5.5
    -    Returns a QTimeZone object that refers to the local system time, as
    -    specified by systemTimeZoneId().
    -
    -    \sa utc()
    -*/
    -QTimeZone QTimeZone::systemTimeZone()
    -{
    -    return QTimeZone(QTimeZone::systemTimeZoneId());
    -}
    -
    -/*!
    -    \since 5.5
    -    Returns a QTimeZone object that refers to UTC (Universal Time Coordinated).
    -
    -    \sa systemTimeZone()
    -*/
    -QTimeZone QTimeZone::utc()
    -{
    -    return QTimeZone(QTimeZonePrivate::utcQByteArray());
    -}
    -
    -/*!
    -    Returns \c true if a given time zone \a ianaId is available on this system.
    -
    -    \sa availableTimeZoneIds()
    -*/
    -
    -bool QTimeZone::isTimeZoneIdAvailable(const QByteArray &ianaId)
    -{
    -    // isValidId is not strictly required, but faster to weed out invalid
    -    // IDs as availableTimeZoneIds() may be slow
    -    if (!QTimeZonePrivate::isValidId(ianaId))
    -        return false;
    -    return QUtcTimeZonePrivate().isTimeZoneIdAvailable(ianaId) ||
    -           global_tz->backend->isTimeZoneIdAvailable(ianaId);
    -}
    -
    -static QList set_union(const QList &l1, const QList &l2)
    -{
    -    QList result;
    -    result.reserve(l1.size() + l2.size());
    -    std::set_union(l1.begin(), l1.end(),
    -                   l2.begin(), l2.end(),
    -                   std::back_inserter(result));
    -    return result;
    -}
    -
    -/*!
    -    Returns a list of all available IANA time zone IDs on this system.
    -
    -    \sa isTimeZoneIdAvailable()
    -*/
    -
    -QList QTimeZone::availableTimeZoneIds()
    -{
    -    return set_union(QUtcTimeZonePrivate().availableTimeZoneIds(),
    -                     global_tz->backend->availableTimeZoneIds());
    -}
    -
    -/*!
    -    Returns a list of all available IANA time zone IDs for a given \a country.
    -
    -    As a special case, a \a country of Qt::AnyCountry returns those time zones
    -    that do not have any country related to them, such as UTC.  If you require
    -    a list of all time zone IDs for all countries then use the standard
    -    availableTimeZoneIds() method.
    -
    -    \sa isTimeZoneIdAvailable()
    -*/
    -
    -QList QTimeZone::availableTimeZoneIds(QLocale::Country country)
    -{
    -    return set_union(QUtcTimeZonePrivate().availableTimeZoneIds(country),
    -                     global_tz->backend->availableTimeZoneIds(country));
    -}
    -
    -/*!
    -    Returns a list of all available IANA time zone IDs with a given standard
    -    time offset of \a offsetSeconds.
    -
    -    \sa isTimeZoneIdAvailable()
    -*/
    -
    -QList QTimeZone::availableTimeZoneIds(int offsetSeconds)
    -{
    -    return set_union(QUtcTimeZonePrivate().availableTimeZoneIds(offsetSeconds),
    -                     global_tz->backend->availableTimeZoneIds(offsetSeconds));
    -}
    -
    -/*!
    -    Returns the Windows ID equivalent to the given \a ianaId.
    -
    -    \sa windowsIdToDefaultIanaId(), windowsIdToIanaIds()
    -*/
    -
    -QByteArray QTimeZone::ianaIdToWindowsId(const QByteArray &ianaId)
    -{
    -    return QTimeZonePrivate::ianaIdToWindowsId(ianaId);
    -}
    -
    -/*!
    -    Returns the default IANA ID for a given \a windowsId.
    -
    -    Because a Windows ID can cover several IANA IDs in several different
    -    countries, this function returns the most frequently used IANA ID with no
    -    regard for the country and should thus be used with care.  It is usually
    -    best to request the default for a specific country.
    -
    -    \sa ianaIdToWindowsId(), windowsIdToIanaIds()
    -*/
    -
    -QByteArray QTimeZone::windowsIdToDefaultIanaId(const QByteArray &windowsId)
    -{
    -    return QTimeZonePrivate::windowsIdToDefaultIanaId(windowsId);
    -}
    -
    -/*!
    -    Returns the default IANA ID for a given \a windowsId and \a country.
    -
    -    Because a Windows ID can cover several IANA IDs within a given country,
    -    the most frequently used IANA ID in that country is returned.
    -
    -    As a special case, QLocale::AnyCountry returns the default of those IANA IDs
    -    that do not have any specific country.
    -
    -    \sa ianaIdToWindowsId(), windowsIdToIanaIds()
    -*/
    -
    -QByteArray QTimeZone::windowsIdToDefaultIanaId(const QByteArray &windowsId,
    -                                                QLocale::Country country)
    -{
    -    return QTimeZonePrivate::windowsIdToDefaultIanaId(windowsId, country);
    -}
    -
    -/*!
    -    Returns all the IANA IDs for a given \a windowsId.
    -
    -    The returned list is sorted alphabetically.
    -
    -    \sa ianaIdToWindowsId(), windowsIdToDefaultIanaId()
    -*/
    -
    -QList QTimeZone::windowsIdToIanaIds(const QByteArray &windowsId)
    -{
    -    return QTimeZonePrivate::windowsIdToIanaIds(windowsId);
    -}
    -
    -/*!
    -    Returns all the IANA IDs for a given \a windowsId and \a country.
    -
    -    As a special case QLocale::AnyCountry returns those IANA IDs that do
    -    not have any specific country.
    -
    -    The returned list is in order of frequency of usage, i.e. larger zones
    -    within a country are listed first.
    -
    -    \sa ianaIdToWindowsId(), windowsIdToDefaultIanaId()
    -*/
    -
    -QList QTimeZone::windowsIdToIanaIds(const QByteArray &windowsId,
    -                                                    QLocale::Country country)
    -{
    -    return QTimeZonePrivate::windowsIdToIanaIds(windowsId, country);
    -}
    -
    -#ifndef QT_NO_DATASTREAM
    -QDataStream &operator<<(QDataStream &ds, const QTimeZone &tz)
    -{
    -    tz.d->serialize(ds);
    -    return ds;
    -}
    -
    -QDataStream &operator>>(QDataStream &ds, QTimeZone &tz)
    -{
    -    QString ianaId;
    -    ds >> ianaId;
    -    if (ianaId == QLatin1String("OffsetFromUtc")) {
    -        int utcOffset;
    -        QString name;
    -        QString abbreviation;
    -        int country;
    -        QString comment;
    -        ds >> ianaId >> utcOffset >> name >> abbreviation >> country >> comment;
    -        // Try creating as a system timezone, which succeeds (producing a valid
    -        // zone) iff ianaId is valid; we can then ignore the other data.
    -        tz = QTimeZone(ianaId.toUtf8());
    -        // If not, then construct a custom timezone using all the saved values:
    -        if (!tz.isValid())
    -            tz = QTimeZone(ianaId.toUtf8(), utcOffset, name, abbreviation,
    -                           QLocale::Country(country), comment);
    -    } else {
    -        tz = QTimeZone(ianaId.toUtf8());
    -    }
    -    return ds;
    -}
    -#endif // QT_NO_DATASTREAM
    -
    -#ifndef QT_NO_DEBUG_STREAM
    -QDebug operator<<(QDebug dbg, const QTimeZone &tz)
    -{
    -    QDebugStateSaver saver(dbg);
    -    //TODO Include backend and data version details?
    -    dbg.nospace() << "QTimeZone(" << QString::fromUtf8(tz.id()) << ')';
    -    return dbg;
    -}
    -#endif
    -
    -QT_END_NAMESPACE
    diff --git a/src/corelib/tools/qtimezone.h b/src/corelib/tools/qtimezone.h
    deleted file mode 100644
    index 62ecee49bb..0000000000
    --- a/src/corelib/tools/qtimezone.h
    +++ /dev/null
    @@ -1,188 +0,0 @@
    -/****************************************************************************
    -**
    -** Copyright (C) 2013 John Layt 
    -** Contact: https://www.qt.io/licensing/
    -**
    -** This file is part of the QtCore module of the Qt Toolkit.
    -**
    -** $QT_BEGIN_LICENSE:LGPL$
    -** Commercial License Usage
    -** Licensees holding valid commercial Qt licenses may use this file in
    -** accordance with the commercial license agreement provided with the
    -** Software or, alternatively, in accordance with the terms contained in
    -** a written agreement between you and The Qt Company. For licensing terms
    -** and conditions see https://www.qt.io/terms-conditions. For further
    -** information use the contact form at https://www.qt.io/contact-us.
    -**
    -** GNU Lesser General Public License Usage
    -** Alternatively, this file may be used under the terms of the GNU Lesser
    -** General Public License version 3 as published by the Free Software
    -** Foundation and appearing in the file LICENSE.LGPL3 included in the
    -** packaging of this file. Please review the following information to
    -** ensure the GNU Lesser General Public License version 3 requirements
    -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
    -**
    -** GNU General Public License Usage
    -** Alternatively, this file may be used under the terms of the GNU
    -** General Public License version 2.0 or (at your option) the GNU General
    -** Public license version 3 or any later version approved by the KDE Free
    -** Qt Foundation. The licenses are as published by the Free Software
    -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
    -** included in the packaging of this file. Please review the following
    -** information to ensure the GNU General Public License requirements will
    -** be met: https://www.gnu.org/licenses/gpl-2.0.html and
    -** https://www.gnu.org/licenses/gpl-3.0.html.
    -**
    -** $QT_END_LICENSE$
    -**
    -****************************************************************************/
    -
    -
    -#ifndef QTIMEZONE_H
    -#define QTIMEZONE_H
    -
    -#include 
    -#include 
    -#include 
    -
    -QT_REQUIRE_CONFIG(timezone);
    -
    -#if (defined(Q_OS_DARWIN) || defined(Q_QDOC)) && !defined(QT_NO_SYSTEMLOCALE)
    -Q_FORWARD_DECLARE_CF_TYPE(CFTimeZone);
    -Q_FORWARD_DECLARE_OBJC_CLASS(NSTimeZone);
    -#endif
    -
    -QT_BEGIN_NAMESPACE
    -
    -class QTimeZonePrivate;
    -
    -class Q_CORE_EXPORT QTimeZone
    -{
    -public:
    -    // Sane UTC offsets range from -14 to +14 hours:
    -    enum {
    -        // No known zone > 12 hrs West of Greenwich (Baker Island, USA)
    -        MinUtcOffsetSecs = -14 * 3600,
    -        // No known zone > 14 hrs East of Greenwich (Kiritimati, Christmas Island, Kiribati)
    -        MaxUtcOffsetSecs = +14 * 3600
    -    };
    -
    -    enum TimeType {
    -        StandardTime = 0,
    -        DaylightTime = 1,
    -        GenericTime = 2
    -    };
    -
    -    enum NameType {
    -        DefaultName = 0,
    -        LongName = 1,
    -        ShortName = 2,
    -        OffsetName = 3
    -    };
    -
    -    struct OffsetData {
    -        QString abbreviation;
    -        QDateTime atUtc;
    -        int offsetFromUtc;
    -        int standardTimeOffset;
    -        int daylightTimeOffset;
    -    };
    -    typedef QVector OffsetDataList;
    -
    -    QTimeZone() noexcept;
    -    explicit QTimeZone(const QByteArray &ianaId);
    -    explicit QTimeZone(int offsetSeconds);
    -    /*implicit*/ QTimeZone(const QByteArray &zoneId, int offsetSeconds, const QString &name,
    -              const QString &abbreviation, QLocale::Country country = QLocale::AnyCountry,
    -              const QString &comment = QString());
    -    QTimeZone(const QTimeZone &other);
    -    ~QTimeZone();
    -
    -    QTimeZone &operator=(const QTimeZone &other);
    -    QTimeZone &operator=(QTimeZone &&other) noexcept { swap(other); return *this; }
    -
    -    void swap(QTimeZone &other) noexcept
    -    { d.swap(other.d); }
    -
    -    bool operator==(const QTimeZone &other) const;
    -    bool operator!=(const QTimeZone &other) const;
    -
    -    bool isValid() const;
    -
    -    QByteArray id() const;
    -    QLocale::Country country() const;
    -    QString comment() const;
    -
    -    QString displayName(const QDateTime &atDateTime,
    -                        QTimeZone::NameType nameType = QTimeZone::DefaultName,
    -                        const QLocale &locale = QLocale()) const;
    -    QString displayName(QTimeZone::TimeType timeType,
    -                        QTimeZone::NameType nameType = QTimeZone::DefaultName,
    -                        const QLocale &locale = QLocale()) const;
    -    QString abbreviation(const QDateTime &atDateTime) const;
    -
    -    int offsetFromUtc(const QDateTime &atDateTime) const;
    -    int standardTimeOffset(const QDateTime &atDateTime) const;
    -    int daylightTimeOffset(const QDateTime &atDateTime) const;
    -
    -    bool hasDaylightTime() const;
    -    bool isDaylightTime(const QDateTime &atDateTime) const;
    -
    -    OffsetData offsetData(const QDateTime &forDateTime) const;
    -
    -    bool hasTransitions() const;
    -    OffsetData nextTransition(const QDateTime &afterDateTime) const;
    -    OffsetData previousTransition(const QDateTime &beforeDateTime) const;
    -    OffsetDataList transitions(const QDateTime &fromDateTime, const QDateTime &toDateTime) const;
    -
    -    static QByteArray systemTimeZoneId();
    -    static QTimeZone systemTimeZone();
    -    static QTimeZone utc();
    -
    -    static bool isTimeZoneIdAvailable(const QByteArray &ianaId);
    -
    -    static QList availableTimeZoneIds();
    -    static QList availableTimeZoneIds(QLocale::Country country);
    -    static QList availableTimeZoneIds(int offsetSeconds);
    -
    -    static QByteArray ianaIdToWindowsId(const QByteArray &ianaId);
    -    static QByteArray windowsIdToDefaultIanaId(const QByteArray &windowsId);
    -    static QByteArray windowsIdToDefaultIanaId(const QByteArray &windowsId,
    -                                                QLocale::Country country);
    -    static QList windowsIdToIanaIds(const QByteArray &windowsId);
    -    static QList windowsIdToIanaIds(const QByteArray &windowsId,
    -                                                 QLocale::Country country);
    -
    -#if (defined(Q_OS_DARWIN) || defined(Q_QDOC)) && !defined(QT_NO_SYSTEMLOCALE)
    -    static QTimeZone fromCFTimeZone(CFTimeZoneRef timeZone);
    -    CFTimeZoneRef toCFTimeZone() const Q_DECL_CF_RETURNS_RETAINED;
    -    static QTimeZone fromNSTimeZone(const NSTimeZone *timeZone);
    -    NSTimeZone *toNSTimeZone() const Q_DECL_NS_RETURNS_AUTORELEASED;
    -#endif
    -
    -private:
    -    QTimeZone(QTimeZonePrivate &dd);
    -#ifndef QT_NO_DATASTREAM
    -    friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &ds, const QTimeZone &tz);
    -#endif
    -    friend class QTimeZonePrivate;
    -    friend class QDateTime;
    -    friend class QDateTimePrivate;
    -    QSharedDataPointer d;
    -};
    -
    -Q_DECLARE_TYPEINFO(QTimeZone::OffsetData, Q_MOVABLE_TYPE);
    -Q_DECLARE_SHARED(QTimeZone)
    -
    -#ifndef QT_NO_DATASTREAM
    -Q_CORE_EXPORT QDataStream &operator<<(QDataStream &ds, const QTimeZone &tz);
    -Q_CORE_EXPORT QDataStream &operator>>(QDataStream &ds, QTimeZone &tz);
    -#endif
    -
    -#ifndef QT_NO_DEBUG_STREAM
    -Q_CORE_EXPORT QDebug operator<<(QDebug dbg, const QTimeZone &tz);
    -#endif
    -
    -QT_END_NAMESPACE
    -
    -#endif // QTIMEZONE_H
    diff --git a/src/corelib/tools/qtimezoneprivate.cpp b/src/corelib/tools/qtimezoneprivate.cpp
    deleted file mode 100644
    index 569b343187..0000000000
    --- a/src/corelib/tools/qtimezoneprivate.cpp
    +++ /dev/null
    @@ -1,926 +0,0 @@
    -/****************************************************************************
    -**
    -** Copyright (C) 2013 John Layt 
    -** Contact: https://www.qt.io/licensing/
    -**
    -** This file is part of the QtCore module of the Qt Toolkit.
    -**
    -** $QT_BEGIN_LICENSE:LGPL$
    -** Commercial License Usage
    -** Licensees holding valid commercial Qt licenses may use this file in
    -** accordance with the commercial license agreement provided with the
    -** Software or, alternatively, in accordance with the terms contained in
    -** a written agreement between you and The Qt Company. For licensing terms
    -** and conditions see https://www.qt.io/terms-conditions. For further
    -** information use the contact form at https://www.qt.io/contact-us.
    -**
    -** GNU Lesser General Public License Usage
    -** Alternatively, this file may be used under the terms of the GNU Lesser
    -** General Public License version 3 as published by the Free Software
    -** Foundation and appearing in the file LICENSE.LGPL3 included in the
    -** packaging of this file. Please review the following information to
    -** ensure the GNU Lesser General Public License version 3 requirements
    -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
    -**
    -** GNU General Public License Usage
    -** Alternatively, this file may be used under the terms of the GNU
    -** General Public License version 2.0 or (at your option) the GNU General
    -** Public license version 3 or any later version approved by the KDE Free
    -** Qt Foundation. The licenses are as published by the Free Software
    -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
    -** included in the packaging of this file. Please review the following
    -** information to ensure the GNU General Public License requirements will
    -** be met: https://www.gnu.org/licenses/gpl-2.0.html and
    -** https://www.gnu.org/licenses/gpl-3.0.html.
    -**
    -** $QT_END_LICENSE$
    -**
    -****************************************************************************/
    -
    -
    -#include "qtimezone.h"
    -#include "qtimezoneprivate_p.h"
    -#include "qtimezoneprivate_data_p.h"
    -
    -#include 
    -#include 
    -
    -#include 
    -
    -QT_BEGIN_NAMESPACE
    -
    -/*
    -    Static utilities for looking up Windows ID tables
    -*/
    -
    -static const int windowsDataTableSize = sizeof(windowsDataTable) / sizeof(QWindowsData) - 1;
    -static const int zoneDataTableSize = sizeof(zoneDataTable) / sizeof(QZoneData) - 1;
    -static const int utcDataTableSize = sizeof(utcDataTable) / sizeof(QUtcData) - 1;
    -
    -
    -static const QZoneData *zoneData(quint16 index)
    -{
    -    Q_ASSERT(index < zoneDataTableSize);
    -    return &zoneDataTable[index];
    -}
    -
    -static const QWindowsData *windowsData(quint16 index)
    -{
    -    Q_ASSERT(index < windowsDataTableSize);
    -    return &windowsDataTable[index];
    -}
    -
    -static const QUtcData *utcData(quint16 index)
    -{
    -    Q_ASSERT(index < utcDataTableSize);
    -    return &utcDataTable[index];
    -}
    -
    -// Return the Windows ID literal for a given QWindowsData
    -static QByteArray windowsId(const QWindowsData *windowsData)
    -{
    -    return (windowsIdData + windowsData->windowsIdIndex);
    -}
    -
    -// Return the IANA ID literal for a given QWindowsData
    -static QByteArray ianaId(const QWindowsData *windowsData)
    -{
    -    return (ianaIdData + windowsData->ianaIdIndex);
    -}
    -
    -// Return the IANA ID literal for a given QZoneData
    -static QByteArray ianaId(const QZoneData *zoneData)
    -{
    -    return (ianaIdData + zoneData->ianaIdIndex);
    -}
    -
    -static QByteArray utcId(const QUtcData *utcData)
    -{
    -    return (ianaIdData + utcData->ianaIdIndex);
    -}
    -
    -static quint16 toWindowsIdKey(const QByteArray &winId)
    -{
    -    for (quint16 i = 0; i < windowsDataTableSize; ++i) {
    -        const QWindowsData *data = windowsData(i);
    -        if (windowsId(data) == winId)
    -            return data->windowsIdKey;
    -    }
    -    return 0;
    -}
    -
    -static QByteArray toWindowsIdLiteral(quint16 windowsIdKey)
    -{
    -    for (quint16 i = 0; i < windowsDataTableSize; ++i) {
    -        const QWindowsData *data = windowsData(i);
    -        if (data->windowsIdKey == windowsIdKey)
    -            return windowsId(data);
    -    }
    -    return QByteArray();
    -}
    -
    -/*
    -    Base class implementing common utility routines, only intantiate for a null tz.
    -*/
    -
    -QTimeZonePrivate::QTimeZonePrivate()
    -{
    -}
    -
    -QTimeZonePrivate::QTimeZonePrivate(const QTimeZonePrivate &other)
    -    : QSharedData(other), m_id(other.m_id)
    -{
    -}
    -
    -QTimeZonePrivate::~QTimeZonePrivate()
    -{
    -}
    -
    -QTimeZonePrivate *QTimeZonePrivate::clone() const
    -{
    -    return new QTimeZonePrivate(*this);
    -}
    -
    -bool QTimeZonePrivate::operator==(const QTimeZonePrivate &other) const
    -{
    -    // TODO Too simple, but need to solve problem of comparing different derived classes
    -    // Should work for all System and ICU classes as names guaranteed unique, but not for Simple.
    -    // Perhaps once all classes have working transitions can compare full list?
    -    return (m_id == other.m_id);
    -}
    -
    -bool QTimeZonePrivate::operator!=(const QTimeZonePrivate &other) const
    -{
    -    return !(*this == other);
    -}
    -
    -bool QTimeZonePrivate::isValid() const
    -{
    -    return !m_id.isEmpty();
    -}
    -
    -QByteArray QTimeZonePrivate::id() const
    -{
    -    return m_id;
    -}
    -
    -QLocale::Country QTimeZonePrivate::country() const
    -{
    -    // Default fall-back mode, use the zoneTable to find Region of known Zones
    -    for (int i = 0; i < zoneDataTableSize; ++i) {
    -        const QZoneData *data = zoneData(i);
    -        if (ianaId(data).split(' ').contains(m_id))
    -            return (QLocale::Country)data->country;
    -    }
    -    return QLocale::AnyCountry;
    -}
    -
    -QString QTimeZonePrivate::comment() const
    -{
    -    return QString();
    -}
    -
    -QString QTimeZonePrivate::displayName(qint64 atMSecsSinceEpoch,
    -                                      QTimeZone::NameType nameType,
    -                                      const QLocale &locale) const
    -{
    -    if (nameType == QTimeZone::OffsetName)
    -        return isoOffsetFormat(offsetFromUtc(atMSecsSinceEpoch));
    -
    -    if (isDaylightTime(atMSecsSinceEpoch))
    -        return displayName(QTimeZone::DaylightTime, nameType, locale);
    -    else
    -        return displayName(QTimeZone::StandardTime, nameType, locale);
    -}
    -
    -QString QTimeZonePrivate::displayName(QTimeZone::TimeType timeType,
    -                                      QTimeZone::NameType nameType,
    -                                      const QLocale &locale) const
    -{
    -    Q_UNUSED(timeType)
    -    Q_UNUSED(nameType)
    -    Q_UNUSED(locale)
    -    return QString();
    -}
    -
    -QString QTimeZonePrivate::abbreviation(qint64 atMSecsSinceEpoch) const
    -{
    -    Q_UNUSED(atMSecsSinceEpoch)
    -    return QString();
    -}
    -
    -int QTimeZonePrivate::offsetFromUtc(qint64 atMSecsSinceEpoch) const
    -{
    -    return standardTimeOffset(atMSecsSinceEpoch) + daylightTimeOffset(atMSecsSinceEpoch);
    -}
    -
    -int QTimeZonePrivate::standardTimeOffset(qint64 atMSecsSinceEpoch) const
    -{
    -    Q_UNUSED(atMSecsSinceEpoch)
    -    return invalidSeconds();
    -}
    -
    -int QTimeZonePrivate::daylightTimeOffset(qint64 atMSecsSinceEpoch) const
    -{
    -    Q_UNUSED(atMSecsSinceEpoch)
    -    return invalidSeconds();
    -}
    -
    -bool QTimeZonePrivate::hasDaylightTime() const
    -{
    -    return false;
    -}
    -
    -bool QTimeZonePrivate::isDaylightTime(qint64 atMSecsSinceEpoch) const
    -{
    -    Q_UNUSED(atMSecsSinceEpoch)
    -    return false;
    -}
    -
    -QTimeZonePrivate::Data QTimeZonePrivate::data(qint64 forMSecsSinceEpoch) const
    -{
    -    Q_UNUSED(forMSecsSinceEpoch)
    -    return invalidData();
    -}
    -
    -// Private only method for use by QDateTime to convert local msecs to epoch msecs
    -QTimeZonePrivate::Data QTimeZonePrivate::dataForLocalTime(qint64 forLocalMSecs, int hint) const
    -{
    -    if (!hasDaylightTime()) // No DST means same offset for all local msecs
    -        return data(forLocalMSecs - standardTimeOffset(forLocalMSecs) * 1000);
    -
    -    /*
    -      We need a UTC time at which to ask for the offset, in order to be able to
    -      add that offset to forLocalMSecs, to get the UTC time we
    -      need. Fortunately, no time-zone offset is more than 14 hours; and DST
    -      transitions happen (much) more than thirty-two hours apart.  So sampling
    -      offset sixteen hours each side gives us information we can be sure
    -      brackets the correct time and at most one DST transition.
    -    */
    -    const qint64 sixteenHoursInMSecs(16 * 3600 * 1000);
    -    Q_STATIC_ASSERT(-sixteenHoursInMSecs / 1000 < QTimeZone::MinUtcOffsetSecs
    -                  && sixteenHoursInMSecs / 1000 > QTimeZone::MaxUtcOffsetSecs);
    -    const qint64 recent = forLocalMSecs - sixteenHoursInMSecs;
    -    const qint64 imminent = forLocalMSecs + sixteenHoursInMSecs;
    -    /*
    -      Offsets are Local - UTC, positive to the east of Greenwich, negative to
    -      the west; DST offset always exceeds standard offset, when DST applies.
    -      When we have offsets on either side of a transition, the lower one is
    -      standard, the higher is DST.
    -
    -      Non-DST transitions (jurisdictions changing time-zone and time-zones
    -      changing their standard offset, typically) are described below as if they
    -      were DST transitions (since these are more usual and familiar); the code
    -      mostly concerns itself with offsets from UTC, described in terms of the
    -      common case for changes in that.  If there is no actual change in offset
    -      (e.g. a DST transition cancelled by a standard offset change), this code
    -      should handle it gracefully; without transitions, it'll see early == late
    -      and take the easy path; with transitions, tran and nextTran get the
    -      correct UTC time as atMSecsSinceEpoch so comparing to nextStart selects
    -      the right one.  In all other cases, the transition changes offset and the
    -      reasoning that applies to DST applies just the same.  Aside from hinting,
    -      the only thing that looks at DST-ness at all, other than inferred from
    -      offset changes, is the case without transition data handling an invalid
    -      time in the gap that a transition passed over.
    -
    -      The handling of hint (see below) is apt to go wrong in non-DST
    -      transitions.  There isn't really a great deal we can hope to do about that
    -      without adding yet more unreliable complexity to the heuristics in use for
    -      already obscure corner-cases.
    -     */
    -
    -    /*
    -      The hint (really a QDateTimePrivate::DaylightStatus) is > 0 if caller
    -      thinks we're in DST, 0 if in standard.  A value of -2 means never-DST, so
    -      should have been handled above; if it slips through, it's wrong but we
    -      should probably treat it as standard anyway (never-DST means
    -      always-standard, after all).  If the hint turns out to be wrong, fall back
    -      on trying the other possibility: which makes it harmless to treat -1
    -      (meaning unknown) as standard (i.e. try standard first, then try DST).  In
    -      practice, away from a transition, the only difference hint makes is to
    -      which candidate we try first: if the hint is wrong (or unknown and
    -      standard fails), we'll try the other candidate and it'll work.
    -
    -      For the obscure (and invalid) case where forLocalMSecs falls in a
    -      spring-forward's missing hour, a common case is that we started with a
    -      date/time for which the hint was valid and adjusted it naively; for that
    -      case, we should correct the adjustment by shunting across the transition
    -      into where hint is wrong.  So half-way through the gap, arrived at from
    -      the DST side, should be read as an hour earlier, in standard time; but, if
    -      arrived at from the standard side, should be read as an hour later, in
    -      DST.  (This shall be wrong in some cases; for example, when a country
    -      changes its transition dates and changing a date/time by more than six
    -      months lands it on a transition.  However, these cases are even more
    -      obscure than those where the heuristic is good.)
    -     */
    -
    -    if (hasTransitions()) {
    -        /*
    -          We have transitions.
    -
    -          Each transition gives the offsets to use until the next; so we need the
    -          most recent transition before the time forLocalMSecs describes.  If it
    -          describes a time *in* a transition, we'll need both that transition and
    -          the one before it.  So find one transition that's probably after (and not
    -          much before, otherwise) and another that's definitely before, then work
    -          out which one to use.  When both or neither work on forLocalMSecs, use
    -          hint to disambiguate.
    -        */
    -
    -        // Get a transition definitely before the local MSecs; usually all we need.
    -        // Only around the transition times might we need another.
    -        Data tran = previousTransition(recent);
    -        Q_ASSERT(forLocalMSecs < 0 || // Pre-epoch TZ info may be unavailable
    -                 forLocalMSecs - tran.offsetFromUtc * 1000 >= tran.atMSecsSinceEpoch);
    -        Data nextTran = nextTransition(tran.atMSecsSinceEpoch);
    -        /*
    -          Now walk those forward until they bracket forLocalMSecs with transitions.
    -
    -          One of the transitions should then be telling us the right offset to use.
    -          In a transition, we need the transition before it (to describe the run-up
    -          to the transition) and the transition itself; so we need to stop when
    -          nextTran is that transition.
    -        */
    -        while (nextTran.atMSecsSinceEpoch != invalidMSecs()
    -               && forLocalMSecs > nextTran.atMSecsSinceEpoch + nextTran.offsetFromUtc * 1000) {
    -            Data newTran = nextTransition(nextTran.atMSecsSinceEpoch);
    -            if (newTran.atMSecsSinceEpoch == invalidMSecs()
    -                || newTran.atMSecsSinceEpoch + newTran.offsetFromUtc * 1000 > imminent) {
    -                // Definitely not a relevant tansition: too far in the future.
    -                break;
    -            }
    -            tran = nextTran;
    -            nextTran = newTran;
    -        }
    -
    -        // Check we do *really* have transitions for this zone:
    -        if (tran.atMSecsSinceEpoch != invalidMSecs()) {
    -
    -            /*
    -              So now tran is definitely before and nextTran is either after or only
    -              slightly before.  One is standard time; we interpret the other as DST
    -              (although the transition might in fact by a change in standard offset).  Our
    -              hint tells us which of those to use (defaulting to standard if no hint): try
    -              it first; if that fails, try the other; if both fail, life's tricky.
    -            */
    -            Q_ASSERT(forLocalMSecs < 0
    -                     || forLocalMSecs - tran.offsetFromUtc * 1000 > tran.atMSecsSinceEpoch);
    -            const qint64 nextStart = nextTran.atMSecsSinceEpoch;
    -            // Work out the UTC values it might make sense to return:
    -            nextTran.atMSecsSinceEpoch = forLocalMSecs - nextTran.offsetFromUtc * 1000;
    -            tran.atMSecsSinceEpoch = forLocalMSecs - tran.offsetFromUtc * 1000;
    -
    -            // If both or neither have zero DST, treat the one with lower offset as standard:
    -            const bool nextIsDst = !nextTran.daylightTimeOffset == !tran.daylightTimeOffset
    -                ? tran.offsetFromUtc < nextTran.offsetFromUtc : nextTran.daylightTimeOffset;
    -            // If that agrees with hint > 0, our first guess is to use nextTran; else tran.
    -            const bool nextFirst = nextIsDst == (hint > 0) && nextStart != invalidMSecs();
    -            for (int i = 0; i < 2; i++) {
    -                /*
    -                  On the first pass, the case we consider is what hint told us to expect
    -                  (except when hint was -1 and didn't actually tell us what to expect),
    -                  so it's likely right.  We only get a second pass if the first failed,
    -                  by which time the second case, that we're trying, is likely right.  If
    -                  an overwhelming majority of calls have hint == -1, the Q_LIKELY here
    -                  shall be wrong half the time; otherwise, its errors shall be rarer
    -                  than that.
    -                */
    -                if (nextFirst ? i == 0 : i) {
    -                    Q_ASSERT(nextStart != invalidMSecs());
    -                    if (Q_LIKELY(nextStart <= nextTran.atMSecsSinceEpoch))
    -                        return nextTran;
    -                } else {
    -                    // If next is invalid, nextFirst is false, to route us here first:
    -                    if (nextStart == invalidMSecs() || Q_LIKELY(nextStart > tran.atMSecsSinceEpoch))
    -                        return tran;
    -                }
    -            }
    -
    -            /*
    -              Neither is valid (e.g. in a spring-forward's gap) and
    -              nextTran.atMSecsSinceEpoch < nextStart <= tran.atMSecsSinceEpoch, so
    -              0 < tran.atMSecsSinceEpoch - nextTran.atMSecsSinceEpoch
    -              = (nextTran.offsetFromUtc - tran.offsetFromUtc) * 1000
    -            */
    -            int dstStep = (nextTran.offsetFromUtc - tran.offsetFromUtc) * 1000;
    -            Q_ASSERT(dstStep > 0); // How else could we get here ?
    -            if (nextFirst) { // hint thought we needed nextTran, so use tran
    -                tran.atMSecsSinceEpoch -= dstStep;
    -                return tran;
    -            }
    -            nextTran.atMSecsSinceEpoch += dstStep;
    -            return nextTran;
    -        }
    -        // System has transitions but not for this zone.
    -        // Try falling back to offsetFromUtc
    -    }
    -
    -    /* Bracket and refine to discover offset. */
    -    qint64 utcEpochMSecs;
    -
    -    int early = offsetFromUtc(recent);
    -    int late = offsetFromUtc(imminent);
    -    if (Q_LIKELY(early == late)) { // > 99% of the time
    -        utcEpochMSecs = forLocalMSecs - early * 1000;
    -    } else {
    -        // Close to a DST transition: early > late is near a fall-back,
    -        // early < late is near a spring-forward.
    -        const int offsetInDst = qMax(early, late);
    -        const int offsetInStd = qMin(early, late);
    -        // Candidate values for utcEpochMSecs (if forLocalMSecs is valid):
    -        const qint64 forDst = forLocalMSecs - offsetInDst * 1000;
    -        const qint64 forStd = forLocalMSecs - offsetInStd * 1000;
    -        // Best guess at the answer:
    -        const qint64 hinted = hint > 0 ? forDst : forStd;
    -        if (Q_LIKELY(offsetFromUtc(hinted) == (hint > 0 ? offsetInDst : offsetInStd))) {
    -            utcEpochMSecs = hinted;
    -        } else if (hint <= 0 && offsetFromUtc(forDst) == offsetInDst) {
    -            utcEpochMSecs = forDst;
    -        } else if (hint > 0 && offsetFromUtc(forStd) == offsetInStd) {
    -            utcEpochMSecs = forStd;
    -        } else {
    -            // Invalid forLocalMSecs: in spring-forward gap.
    -            const int dstStep = daylightTimeOffset(early < late ? imminent : recent) * 1000;
    -            Q_ASSERT(dstStep); // There can't be a transition without it !
    -            utcEpochMSecs = (hint > 0) ? forStd - dstStep : forDst + dstStep;
    -        }
    -    }
    -
    -    return data(utcEpochMSecs);
    -}
    -
    -bool QTimeZonePrivate::hasTransitions() const
    -{
    -    return false;
    -}
    -
    -QTimeZonePrivate::Data QTimeZonePrivate::nextTransition(qint64 afterMSecsSinceEpoch) const
    -{
    -    Q_UNUSED(afterMSecsSinceEpoch)
    -    return invalidData();
    -}
    -
    -QTimeZonePrivate::Data QTimeZonePrivate::previousTransition(qint64 beforeMSecsSinceEpoch) const
    -{
    -    Q_UNUSED(beforeMSecsSinceEpoch)
    -    return invalidData();
    -}
    -
    -QTimeZonePrivate::DataList QTimeZonePrivate::transitions(qint64 fromMSecsSinceEpoch,
    -                                                         qint64 toMSecsSinceEpoch) const
    -{
    -    DataList list;
    -    if (toMSecsSinceEpoch >= fromMSecsSinceEpoch) {
    -        // fromMSecsSinceEpoch is inclusive but nextTransitionTime() is exclusive so go back 1 msec
    -        Data next = nextTransition(fromMSecsSinceEpoch - 1);
    -        while (next.atMSecsSinceEpoch != invalidMSecs()
    -               && next.atMSecsSinceEpoch <= toMSecsSinceEpoch) {
    -            list.append(next);
    -            next = nextTransition(next.atMSecsSinceEpoch);
    -        }
    -    }
    -    return list;
    -}
    -
    -QByteArray QTimeZonePrivate::systemTimeZoneId() const
    -{
    -    return QByteArray();
    -}
    -
    -bool QTimeZonePrivate::isTimeZoneIdAvailable(const QByteArray& ianaId) const
    -{
    -    // Fall-back implementation, can be made faster in subclasses
    -    const QList tzIds = availableTimeZoneIds();
    -    return std::binary_search(tzIds.begin(), tzIds.end(), ianaId);
    -}
    -
    -QList QTimeZonePrivate::availableTimeZoneIds() const
    -{
    -    return QList();
    -}
    -
    -QList QTimeZonePrivate::availableTimeZoneIds(QLocale::Country country) const
    -{
    -    // Default fall-back mode, use the zoneTable to find Region of know Zones
    -    QList regions;
    -
    -    // First get all Zones in the Zones table belonging to the Region
    -    for (int i = 0; i < zoneDataTableSize; ++i) {
    -        if (zoneData(i)->country == country)
    -            regions += ianaId(zoneData(i)).split(' ');
    -    }
    -
    -    std::sort(regions.begin(), regions.end());
    -    regions.erase(std::unique(regions.begin(), regions.end()), regions.end());
    -
    -    // Then select just those that are available
    -    const QList all = availableTimeZoneIds();
    -    QList result;
    -    result.reserve(qMin(all.size(), regions.size()));
    -    std::set_intersection(all.begin(), all.end(), regions.cbegin(), regions.cend(),
    -                          std::back_inserter(result));
    -    return result;
    -}
    -
    -QList QTimeZonePrivate::availableTimeZoneIds(int offsetFromUtc) const
    -{
    -    // Default fall-back mode, use the zoneTable to find Offset of know Zones
    -    QList offsets;
    -    // First get all Zones in the table using the Offset
    -    for (int i = 0; i < windowsDataTableSize; ++i) {
    -        const QWindowsData *winData = windowsData(i);
    -        if (winData->offsetFromUtc == offsetFromUtc) {
    -            for (int j = 0; j < zoneDataTableSize; ++j) {
    -                const QZoneData *data = zoneData(j);
    -                if (data->windowsIdKey == winData->windowsIdKey)
    -                    offsets += ianaId(data).split(' ');
    -            }
    -        }
    -    }
    -
    -    std::sort(offsets.begin(), offsets.end());
    -    offsets.erase(std::unique(offsets.begin(), offsets.end()), offsets.end());
    -
    -    // Then select just those that are available
    -    const QList all = availableTimeZoneIds();
    -    QList result;
    -    result.reserve(qMin(all.size(), offsets.size()));
    -    std::set_intersection(all.begin(), all.end(), offsets.cbegin(), offsets.cend(),
    -                          std::back_inserter(result));
    -    return result;
    -}
    -
    -#ifndef QT_NO_DATASTREAM
    -void QTimeZonePrivate::serialize(QDataStream &ds) const
    -{
    -    ds << QString::fromUtf8(m_id);
    -}
    -#endif // QT_NO_DATASTREAM
    -
    -// Static Utility Methods
    -
    -QTimeZonePrivate::Data QTimeZonePrivate::invalidData()
    -{
    -    Data data;
    -    data.atMSecsSinceEpoch = invalidMSecs();
    -    data.offsetFromUtc = invalidSeconds();
    -    data.standardTimeOffset = invalidSeconds();
    -    data.daylightTimeOffset = invalidSeconds();
    -    return data;
    -}
    -
    -QTimeZone::OffsetData QTimeZonePrivate::invalidOffsetData()
    -{
    -    QTimeZone::OffsetData offsetData;
    -    offsetData.atUtc = QDateTime();
    -    offsetData.offsetFromUtc = invalidSeconds();
    -    offsetData.standardTimeOffset = invalidSeconds();
    -    offsetData.daylightTimeOffset = invalidSeconds();
    -    return offsetData;
    -}
    -
    -QTimeZone::OffsetData QTimeZonePrivate::toOffsetData(const QTimeZonePrivate::Data &data)
    -{
    -    QTimeZone::OffsetData offsetData = invalidOffsetData();
    -    if (data.atMSecsSinceEpoch != invalidMSecs()) {
    -        offsetData.atUtc = QDateTime::fromMSecsSinceEpoch(data.atMSecsSinceEpoch, Qt::UTC);
    -        offsetData.offsetFromUtc = data.offsetFromUtc;
    -        offsetData.standardTimeOffset = data.standardTimeOffset;
    -        offsetData.daylightTimeOffset = data.daylightTimeOffset;
    -        offsetData.abbreviation = data.abbreviation;
    -    }
    -    return offsetData;
    -}
    -
    -// Is the format of the ID valid ?
    -bool QTimeZonePrivate::isValidId(const QByteArray &ianaId)
    -{
    -    /*
    -      Main rules for defining TZ/IANA names as per ftp://ftp.iana.org/tz/code/Theory
    -       1. Use only valid POSIX file name components
    -       2. Within a file name component, use only ASCII letters, `.', `-' and `_'.
    -       3. Do not use digits (except in a [+-]\d+ suffix, when used).
    -       4. A file name component must not exceed 14 characters or start with `-'
    -      However, the rules are really guidelines - a later one says
    -       - Do not change established names if they only marginally violate the
    -         above rules.
    -      We may, therefore, need to be a bit slack in our check here, if we hit
    -      legitimate exceptions in real time-zone databases.
    -
    -      In particular, aliases such as "Etc/GMT+7" and "SystemV/EST5EDT" are valid
    -      so we need to accept digits, ':', and '+'; aliases typically have the form
    -      of POSIX TZ strings, which allow a suffix to a proper IANA name.  A POSIX
    -      suffix starts with an offset (as in GMT+7) and may continue with another
    -      name (as in EST5EDT, giving the DST name of the zone); a further offset is
    -      allowed (for DST).  The ("hard to describe and [...] error-prone in
    -      practice") POSIX form even allows a suffix giving the dates (and
    -      optionally times) of the annual DST transitions.  Hopefully, no TZ aliases
    -      go that far, but we at least need to accept an offset and (single
    -      fragment) DST-name.
    -
    -      But for the legacy complications, the following would be preferable if
    -      QRegExp would work on QByteArrays directly:
    -          const QRegExp rx(QStringLiteral("[a-z+._][a-z+._-]{,13}"
    -                                      "(?:/[a-z+._][a-z+._-]{,13})*"
    -                                          // Optional suffix:
    -                                          "(?:[+-]?\d{1,2}(?::\d{1,2}){,2}" // offset
    -                                             // one name fragment (DST):
    -                                             "(?:[a-z+._][a-z+._-]{,13})?)"),
    -                           Qt::CaseInsensitive);
    -          return rx.exactMatch(ianaId);
    -    */
    -
    -    // Somewhat slack hand-rolled version:
    -    const int MinSectionLength = 1;
    -    const int MaxSectionLength = 14;
    -    int sectionLength = 0;
    -    for (const char *it = ianaId.begin(), * const end = ianaId.end(); it != end; ++it, ++sectionLength) {
    -        const char ch = *it;
    -        if (ch == '/') {
    -            if (sectionLength < MinSectionLength || sectionLength > MaxSectionLength)
    -                return false; // violates (4)
    -            sectionLength = -1;
    -        } else if (ch == '-') {
    -            if (sectionLength == 0)
    -                return false; // violates (4)
    -        } else if (!(ch >= 'a' && ch <= 'z')
    -                && !(ch >= 'A' && ch <= 'Z')
    -                && !(ch == '_')
    -                && !(ch == '.')
    -                   // Should ideally check these only happen as an offset:
    -                && !(ch >= '0' && ch <= '9')
    -                && !(ch == '+')
    -                && !(ch == ':')) {
    -            return false; // violates (2)
    -        }
    -    }
    -    if (sectionLength < MinSectionLength || sectionLength > MaxSectionLength)
    -        return false; // violates (4)
    -    return true;
    -}
    -
    -QString QTimeZonePrivate::isoOffsetFormat(int offsetFromUtc)
    -{
    -    const int mins = offsetFromUtc / 60;
    -    return QString::fromUtf8("UTC%1%2:%3").arg(mins >= 0 ? QLatin1Char('+') : QLatin1Char('-'))
    -                                          .arg(qAbs(mins) / 60, 2, 10, QLatin1Char('0'))
    -                                          .arg(qAbs(mins) % 60, 2, 10, QLatin1Char('0'));
    -}
    -
    -QByteArray QTimeZonePrivate::ianaIdToWindowsId(const QByteArray &id)
    -{
    -    for (int i = 0; i < zoneDataTableSize; ++i) {
    -        const QZoneData *data = zoneData(i);
    -        if (ianaId(data).split(' ').contains(id))
    -            return toWindowsIdLiteral(data->windowsIdKey);
    -    }
    -    return QByteArray();
    -}
    -
    -QByteArray QTimeZonePrivate::windowsIdToDefaultIanaId(const QByteArray &windowsId)
    -{
    -    const quint16 windowsIdKey = toWindowsIdKey(windowsId);
    -    for (int i = 0; i < windowsDataTableSize; ++i) {
    -        const QWindowsData *data = windowsData(i);
    -        if (data->windowsIdKey == windowsIdKey)
    -            return ianaId(data);
    -    }
    -    return QByteArray();
    -}
    -
    -QByteArray QTimeZonePrivate::windowsIdToDefaultIanaId(const QByteArray &windowsId,
    -                                                       QLocale::Country country)
    -{
    -    const QList list = windowsIdToIanaIds(windowsId, country);
    -    if (list.count() > 0)
    -        return list.first();
    -    else
    -        return QByteArray();
    -}
    -
    -QList QTimeZonePrivate::windowsIdToIanaIds(const QByteArray &windowsId)
    -{
    -    const quint16 windowsIdKey = toWindowsIdKey(windowsId);
    -    QList list;
    -
    -    for (int i = 0; i < zoneDataTableSize; ++i) {
    -        const QZoneData *data = zoneData(i);
    -        if (data->windowsIdKey == windowsIdKey)
    -            list << ianaId(data).split(' ');
    -    }
    -
    -    // Return the full list in alpha order
    -    std::sort(list.begin(), list.end());
    -    return list;
    -}
    -
    -QList QTimeZonePrivate::windowsIdToIanaIds(const QByteArray &windowsId,
    -                                                        QLocale::Country country)
    -{
    -    const quint16 windowsIdKey = toWindowsIdKey(windowsId);
    -    for (int i = 0; i < zoneDataTableSize; ++i) {
    -        const QZoneData *data = zoneData(i);
    -        // Return the region matches in preference order
    -        if (data->windowsIdKey == windowsIdKey && data->country == (quint16) country)
    -            return ianaId(data).split(' ');
    -    }
    -
    -    return QList();
    -}
    -
    -// Define template for derived classes to reimplement so QSharedDataPointer clone() works correctly
    -template<> QTimeZonePrivate *QSharedDataPointer::clone()
    -{
    -    return d->clone();
    -}
    -
    -/*
    -    UTC Offset implementation, used when QT_NO_SYSTEMLOCALE set and ICU is not being used,
    -    or for QDateTimes with a Qt:Spec of Qt::OffsetFromUtc.
    -*/
    -
    -// Create default UTC time zone
    -QUtcTimeZonePrivate::QUtcTimeZonePrivate()
    -{
    -    const QString name = utcQString();
    -    init(utcQByteArray(), 0, name, name, QLocale::AnyCountry, name);
    -}
    -
    -// Create a named UTC time zone
    -QUtcTimeZonePrivate::QUtcTimeZonePrivate(const QByteArray &id)
    -{
    -    // Look for the name in the UTC list, if found set the values
    -    for (int i = 0; i < utcDataTableSize; ++i) {
    -        const QUtcData *data = utcData(i);
    -        const QByteArray uid = utcId(data);
    -        if (uid == id) {
    -            QString name = QString::fromUtf8(id);
    -            init(id, data->offsetFromUtc, name, name, QLocale::AnyCountry, name);
    -            break;
    -        }
    -    }
    -}
    -
    -// Create offset from UTC
    -QUtcTimeZonePrivate::QUtcTimeZonePrivate(qint32 offsetSeconds)
    -{
    -    QString utcId;
    -
    -    if (offsetSeconds == 0)
    -        utcId = utcQString();
    -    else
    -        utcId = isoOffsetFormat(offsetSeconds);
    -
    -    init(utcId.toUtf8(), offsetSeconds, utcId, utcId, QLocale::AnyCountry, utcId);
    -}
    -
    -QUtcTimeZonePrivate::QUtcTimeZonePrivate(const QByteArray &zoneId, int offsetSeconds,
    -                                         const QString &name, const QString &abbreviation,
    -                                         QLocale::Country country, const QString &comment)
    -{
    -    init(zoneId, offsetSeconds, name, abbreviation, country, comment);
    -}
    -
    -QUtcTimeZonePrivate::QUtcTimeZonePrivate(const QUtcTimeZonePrivate &other)
    -    : QTimeZonePrivate(other), m_name(other.m_name),
    -      m_abbreviation(other.m_abbreviation),
    -      m_comment(other.m_comment),
    -      m_country(other.m_country),
    -      m_offsetFromUtc(other.m_offsetFromUtc)
    -{
    -}
    -
    -QUtcTimeZonePrivate::~QUtcTimeZonePrivate()
    -{
    -}
    -
    -QUtcTimeZonePrivate *QUtcTimeZonePrivate::clone() const
    -{
    -    return new QUtcTimeZonePrivate(*this);
    -}
    -
    -QTimeZonePrivate::Data QUtcTimeZonePrivate::data(qint64 forMSecsSinceEpoch) const
    -{
    -    Data d;
    -    d.abbreviation = m_abbreviation;
    -    d.atMSecsSinceEpoch = forMSecsSinceEpoch;
    -    d.standardTimeOffset = d.offsetFromUtc = m_offsetFromUtc;
    -    d.daylightTimeOffset = 0;
    -    return d;
    -}
    -
    -void QUtcTimeZonePrivate::init(const QByteArray &zoneId)
    -{
    -    m_id = zoneId;
    -}
    -
    -void QUtcTimeZonePrivate::init(const QByteArray &zoneId, int offsetSeconds, const QString &name,
    -                               const QString &abbreviation, QLocale::Country country,
    -                               const QString &comment)
    -{
    -    m_id = zoneId;
    -    m_offsetFromUtc = offsetSeconds;
    -    m_name = name;
    -    m_abbreviation = abbreviation;
    -    m_country = country;
    -    m_comment = comment;
    -}
    -
    -QLocale::Country QUtcTimeZonePrivate::country() const
    -{
    -    return m_country;
    -}
    -
    -QString QUtcTimeZonePrivate::comment() const
    -{
    -    return m_comment;
    -}
    -
    -QString QUtcTimeZonePrivate::displayName(QTimeZone::TimeType timeType,
    -                                         QTimeZone::NameType nameType,
    -                                         const QLocale &locale) const
    -{
    -    Q_UNUSED(timeType)
    -    Q_UNUSED(locale)
    -    if (nameType == QTimeZone::ShortName)
    -        return m_abbreviation;
    -    else if (nameType == QTimeZone::OffsetName)
    -        return isoOffsetFormat(m_offsetFromUtc);
    -    return m_name;
    -}
    -
    -QString QUtcTimeZonePrivate::abbreviation(qint64 atMSecsSinceEpoch) const
    -{
    -    Q_UNUSED(atMSecsSinceEpoch)
    -    return m_abbreviation;
    -}
    -
    -qint32 QUtcTimeZonePrivate::standardTimeOffset(qint64 atMSecsSinceEpoch) const
    -{
    -    Q_UNUSED(atMSecsSinceEpoch)
    -    return m_offsetFromUtc;
    -}
    -
    -qint32 QUtcTimeZonePrivate::daylightTimeOffset(qint64 atMSecsSinceEpoch) const
    -{
    -    Q_UNUSED(atMSecsSinceEpoch)
    -    return 0;
    -}
    -
    -QByteArray QUtcTimeZonePrivate::systemTimeZoneId() const
    -{
    -    return utcQByteArray();
    -}
    -
    -bool QUtcTimeZonePrivate::isTimeZoneIdAvailable(const QByteArray &ianaId) const
    -{
    -    for (int i = 0; i < utcDataTableSize; ++i) {
    -        const QUtcData *data = utcData(i);
    -        if (utcId(data) == ianaId) {
    -            return true;
    -        }
    -    }
    -    return false;
    -}
    -
    -QList QUtcTimeZonePrivate::availableTimeZoneIds() const
    -{
    -    QList result;
    -    result.reserve(utcDataTableSize);
    -    for (int i = 0; i < utcDataTableSize; ++i)
    -        result << utcId(utcData(i));
    -    std::sort(result.begin(), result.end()); // ### or already sorted??
    -    // ### assuming no duplicates
    -    return result;
    -}
    -
    -QList QUtcTimeZonePrivate::availableTimeZoneIds(QLocale::Country country) const
    -{
    -    // If AnyCountry then is request for all non-region offset codes
    -    if (country == QLocale::AnyCountry)
    -        return availableTimeZoneIds();
    -    return QList();
    -}
    -
    -QList QUtcTimeZonePrivate::availableTimeZoneIds(qint32 offsetSeconds) const
    -{
    -    QList result;
    -    for (int i = 0; i < utcDataTableSize; ++i) {
    -        const QUtcData *data = utcData(i);
    -        if (data->offsetFromUtc == offsetSeconds)
    -            result << utcId(data);
    -    }
    -    std::sort(result.begin(), result.end()); // ### or already sorted??
    -    // ### assuming no duplicates
    -    return result;
    -}
    -
    -#ifndef QT_NO_DATASTREAM
    -void QUtcTimeZonePrivate::serialize(QDataStream &ds) const
    -{
    -    ds << QStringLiteral("OffsetFromUtc") << QString::fromUtf8(m_id) << m_offsetFromUtc << m_name
    -       << m_abbreviation << (qint32) m_country << m_comment;
    -}
    -#endif // QT_NO_DATASTREAM
    -
    -QT_END_NAMESPACE
    diff --git a/src/corelib/tools/qtimezoneprivate_android.cpp b/src/corelib/tools/qtimezoneprivate_android.cpp
    deleted file mode 100644
    index be4f374fdd..0000000000
    --- a/src/corelib/tools/qtimezoneprivate_android.cpp
    +++ /dev/null
    @@ -1,257 +0,0 @@
    -/****************************************************************************
    -**
    -** Copyright (C) 2014 Drew Parsons 
    -** Contact: https://www.qt.io/licensing/
    -**
    -** This file is part of the QtCore module of the Qt Toolkit.
    -**
    -** $QT_BEGIN_LICENSE:LGPL$
    -** Commercial License Usage
    -** Licensees holding valid commercial Qt licenses may use this file in
    -** accordance with the commercial license agreement provided with the
    -** Software or, alternatively, in accordance with the terms contained in
    -** a written agreement between you and The Qt Company. For licensing terms
    -** and conditions see https://www.qt.io/terms-conditions. For further
    -** information use the contact form at https://www.qt.io/contact-us.
    -**
    -** GNU Lesser General Public License Usage
    -** Alternatively, this file may be used under the terms of the GNU Lesser
    -** General Public License version 3 as published by the Free Software
    -** Foundation and appearing in the file LICENSE.LGPL3 included in the
    -** packaging of this file. Please review the following information to
    -** ensure the GNU Lesser General Public License version 3 requirements
    -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
    -**
    -** GNU General Public License Usage
    -** Alternatively, this file may be used under the terms of the GNU
    -** General Public License version 2.0 or (at your option) the GNU General
    -** Public license version 3 or any later version approved by the KDE Free
    -** Qt Foundation. The licenses are as published by the Free Software
    -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
    -** included in the packaging of this file. Please review the following
    -** information to ensure the GNU General Public License requirements will
    -** be met: https://www.gnu.org/licenses/gpl-2.0.html and
    -** https://www.gnu.org/licenses/gpl-3.0.html.
    -**
    -** $QT_END_LICENSE$
    -**
    -****************************************************************************/
    -
    -#include 
    -#include "qtimezone.h"
    -#include "qtimezoneprivate_p.h"
    -
    -QT_BEGIN_NAMESPACE
    -
    -/*
    -    Private
    -
    -    Android implementation
    -*/
    -
    -// Create the system default time zone
    -QAndroidTimeZonePrivate::QAndroidTimeZonePrivate()
    -    : QTimeZonePrivate()
    -{
    -    // start with system time zone
    -    androidTimeZone = QJNIObjectPrivate::callStaticObjectMethod("java.util.TimeZone", "getDefault", "()Ljava/util/TimeZone;");
    -    init("UTC");
    -}
    -
    -// Create a named time zone
    -QAndroidTimeZonePrivate::QAndroidTimeZonePrivate(const QByteArray &ianaId)
    -    : QTimeZonePrivate()
    -{
    -    init(ianaId);
    -}
    -
    -QAndroidTimeZonePrivate::QAndroidTimeZonePrivate(const QAndroidTimeZonePrivate &other)
    -    : QTimeZonePrivate(other)
    -{
    -    androidTimeZone = other.androidTimeZone;
    -    m_id = other.id();
    -}
    -
    -QAndroidTimeZonePrivate::~QAndroidTimeZonePrivate()
    -{
    -}
    -
    -
    -void QAndroidTimeZonePrivate::init(const QByteArray &ianaId)
    -{
    -    QJNIObjectPrivate jo_ianaId = QJNIObjectPrivate::fromString( QString::fromUtf8(ianaId) );
    -    androidTimeZone = QJNIObjectPrivate::callStaticObjectMethod( "java.util.TimeZone", "getTimeZone", "(Ljava/lang/String;)Ljava/util/TimeZone;",  static_cast(jo_ianaId.object()) );
    -
    -    // Painfully, JNI gives us back a default zone object if it doesn't
    -    // recognize the name; so check for whether ianaId is a recognized name of
    -    // the zone object we got and ignore the zone if not.
    -    // Try checking ianaId against getID(), getDisplayName():
    -    QJNIObjectPrivate jname = androidTimeZone.callObjectMethod("getID", "()Ljava/lang/String;");
    -    bool found = (jname.toString().toUtf8() == ianaId);
    -    for (int style = 1; !found && style-- > 0;) {
    -        for (int dst = 1; !found && dst-- > 0;) {
    -            jname = androidTimeZone.callObjectMethod("getDisplayName", "(ZI;)Ljava/lang/String;",
    -                                                     bool(dst), style);
    -            found = (jname.toString().toUtf8() == ianaId);
    -        }
    -    }
    -
    -    if (!found)
    -        m_id.clear();
    -    else if (ianaId.isEmpty())
    -        m_id = systemTimeZoneId();
    -    else
    -        m_id = ianaId;
    -}
    -
    -QAndroidTimeZonePrivate *QAndroidTimeZonePrivate::clone() const
    -{
    -    return new QAndroidTimeZonePrivate(*this);
    -}
    -
    -
    -QString QAndroidTimeZonePrivate::displayName(QTimeZone::TimeType timeType, QTimeZone::NameType nameType,
    -                                             const QLocale &locale) const
    -{
    -    QString name;
    -
    -    if (androidTimeZone.isValid()) {
    -        jboolean daylightTime = (timeType == QTimeZone::DaylightTime);  // treat QTimeZone::GenericTime as QTimeZone::StandardTime
    -
    -        // treat all NameTypes as java TimeZone style LONG (value 1), except of course QTimeZone::ShortName which is style SHORT (value 0);
    -        jint style = (nameType == QTimeZone::ShortName ? 0 : 1);
    -
    -        QJNIObjectPrivate jlanguage = QJNIObjectPrivate::fromString(QLocale::languageToString(locale.language()));
    -        QJNIObjectPrivate jcountry = QJNIObjectPrivate::fromString(QLocale::countryToString(locale.country()));
    -        QJNIObjectPrivate jvariant = QJNIObjectPrivate::fromString(QLocale::scriptToString(locale.script()));
    -        QJNIObjectPrivate jlocale("java.util.Locale", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V", static_cast(jlanguage.object()), static_cast(jcountry.object()), static_cast(jvariant.object()));
    -
    -        QJNIObjectPrivate jname = androidTimeZone.callObjectMethod("getDisplayName", "(ZILjava/util/Locale;)Ljava/lang/String;", daylightTime, style, jlocale.object());
    -
    -        name = jname.toString();
    -    }
    -
    -    return name;
    -}
    -
    -QString QAndroidTimeZonePrivate::abbreviation(qint64 atMSecsSinceEpoch) const
    -{
    -    if ( isDaylightTime( atMSecsSinceEpoch ) )
    -        return displayName(QTimeZone::DaylightTime, QTimeZone::ShortName, QLocale() );
    -    else
    -        return displayName(QTimeZone::StandardTime, QTimeZone::ShortName, QLocale() );
    -}
    -
    -int QAndroidTimeZonePrivate::offsetFromUtc(qint64 atMSecsSinceEpoch) const
    -{
    -    // offsetFromUtc( ) is invoked when androidTimeZone may not yet be set at startup,
    -    // so a validity test is needed here
    -    if ( androidTimeZone.isValid() )
    -        // the java method getOffset() returns milliseconds, but QTimeZone returns seconds
    -        return androidTimeZone.callMethod( "getOffset", "(J)I", static_cast(atMSecsSinceEpoch) ) / 1000;
    -    else
    -        return 0;
    -}
    -
    -int QAndroidTimeZonePrivate::standardTimeOffset(qint64 atMSecsSinceEpoch) const
    -{
    -    // the java method does not use a reference time
    -    Q_UNUSED( atMSecsSinceEpoch );
    -    if ( androidTimeZone.isValid() )
    -        // the java method getRawOffset() returns milliseconds, but QTimeZone returns seconds
    -        return androidTimeZone.callMethod( "getRawOffset" ) / 1000;
    -    else
    -        return 0;
    -}
    -
    -int QAndroidTimeZonePrivate::daylightTimeOffset(qint64 atMSecsSinceEpoch) const
    -{
    -    return ( offsetFromUtc(atMSecsSinceEpoch) - standardTimeOffset(atMSecsSinceEpoch) );
    -}
    -
    -bool QAndroidTimeZonePrivate::hasDaylightTime() const
    -{
    -    if ( androidTimeZone.isValid() )
    -        /* note: the Java function only tests for future DST transtions, not past */
    -        return androidTimeZone.callMethod("useDaylightTime" );
    -    else
    -        return false;
    -}
    -
    -bool QAndroidTimeZonePrivate::isDaylightTime(qint64 atMSecsSinceEpoch) const
    -{
    -    if ( androidTimeZone.isValid() ) {
    -        QJNIObjectPrivate jDate( "java/util/Date", "(J)V", static_cast(atMSecsSinceEpoch) );
    -        return androidTimeZone.callMethod("inDaylightTime", "(Ljava/util/Date;)Z", jDate.object() );
    -    }
    -    else
    -        return false;
    -}
    -
    -QTimeZonePrivate::Data QAndroidTimeZonePrivate::data(qint64 forMSecsSinceEpoch) const
    -{
    -    if (androidTimeZone.isValid()) {
    -        Data data;
    -        data.atMSecsSinceEpoch = forMSecsSinceEpoch;
    -        data.standardTimeOffset = standardTimeOffset(forMSecsSinceEpoch);
    -        data.offsetFromUtc = offsetFromUtc(forMSecsSinceEpoch);
    -        data.daylightTimeOffset = data.offsetFromUtc - data.standardTimeOffset;
    -        data.abbreviation = abbreviation(forMSecsSinceEpoch);
    -        return data;
    -    } else {
    -        return invalidData();
    -    }
    -}
    -
    -bool QAndroidTimeZonePrivate::hasTransitions() const
    -{
    -    // java.util.TimeZone does not directly provide transitions
    -    return false;
    -}
    -
    -QTimeZonePrivate::Data QAndroidTimeZonePrivate::nextTransition(qint64 afterMSecsSinceEpoch) const
    -{
    -    // transitions not available on Android, so return an invalid data object
    -    Q_UNUSED( afterMSecsSinceEpoch );
    -    return invalidData();
    -}
    -
    -QTimeZonePrivate::Data QAndroidTimeZonePrivate::previousTransition(qint64 beforeMSecsSinceEpoch) const
    -{
    -    // transitions not available on Android, so return an invalid data object
    -    Q_UNUSED( beforeMSecsSinceEpoch );
    -    return invalidData();
    -}
    -
    -QByteArray QAndroidTimeZonePrivate::systemTimeZoneId() const
    -{
    -    QJNIObjectPrivate androidSystemTimeZone = QJNIObjectPrivate::callStaticObjectMethod("java.util.TimeZone", "getDefault", "()Ljava/util/TimeZone;");
    -    QJNIObjectPrivate systemTZIdAndroid = androidSystemTimeZone.callObjectMethod("getID");
    -    QByteArray systemTZid = systemTZIdAndroid.toString().toUtf8();
    -
    -    return systemTZid;
    -}
    -
    -QList QAndroidTimeZonePrivate::availableTimeZoneIds() const
    -{
    -    QList availableTimeZoneIdList;
    -    QJNIObjectPrivate androidAvailableIdList = QJNIObjectPrivate::callStaticObjectMethod("java.util.TimeZone", "getAvailableIDs", "()[Ljava/lang/String;");
    -
    -    QJNIEnvironmentPrivate jniEnv;
    -    int androidTZcount = jniEnv->GetArrayLength( static_cast(androidAvailableIdList.object()) );
    -
    -    // need separate jobject and QAndroidJniObject here so that we can delete (DeleteLocalRef) the reference to the jobject
    -    // (or else the JNI reference table fills after 512 entries from GetObjectArrayElement)
    -    jobject androidTZobject;
    -    QJNIObjectPrivate androidTZ;
    -    for (int i=0; iGetObjectArrayElement( static_cast( androidAvailableIdList.object() ), i );
    -        androidTZ = androidTZobject;
    -        availableTimeZoneIdList.append( androidTZ.toString().toUtf8() );
    -        jniEnv->DeleteLocalRef(androidTZobject);
    -    }
    -
    -    return availableTimeZoneIdList;
    -}
    -
    -QT_END_NAMESPACE
    diff --git a/src/corelib/tools/qtimezoneprivate_data_p.h b/src/corelib/tools/qtimezoneprivate_data_p.h
    deleted file mode 100644
    index 40d6c972c2..0000000000
    --- a/src/corelib/tools/qtimezoneprivate_data_p.h
    +++ /dev/null
    @@ -1,1257 +0,0 @@
    -/****************************************************************************
    -**
    -** Copyright (C) 2013 John Layt 
    -** Contact: https://www.qt.io/licensing/
    -**
    -** This file is part of the QtCore module of the Qt Toolkit.
    -**
    -** $QT_BEGIN_LICENSE:LGPL$
    -** Commercial License Usage
    -** Licensees holding valid commercial Qt licenses may use this file in
    -** accordance with the commercial license agreement provided with the
    -** Software or, alternatively, in accordance with the terms contained in
    -** a written agreement between you and The Qt Company. For licensing terms
    -** and conditions see https://www.qt.io/terms-conditions. For further
    -** information use the contact form at https://www.qt.io/contact-us.
    -**
    -** GNU Lesser General Public License Usage
    -** Alternatively, this file may be used under the terms of the GNU Lesser
    -** General Public License version 3 as published by the Free Software
    -** Foundation and appearing in the file LICENSE.LGPL3 included in the
    -** packaging of this file. Please review the following information to
    -** ensure the GNU Lesser General Public License version 3 requirements
    -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
    -**
    -** GNU General Public License Usage
    -** Alternatively, this file may be used under the terms of the GNU
    -** General Public License version 2.0 or (at your option) the GNU General
    -** Public license version 3 or any later version approved by the KDE Free
    -** Qt Foundation. The licenses are as published by the Free Software
    -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
    -** included in the packaging of this file. Please review the following
    -** information to ensure the GNU General Public License requirements will
    -** be met: https://www.gnu.org/licenses/gpl-2.0.html and
    -** https://www.gnu.org/licenses/gpl-3.0.html.
    -**
    -** $QT_END_LICENSE$
    -**
    -****************************************************************************/
    -
    -
    -#ifndef QTIMEZONEPRIVATE_DATA_P_H
    -#define QTIMEZONEPRIVATE_DATA_P_H
    -
    -//
    -//  W A R N I N G
    -//  -------------
    -//
    -// This file is not part of the Qt API.  It exists for the convenience
    -// of internal files.  This header file may change from version to version
    -// without notice, or even be removed.
    -//
    -// We mean it.
    -//
    -
    -#include 
    -
    -QT_BEGIN_NAMESPACE
    -
    -/*
    -    Windows Zone ID support, included in default base class build so can be used on all platforms,
    -    e.g. an app running on Linux may need to communicate with a Windows Outlook server.  These
    -    tables can also be used to look-up Region Codes and UTC Offsets on platforms that don't directly
    -    support them., e.g. Mac does not support availableTimeZones() filtering by region or offset.
    -
    -    Another data table is provided for generic UTC+00:00 format time zones to be used as a
    -    fall-back if no system time zones are available (QT_NO_SYSTEMLOCALE is set) or for QDateTimes
    -    with a QT:Spec of OffsetFromUTC
    -
    -    These tables are automatically adapted from the CLDR supplemental/windowsZones.xml data file
    -    using a script in qtbase/util/locale_database.  Please do not edit this data directly.  In the
    -    future if ICU is made a hard dependency then the ICU resource can be used directly and this
    -    table removed
    -*/
    -
    -struct QZoneData {
    -    quint16 windowsIdKey;      // Windows ID Key
    -    quint16 country;           // Country of IANA ID's, AnyCountry means No Country
    -    quint16 ianaIdIndex;      // All IANA ID's for the Windows ID and Country, space separated
    -};
    -
    -struct QWindowsData {
    -    quint16 windowsIdKey;      // Windows ID Key
    -    quint16 windowsIdIndex;    // Windows ID Literal
    -    quint16 ianaIdIndex;      // Default IANA ID for the Windows ID
    -    qint32 offsetFromUtc;      // Standard Time Offset from UTC, used for quick look-ups
    -};
    -
    -struct QUtcData {
    -    quint16 ianaIdIndex;      // IANA ID's
    -    qint32 offsetFromUtc;      // Offset form UTC is seconds
    -};
    -
    -/*
    -    COPYRIGHT AND PERMISSION NOTICE
    -
    -    Copyright © 1991-2012 Unicode, Inc. All rights reserved. Distributed under
    -    the Terms of Use in http://www.unicode.org/copyright.html.
    -
    -    Permission is hereby granted, free of charge, to any person obtaining a
    -    copy of the Unicode data files and any associated documentation (the "Data
    -    Files") or Unicode software and any associated documentation (the "Software")
    -    to deal in the Data Files or Software without restriction, including without
    -    limitation the rights to use, copy, modify, merge, publish, distribute, and/or
    -    sell copies of the Data Files or Software, and to permit persons to whom the
    -    Data Files or Software are furnished to do so, provided that (a) the above
    -    copyright notice(s) and this permission notice appear with all copies of the
    -    Data Files or Software, (b) both the above copyright notice(s) and this
    -    permission notice appear in associated documentation, and (c) there is clear
    -    notice in each modified Data File or in the Software as well as in the
    -    documentation associated with the Data File(s) or Software that the data or
    -    software has been modified.
    -*/
    -
    -// GENERATED PART STARTS HERE
    -
    -/*
    -    This part of the file was generated on 2019-05-28 from the
    -    Common Locale Data Repository v35.1 supplemental/windowsZones.xml file $Revision: 14742 $
    -
    -    http://www.unicode.org/cldr/
    -
    -    Do not edit this code: run cldr2qtimezone.py on updated (or
    -    edited) CLDR data; see qtbase/util/locale_database/.
    -*/
    -
    -// Windows ID Key, Country Enum, IANA ID Index
    -static const QZoneData zoneDataTable[] = {
    -    {    131,   143,     0 }, // W. Mongolia Standard Time / Mongolia
    -    {    124,   112,    10 }, // UTC+12 / Kiribati
    -    {     52,    94,    25 }, // Haiti Standard Time / Haiti
    -    {     32,    44,    48 }, // China Standard Time / China
    -    {     95,   244,    62 }, // SA Western Standard Time / Saint Barthelemy
    -    {     25,   116,    84 }, // Central Asia Standard Time / Kyrgyzstan
    -    {     36,     8,    97 }, // E. Africa Standard Time / Antarctica
    -    {     33,   154,   114 }, // Chatham Islands Standard Time / New Zealand
    -    {     95,   144,   130 }, // SA Western Standard Time / Montserrat
    -    {     37,    13,   149 }, // E. Australia Standard Time / Australia
    -    {     61,     0,   187 }, // Line Islands Standard Time / AnyCountry
    -    {    132,   218,   198 }, // West Asia Standard Time / Turkmenistan
    -    {    122,    30,   212 }, // UTC-02 / Brazil
    -    {     24,    52,   228 }, // Central America Standard Time / Costa Rica
    -    {     36,    67,   247 }, // E. Africa Standard Time / Eritrea
    -    {    128,     8,   261 }, // W. Australia Standard Time / Antarctica
    -    {    101,   101,   278 }, // SE Asia Standard Time / Indonesia
    -    {     93,     8,   306 }, // SA Eastern Standard Time / Antarctica
    -    {      4,   178,   325 }, // Altai Standard Time / Russia
    -    {     95,   256,   338 }, // SA Western Standard Time / Sint Maarten
    -    {     95,    60,   360 }, // SA Western Standard Time / Dominica
    -    {    134,   167,   377 }, // West Pacific Standard Time / Papua New Guinea
    -    {     13,    13,   398 }, // AUS Eastern Standard Time / Australia
    -    {     69,   236,   435 }, // Morocco Standard Time / Western Sahara
    -    {     39,    30,   451 }, // E. South America Standard Time / Brazil
    -    {    124,   134,   469 }, // UTC+12 / Marshall Islands
    -    {    125,   112,   502 }, // UTC+13 / Kiribati
    -    {    103,   146,   520 }, // South Africa Standard Time / Mozambique
    -    {     94,    30,   534 }, // SA Pacific Standard Time / Brazil
    -    {     88,    74,   570 }, // Romance Standard Time / France
    -    {     71,    38,   583 }, // Mountain Standard Time / Canada
    -    {     72,   147,   657 }, // Myanmar Standard Time / Myanmar
    -    {     26,    30,   670 }, // Central Brazilian Standard Time / Brazil
    -    {    130,   123,   706 }, // W. Europe Standard Time / Liechtenstein
    -    {     46,    73,   719 }, // FLE Standard Time / Finland
    -    {     93,    70,   735 }, // SA Eastern Standard Time / Falkland Islands
    -    {     78,   159,   752 }, // Norfolk Standard Time / Norfolk Island
    -    {     53,     0,   768 }, // Hawaiian Standard Time / AnyCountry
    -    {     28,    54,   779 }, // Central European Standard Time / Croatia
    -    {     75,   150,   793 }, // Nepal Standard Time / Nepal
    -    {     46,    33,   807 }, // FLE Standard Time / Bulgaria
    -    {      6,   162,   820 }, // Arabian Standard Time / Oman
    -    {    132,   131,   832 }, // West Asia Standard Time / Maldives
    -    {     88,   197,   848 }, // Romance Standard Time / Spain
    -    {     50,    91,   875 }, // Greenwich Standard Time / Guinea
    -    {      5,   237,   890 }, // Arab Standard Time / Yemen
    -    {     92,   222,   900 }, // Russian Standard Time / Ukraine
    -    {    103,   204,   918 }, // South Africa Standard Time / Swaziland
    -    {    130,   203,   933 }, // W. Europe Standard Time / Svalbard And Jan Mayen Islands
    -    {      7,   103,   953 }, // Arabic Standard Time / Iraq
    -    {    119,   226,   966 }, // UTC-11 / United States Minor Outlying Islands
    -    {      5,   115,   981 }, // Arab Standard Time / Kuwait
    -    {     50,   189,   993 }, // Greenwich Standard Time / Sierra Leone
    -    {     31,     0,  1009 }, // Central Standard Time / AnyCountry
    -    {     53,    51,  1017 }, // Hawaiian Standard Time / Cook Islands
    -    {    129,    50,  1035 }, // W. Central Africa Standard Time / Congo Brazzaville
    -    {     64,    43,  1054 }, // Magallanes Standard Time / Chile
    -    {    119,     0,  1075 }, // UTC-11 / AnyCountry
    -    {     84,    38,  1086 }, // Pacific Standard Time / Canada
    -    {     22,    11,  1138 }, // Caucasus Standard Time / Armenia
    -    {    130,   142,  1151 }, // W. Europe Standard Time / Monaco
    -    {    103,   239,  1165 }, // South Africa Standard Time / Zambia
    -    {     46,   222,  1179 }, // FLE Standard Time / Ukraine
    -    {     87,   168,  1225 }, // Paraguay Standard Time / Paraguay
    -    {     57,   109,  1242 }, // Jordan Standard Time / Jordan
    -    {    109,    30,  1253 }, // Tocantins Standard Time / Brazil
    -    {     55,   102,  1271 }, // Iran Standard Time / Iran
    -    {    101,     8,  1283 }, // SE Asia Standard Time / Antarctica
    -    {     27,    57,  1300 }, // Central Europe Standard Time / Czech Republic
    -    {     95,   215,  1314 }, // SA Western Standard Time / Trinidad And Tobago
    -    {    103,    28,  1336 }, // South Africa Standard Time / Botswana
    -    {    132,     0,  1352 }, // West Asia Standard Time / AnyCountry
    -    {     94,    63,  1362 }, // SA Pacific Standard Time / Ecuador
    -    {     51,    85,  1380 }, // GTB Standard Time / Greece
    -    {     36,   128,  1394 }, // E. Africa Standard Time / Madagascar
    -    {     53,   226,  1414 }, // Hawaiian Standard Time / United States Minor Outlying Islands
    -    {     94,   107,  1431 }, // SA Pacific Standard Time / Jamaica
    -    {    104,   198,  1447 }, // Sri Lanka Standard Time / Sri Lanka
    -    {     27,   243,  1460 }, // Central Europe Standard Time / Serbia
    -    {     25,   110,  1476 }, // Central Asia Standard Time / Kazakhstan
    -    {    125,     0,  1502 }, // UTC+13 / AnyCountry
    -    {     94,    38,  1513 }, // SA Pacific Standard Time / Canada
    -    {     25,    31,  1535 }, // Central Asia Standard Time / British Indian Ocean Territory
    -    {    108,    13,  1549 }, // Tasmania Standard Time / Australia
    -    {     95,   174,  1583 }, // SA Western Standard Time / Puerto Rico
    -    {     95,   180,  1603 }, // SA Western Standard Time / Saint Kitts And Nevis
    -    {    130,   206,  1620 }, // W. Europe Standard Time / Switzerland
    -    {    117,   225,  1634 }, // US Eastern Standard Time / United States
    -    {     29,   140,  1701 }, // Central Pacific Standard Time / Micronesia
    -    {    120,    77,  1731 }, // UTC-09 / French Polynesia
    -    {    129,   156,  1747 }, // W. Central Africa Standard Time / Niger
    -    {    118,   139,  1761 }, // US Mountain Standard Time / Mexico
    -    {     36,   194,  1780 }, // E. Africa Standard Time / Somalia
    -    {    118,     0,  1797 }, // US Mountain Standard Time / AnyCountry
    -    {     10,    24,  1807 }, // Atlantic Standard Time / Bermuda
    -    {    103,   240,  1824 }, // South Africa Standard Time / Zimbabwe
    -    {     32,   126,  1838 }, // China Standard Time / Macau
    -    {    129,    66,  1849 }, // W. Central Africa Standard Time / Equatorial Guinea
    -    {     66,   137,  1863 }, // Mauritius Standard Time / Mauritius
    -    {     46,    68,  1880 }, // FLE Standard Time / Estonia
    -    {     50,   187,  1895 }, // Greenwich Standard Time / Senegal
    -    {    132,   110,  1908 }, // West Asia Standard Time / Kazakhstan
    -    {     25,    44,  1968 }, // Central Asia Standard Time / China
    -    {    130,   106,  1980 }, // W. Europe Standard Time / Italy
    -    {     48,   251,  1992 }, // GMT Standard Time / Isle Of Man
    -    {     36,   210,  2011 }, // E. Africa Standard Time / Tanzania
    -    {     10,    86,  2032 }, // Atlantic Standard Time / Greenland
    -    {    123,    86,  2046 }, // UTC / Greenland
    -    {     20,    38,  2067 }, // Canada Central Standard Time / Canada
    -    {     15,    86,  2104 }, // Azores Standard Time / Greenland
    -    {     69,   145,  2125 }, // Morocco Standard Time / Morocco
    -    {    115,   219,  2143 }, // Turks And Caicos Standard Time / Turks And Caicos Islands
    -    {     50,    80,  2162 }, // Greenwich Standard Time / Gambia
    -    {    129,    42,  2176 }, // W. Central Africa Standard Time / Chad
    -    {     56,   105,  2192 }, // Israel Standard Time / Israel
    -    {     64,     8,  2207 }, // Magallanes Standard Time / Antarctica
    -    {     12,    13,  2225 }, // Aus Central W. Standard Time / Australia
    -    {     24,   155,  2241 }, // Central America Standard Time / Nicaragua
    -    {    102,   170,  2257 }, // Singapore Standard Time / Philippines
    -    {    134,   160,  2269 }, // West Pacific Standard Time / Northern Mariana Islands
    -    {     43,    64,  2284 }, // Egypt Standard Time / Egypt
    -    {     88,    21,  2297 }, // Romance Standard Time / Belgium
    -    {     76,     8,  2313 }, // New Zealand Standard Time / Antarctica
    -    {     51,   177,  2332 }, // GTB Standard Time / Romania
    -    {    103,     0,  2349 }, // South Africa Standard Time / AnyCountry
    -    {     41,   225,  2359 }, // Eastern Standard Time / United States
    -    {    129,    23,  2516 }, // W. Central Africa Standard Time / Benin
    -    {     79,   178,  2534 }, // North Asia East Standard Time / Russia
    -    {    116,   143,  2547 }, // Ulaanbaatar Standard Time / Mongolia
    -    {    130,    14,  2580 }, // W. Europe Standard Time / Austria
    -    {     41,    38,  2594 }, // Eastern Standard Time / Canada
    -    {     95,   255,  2699 }, // SA Western Standard Time / Bonaire
    -    {    124,   149,  2718 }, // UTC+12 / Nauru
    -    {    134,     8,  2732 }, // West Pacific Standard Time / Antarctica
    -    {     63,   178,  2758 }, // Magadan Standard Time / Russia
    -    {    130,   161,  2771 }, // W. Europe Standard Time / Norway
    -    {    110,     0,  2783 }, // Tokyo Standard Time / AnyCountry
    -    {     24,    63,  2793 }, // Central America Standard Time / Ecuador
    -    {    103,    35,  2811 }, // South Africa Standard Time / Burundi
    -    {     10,    38,  2828 }, // Atlantic Standard Time / Canada
    -    {     29,     0,  2896 }, // Central Pacific Standard Time / AnyCountry
    -    {     95,    87,  2907 }, // SA Western Standard Time / Grenada
    -    {     29,   153,  2923 }, // Central Pacific Standard Time / New Caledonia
    -    {     42,   139,  2938 }, // Eastern Standard Time (Mexico) / Mexico
    -    {      2,   225,  2953 }, // Alaskan Standard Time / United States
    -    {     49,    86,  3029 }, // Greenland Standard Time / Greenland
    -    {     50,    92,  3045 }, // Greenwich Standard Time / Guinea Bissau
    -    {    130,   184,  3059 }, // W. Europe Standard Time / San Marino
    -    {     27,    98,  3077 }, // Central Europe Standard Time / Hungary
    -    {     24,    96,  3093 }, // Central America Standard Time / Honduras
    -    {     62,    13,  3113 }, // Lord Howe Standard Time / Australia
    -    {     36,     0,  3133 }, // E. Africa Standard Time / AnyCountry
    -    {    129,    79,  3143 }, // W. Central Africa Standard Time / Gabon
    -    {     95,   182,  3161 }, // SA Western Standard Time / Saint Vincent And The Grenadines
    -    {     48,   224,  3180 }, // GMT Standard Time / United Kingdom
    -    {     68,   227,  3194 }, // Montevideo Standard Time / Uruguay
    -    {    124,     0,  3213 }, // UTC+12 / AnyCountry
    -    {    130,   230,  3224 }, // W. Europe Standard Time / Vatican City State
    -    {     50,    99,  3239 }, // Greenwich Standard Time / Iceland
    -    {     34,    55,  3258 }, // Cuba Standard Time / Cuba
    -    {     41,    16,  3273 }, // Eastern Standard Time / Bahamas
    -    {    122,   196,  3288 }, // UTC-02 / South Georgia And The South Sandwich Islands
    -    {     24,    65,  3311 }, // Central America Standard Time / El Salvador
    -    {     31,   225,  3331 }, // Central Standard Time / United States
    -    {     95,     0,  3499 }, // SA Western Standard Time / AnyCountry
    -    {     94,   166,  3509 }, // SA Pacific Standard Time / Panama
    -    {     94,    47,  3524 }, // SA Pacific Standard Time / Colombia
    -    {     70,   139,  3539 }, // Mountain Standard Time (Mexico) / Mexico
    -    {    124,   220,  3574 }, // UTC+12 / Tuvalu
    -    {    130,    84,  3591 }, // W. Europe Standard Time / Gibraltar
    -    {     82,   178,  3608 }, // Omsk Standard Time / Russia
    -    {     60,   122,  3618 }, // Libya Standard Time / Libya
    -    {     25,     8,  3633 }, // Central Asia Standard Time / Antarctica
    -    {     95,    12,  3651 }, // SA Western Standard Time / Aruba
    -    {     67,   119,  3665 }, // Middle East Standard Time / Lebanon
    -    {    102,     0,  3677 }, // Singapore Standard Time / AnyCountry
    -    {     74,   148,  3687 }, // Namibia Standard Time / Namibia
    -    {    126,   231,  3703 }, // Venezuela Standard Time / Venezuela
    -    {     95,   234,  3719 }, // SA Western Standard Time / United States Virgin Islands
    -    {     21,     0,  3737 }, // Cape Verde Standard Time / AnyCountry
    -    {     95,     9,  3747 }, // SA Western Standard Time / Antigua And Barbuda
    -    {     94,   169,  3763 }, // SA Pacific Standard Time / Peru
    -    {     46,   248,  3776 }, // FLE Standard Time / Aland Islands
    -    {     50,   199,  3793 }, // Greenwich Standard Time / Saint Helena
    -    {    134,   140,  3812 }, // West Pacific Standard Time / Micronesia
    -    {    102,   190,  3825 }, // Singapore Standard Time / Singapore
    -    {     95,    61,  3840 }, // SA Western Standard Time / Dominican Republic
    -    {    103,   129,  3862 }, // South Africa Standard Time / Malawi
    -    {     30,   139,  3878 }, // Central Standard Time (Mexico) / Mexico
    -    {    102,   130,  3954 }, // Singapore Standard Time / Malaysia
    -    {     45,    72,  3985 }, // Fiji Standard Time / Fiji
    -    {    118,   225,  3998 }, // US Mountain Standard Time / United States
    -    {     17,    25,  4014 }, // Bangladesh Standard Time / Bhutan
    -    {    130,   133,  4027 }, // W. Europe Standard Time / Malta
    -    {     92,   178,  4040 }, // Russian Standard Time / Russia
    -    {     95,   135,  4084 }, // SA Western Standard Time / Martinique
    -    {     35,     0,  4103 }, // Dateline Standard Time / AnyCountry
    -    {    135,   178,  4114 }, // Yakutsk Standard Time / Russia
    -    {      1,     1,  4141 }, // Afghanistan Standard Time / Afghanistan
    -    {    123,     0,  4152 }, // UTC / AnyCountry
    -    {     31,   139,  4168 }, // Central Standard Time / Mexico
    -    {      6,     0,  4186 }, // Arabian Standard Time / AnyCountry
    -    {    101,    45,  4196 }, // SE Asia Standard Time / Christmas Island
    -    {     15,   173,  4213 }, // Azores Standard Time / Portugal
    -    {    129,     0,  4229 }, // W. Central Africa Standard Time / AnyCountry
    -    {     17,    18,  4239 }, // Bangladesh Standard Time / Bangladesh
    -    {     31,    38,  4250 }, // Central Standard Time / Canada
    -    {     94,     0,  4325 }, // SA Pacific Standard Time / AnyCountry
    -    {    125,   213,  4335 }, // UTC+13 / Tokelau
    -    {     73,   178,  4351 }, // N. Central Asia Standard Time / Russia
    -    {    133,   165,  4368 }, // West Bank Standard Time / Palestinian Territories
    -    {    114,   217,  4390 }, // Turkey Standard Time / Turkey
    -    {      3,   225,  4406 }, // Aleutian Standard Time / United States
    -    {    101,     0,  4419 }, // SE Asia Standard Time / AnyCountry
    -    {     71,   225,  4429 }, // Mountain Standard Time / United States
    -    {     36,    69,  4458 }, // E. Africa Standard Time / Ethiopia
    -    {    130,   151,  4477 }, // W. Europe Standard Time / Netherlands
    -    {     95,   245,  4494 }, // SA Western Standard Time / Saint Martin
    -    {     48,   173,  4510 }, // GMT Standard Time / Portugal
    -    {     46,   124,  4541 }, // FLE Standard Time / Lithuania
    -    {    130,    82,  4556 }, // W. Europe Standard Time / Germany
    -    {     65,    77,  4586 }, // Marquesas Standard Time / French Polynesia
    -    {     80,   178,  4604 }, // North Asia Standard Time / Russia
    -    {     61,   112,  4639 }, // Line Islands Standard Time / Kiribati
    -    {     96,   200,  4658 }, // Saint Pierre Standard Time / Saint Pierre And Miquelon
    -    {     48,   104,  4675 }, // GMT Standard Time / Ireland
    -    {      5,   186,  4689 }, // Arab Standard Time / Saudi Arabia
    -    {     83,    43,  4701 }, // Pacific SA Standard Time / Chile
    -    {     91,   178,  4718 }, // Russia Time Zone 11 / Russia
    -    {     36,    48,  4745 }, // E. Africa Standard Time / Comoros
    -    {     95,   152,  4759 }, // SA Western Standard Time / Cura Sao
    -    {     38,   141,  4775 }, // E. Europe Standard Time / Moldova
    -    {     24,    22,  4791 }, // Central America Standard Time / Belize
    -    {    103,   195,  4806 }, // South Africa Standard Time / South Africa
    -    {    127,   178,  4826 }, // Vladivostok Standard Time / Russia
    -    {    122,     0,  4857 }, // UTC-02 / AnyCountry
    -    {    106,   207,  4867 }, // Syria Standard Time / Syria
    -    {     93,    76,  4881 }, // SA Eastern Standard Time / French Guiana
    -    {     50,   136,  4897 }, // Greenwich Standard Time / Mauritania
    -    {     41,     0,  4915 }, // Eastern Standard Time / AnyCountry
    -    {     16,    30,  4923 }, // Bahia Standard Time / Brazil
    -    {     40,    43,  4937 }, // Easter Island Standard Time / Chile
    -    {     93,     0,  4952 }, // SA Eastern Standard Time / AnyCountry
    -    {      9,   178,  4962 }, // Astrakhan Standard Time / Russia
    -    {     95,    30,  4996 }, // SA Western Standard Time / Brazil
    -    {     18,    20,  5049 }, // Belarus Standard Time / Belarus
    -    {     95,   181,  5062 }, // SA Western Standard Time / Saint Lucia
    -    {    129,     6,  5079 }, // W. Central Africa Standard Time / Angola
    -    {    129,   157,  5093 }, // W. Central Africa Standard Time / Nigeria
    -    {    130,     5,  5106 }, // W. Europe Standard Time / Andorra
    -    {     58,   178,  5121 }, // Kaliningrad Standard Time / Russia
    -    {     71,     0,  5140 }, // Mountain Standard Time / AnyCountry
    -    {     95,     7,  5148 }, // SA Western Standard Time / Anguilla
    -    {    124,   235,  5165 }, // UTC+12 / Wallis And Futuna Islands
    -    {      6,   223,  5180 }, // Arabian Standard Time / United Arab Emirates
    -    {     94,    40,  5191 }, // SA Pacific Standard Time / Cayman Islands
    -    {    101,   211,  5206 }, // SE Asia Standard Time / Thailand
    -    {     29,   193,  5219 }, // Central Pacific Standard Time / Solomon Islands
    -    {     47,    81,  5239 }, // Georgian Standard Time / Georgia
    -    {    101,    36,  5252 }, // SE Asia Standard Time / Cambodia
    -    {    132,   228,  5268 }, // West Asia Standard Time / Uzbekistan
    -    {     51,    56,  5297 }, // GTB Standard Time / Cyprus
    -    {     95,    88,  5325 }, // SA Western Standard Time / Guadeloupe
    -    {    101,   232,  5344 }, // SE Asia Standard Time / Vietnam
    -    {    113,   178,  5356 }, // Transbaikal Standard Time / Russia
    -    {     50,   121,  5367 }, // Greenwich Standard Time / Liberia
    -    {     95,   233,  5383 }, // SA Western Standard Time / British Virgin Islands
    -    {    129,    49,  5399 }, // W. Central Africa Standard Time / Congo Kinshasa
    -    {     97,   178,  5415 }, // Sakhalin Standard Time / Russia
    -    {    124,   226,  5429 }, // UTC+12 / United States Minor Outlying Islands
    -    {     50,    83,  5442 }, // Greenwich Standard Time / Ghana
    -    {     76,   154,  5455 }, // New Zealand Standard Time / New Zealand
    -    {     23,    13,  5472 }, // Cen. Australia Standard Time / Australia
    -    {     53,    77,  5513 }, // Hawaiian Standard Time / French Polynesia
    -    {     50,    34,  5528 }, // Greenwich Standard Time / Burkina Faso
    -    {    132,    78,  5547 }, // West Asia Standard Time / French Southern Territories
    -    {    121,     0,  5564 }, // UTC-08 / AnyCountry
    -    {     27,     2,  5574 }, // Central Europe Standard Time / Albania
    -    {    107,   208,  5588 }, // Taipei Standard Time / Taiwan
    -    {     88,    58,  5600 }, // Romance Standard Time / Denmark
    -    {     36,   221,  5618 }, // E. Africa Standard Time / Uganda
    -    {     95,    19,  5633 }, // SA Western Standard Time / Barbados
    -    {     14,    15,  5650 }, // Azerbaijan Standard Time / Azerbaijan
    -    {     32,    97,  5660 }, // China Standard Time / Hong Kong
    -    {    110,   101,  5675 }, // Tokyo Standard Time / Indonesia
    -    {     53,   225,  5689 }, // Hawaiian Standard Time / United States
    -    {     36,   111,  5706 }, // E. Africa Standard Time / Kenya
    -    {    134,    89,  5721 }, // West Pacific Standard Time / Guam
    -    {     36,   254,  5734 }, // E. Africa Standard Time / South Sudan
    -    {     48,    71,  5746 }, // GMT Standard Time / Faroe Islands
    -    {     90,   178,  5762 }, // Russia Time Zone 10 / Russia
    -    {    119,   158,  5781 }, // UTC-11 / Niue
    -    {    129,     3,  5794 }, // W. Central Africa Standard Time / Algeria
    -    {    110,    62,  5809 }, // Tokyo Standard Time / East Timor
    -    {     93,    30,  5819 }, // SA Eastern Standard Time / Brazil
    -    {     27,   242,  5898 }, // Central Europe Standard Time / Montenegro
    -    {    129,    37,  5915 }, // W. Central Africa Standard Time / Cameroon
    -    {    101,   117,  5929 }, // SE Asia Standard Time / Laos
    -    {     85,   139,  5944 }, // Pacific Standard Time (Mexico) / Mexico
    -    {     50,   212,  5981 }, // Greenwich Standard Time / Togo
    -    {     46,   118,  5993 }, // FLE Standard Time / Latvia
    -    {     95,    38,  6005 }, // SA Western Standard Time / Canada
    -    {    132,   209,  6026 }, // West Asia Standard Time / Tajikistan
    -    {     77,    38,  6040 }, // Newfoundland Standard Time / Canada
    -    {    110,   108,  6057 }, // Tokyo Standard Time / Japan
    -    {     25,     0,  6068 }, // Central Asia Standard Time / AnyCountry
    -    {     28,    27,  6078 }, // Central European Standard Time / Bosnia And Herzegowina
    -    {     27,   191,  6094 }, // Central Europe Standard Time / Slovakia
    -    {     95,    93,  6112 }, // SA Western Standard Time / Guyana
    -    {     48,   197,  6127 }, // GMT Standard Time / Spain
    -    {     19,   167,  6143 }, // Bougainville Standard Time / Papua New Guinea
    -    {      5,    17,  6164 }, // Arab Standard Time / Bahrain
    -    {     24,    90,  6177 }, // Central America Standard Time / Guatemala
    -    {     95,    26,  6195 }, // SA Western Standard Time / Bolivia
    -    {     81,   113,  6210 }, // North Korea Standard Time / North Korea
    -    {    119,     4,  6225 }, // UTC-11 / American Samoa
    -    {     66,   176,  6243 }, // Mauritius Standard Time / Reunion
    -    {    103,   120,  6258 }, // South Africa Standard Time / Lesotho
    -    {     84,     0,  6272 }, // Pacific Standard Time / AnyCountry
    -    {    120,     0,  6280 }, // UTC-09 / AnyCountry
    -    {    129,   216,  6290 }, // W. Central Africa Standard Time / Tunisia
    -    {     99,   185,  6303 }, // Sao Tome Standard Time / Sao Tome And Principe
    -    {    100,   178,  6319 }, // Saratov Standard Time / Russia
    -    {    105,   201,  6334 }, // Sudan Standard Time / Sudan
    -    {     48,   252,  6350 }, // GMT Standard Time / Jersey
    -    {     29,    13,  6364 }, // Central Pacific Standard Time / Australia
    -    {     71,   139,  6385 }, // Mountain Standard Time / Mexico
    -    {     21,    39,  6401 }, // Cape Verde Standard Time / Cape Verde
    -    {    102,   101,  6421 }, // Singapore Standard Time / Indonesia
    -    {     27,   192,  6435 }, // Central Europe Standard Time / Slovenia
    -    {     48,    75,  6452 }, // GMT Standard Time / Guernsey
    -    {    132,     8,  6468 }, // West Asia Standard Time / Antarctica
    -    {      8,    10,  6486 }, // Argentina Standard Time / Argentina
    -    {     98,   183,  6759 }, // Samoa Standard Time / Samoa
    -    {    129,    41,  6772 }, // W. Central Africa Standard Time / Central African Republic
    -    {    111,   178,  6786 }, // Tomsk Standard Time / Russia
    -    {    110,   164,  6797 }, // Tokyo Standard Time / Palau
    -    {     11,    13,  6811 }, // AUS Central Standard Time / Australia
    -    {    121,   171,  6828 }, // UTC-08 / Pitcairn
    -    {    102,    32,  6845 }, // Singapore Standard Time / Brunei
    -    {    112,   214,  6857 }, // Tonga Standard Time / Tonga
    -    {     89,   178,  6875 }, // Russia Time Zone 3 / Russia
    -    {    128,    13,  6889 }, // W. Australia Standard Time / Australia
    -    {     28,   172,  6905 }, // Central European Standard Time / Poland
    -    {     72,    46,  6919 }, // Myanmar Standard Time / Cocos Islands
    -    {     66,   188,  6932 }, // Mauritius Standard Time / Seychelles
    -    {     84,   225,  6944 }, // Pacific Standard Time / United States
    -    {     54,   100,  6983 }, // India Standard Time / India
    -    {     50,    53,  6997 }, // Greenwich Standard Time / Ivory Coast
    -    {     24,     0,  7012 }, // Central America Standard Time / AnyCountry
    -    {     29,   229,  7022 }, // Central Pacific Standard Time / Vanuatu
    -    {    130,   125,  7036 }, // W. Europe Standard Time / Luxembourg
    -    {     50,   132,  7054 }, // Greenwich Standard Time / Mali
    -    {    103,   179,  7068 }, // South Africa Standard Time / Rwanda
    -    {      5,   175,  7082 }, // Arab Standard Time / Qatar
    -    {     86,   163,  7093 }, // Pakistan Standard Time / Pakistan
    -    {    134,     0,  7106 }, // West Pacific Standard Time / AnyCountry
    -    {     36,    59,  7117 }, // E. Africa Standard Time / Djibouti
    -    {     44,   178,  7133 }, // Ekaterinburg Standard Time / Russia
    -    {    118,    38,  7152 }, // US Mountain Standard Time / Canada
    -    {     36,   138,  7209 }, // E. Africa Standard Time / Mayotte
    -    {     28,   127,  7224 }, // Central European Standard Time / Macedonia
    -    {     59,   114,  7238 }, // Korea Standard Time / South Korea
    -    {     93,   202,  7249 }, // SA Eastern Standard Time / Suriname
    -    {    130,   205,  7268 }, // W. Europe Standard Time / Sweden
    -    {    103,    49,  7285 }, // South Africa Standard Time / Congo Kinshasa
    -    {      0,     0,     0 } // Trailing zeroes
    -};
    -
    -// Windows ID Key, Windows ID Index, IANA ID Index, UTC Offset
    -static const QWindowsData windowsDataTable[] = {
    -    {      1,     0,  4141, 16200 }, // Afghanistan Standard Time
    -    {      2,    26,  7303,-32400 }, // Alaskan Standard Time
    -    {      3,    48,  4406,-36000 }, // Aleutian Standard Time
    -    {      4,    71,   325, 25200 }, // Altai Standard Time
    -    {      5,    91,  4689, 10800 }, // Arab Standard Time
    -    {      6,   110,  5180, 14400 }, // Arabian Standard Time
    -    {      7,   132,   953, 10800 }, // Arabic Standard Time
    -    {      8,   153,  7321,-10800 }, // Argentina Standard Time
    -    {      9,   177,  7342, 14400 }, // Astrakhan Standard Time
    -    {     10,   201,  7359,-14400 }, // Atlantic Standard Time
    -    {     11,   224,  6811, 34200 }, // AUS Central Standard Time
    -    {     12,   250,  2225, 31500 }, // Aus Central W. Standard Time
    -    {     13,   279,  7375, 36000 }, // AUS Eastern Standard Time
    -    {     14,   305,  5650, 14400 }, // Azerbaijan Standard Time
    -    {     15,   330,  4213, -3600 }, // Azores Standard Time
    -    {     16,   351,  4923,-10800 }, // Bahia Standard Time
    -    {     17,   371,  4239, 21600 }, // Bangladesh Standard Time
    -    {     18,   396,  5049, 10800 }, // Belarus Standard Time
    -    {     19,   418,  6143, 39600 }, // Bougainville Standard Time
    -    {     20,   445,  7392,-21600 }, // Canada Central Standard Time
    -    {     21,   474,  6401, -3600 }, // Cape Verde Standard Time
    -    {     22,   499,  1138, 14400 }, // Caucasus Standard Time
    -    {     23,   522,  7407, 34200 }, // Cen. Australia Standard Time
    -    {     24,   551,  6177,-21600 }, // Central America Standard Time
    -    {     25,   581,  7426, 21600 }, // Central Asia Standard Time
    -    {     26,   608,  7438,-14400 }, // Central Brazilian Standard Time
    -    {     27,   640,  3077,  3600 }, // Central Europe Standard Time
    -    {     28,   669,  6905,  3600 }, // Central European Standard Time
    -    {     29,   700,  5219, 39600 }, // Central Pacific Standard Time
    -    {     30,   730,  7453,-21600 }, // Central Standard Time (Mexico)
    -    {     31,   761,  7473,-21600 }, // Central Standard Time
    -    {     32,   783,    48, 28800 }, // China Standard Time
    -    {     33,   803,   114, 45900 }, // Chatham Islands Standard Time
    -    {     34,   833,  3258,-18000 }, // Cuba Standard Time
    -    {     35,   852,  4103,-43200 }, // Dateline Standard Time
    -    {     36,   875,  5706, 10800 }, // E. Africa Standard Time
    -    {     37,   899,  7489, 36000 }, // E. Australia Standard Time
    -    {     38,   926,  4775,  7200 }, // E. Europe Standard Time
    -    {     39,   950,   451,-10800 }, // E. South America Standard Time
    -    {     40,   981,  4937,-21600 }, // Easter Island Standard Time
    -    {     41,  1009,  7508,-18000 }, // Eastern Standard Time
    -    {     42,  1031,  2938,-18000 }, // Eastern Standard Time (Mexico)
    -    {     43,  1062,  2284,  7200 }, // Egypt Standard Time
    -    {     44,  1082,  7133, 18000 }, // Ekaterinburg Standard Time
    -    {     45,  1109,  3985, 43200 }, // Fiji Standard Time
    -    {     46,  1128,  7525,  7200 }, // FLE Standard Time
    -    {     47,  1146,  5239, 14400 }, // Georgian Standard Time
    -    {     48,  1169,  3180,     0 }, // GMT Standard Time
    -    {     49,  1187,  3029,-10800 }, // Greenland Standard Time
    -    {     50,  1211,  3239,     0 }, // Greenwich Standard Time
    -    {     51,  1235,  2332,  7200 }, // GTB Standard Time
    -    {     52,  1253,    25,-18000 }, // Haiti Standard Time
    -    {     53,  1273,  5689,-36000 }, // Hawaiian Standard Time
    -    {     54,  1296,  6983, 19800 }, // India Standard Time
    -    {     55,  1316,  1271, 12600 }, // Iran Standard Time
    -    {     56,  1335,  2192,  7200 }, // Israel Standard Time
    -    {     57,  1356,  1242,  7200 }, // Jordan Standard Time
    -    {     58,  1377,  5121,  7200 }, // Kaliningrad Standard Time
    -    {     59,  1403,  7238, 32400 }, // Korea Standard Time
    -    {     60,  1423,  3618,  7200 }, // Libya Standard Time
    -    {     61,  1443,  4639, 50400 }, // Line Islands Standard Time
    -    {     62,  1470,  3113, 37800 }, // Lord Howe Standard Time
    -    {     63,  1494,  2758, 36000 }, // Magadan Standard Time
    -    {     64,  1516,  1054,-10800 }, // Magallanes Standard Time
    -    {     65,  1541,  4586,-34200 }, // Marquesas Standard Time
    -    {     66,  1565,  1863, 14400 }, // Mauritius Standard Time
    -    {     67,  1589,  3665,  7200 }, // Middle East Standard Time
    -    {     68,  1615,  3194,-10800 }, // Montevideo Standard Time
    -    {     69,  1640,  2125,     0 }, // Morocco Standard Time
    -    {     70,  1662,  7537,-25200 }, // Mountain Standard Time (Mexico)
    -    {     71,  1694,  7555,-25200 }, // Mountain Standard Time
    -    {     72,  1717,   657, 23400 }, // Myanmar Standard Time
    -    {     73,  1739,  4351, 21600 }, // N. Central Asia Standard Time
    -    {     74,  1769,  3687,  3600 }, // Namibia Standard Time
    -    {     75,  1791,   793, 20700 }, // Nepal Standard Time
    -    {     76,  1811,  5455, 43200 }, // New Zealand Standard Time
    -    {     77,  1837,  6040,-12600 }, // Newfoundland Standard Time
    -    {     78,  1864,   752, 39600 }, // Norfolk Standard Time
    -    {     79,  1886,  2534, 28800 }, // North Asia East Standard Time
    -    {     80,  1916,  7570, 25200 }, // North Asia Standard Time
    -    {     81,  1941,  6210, 30600 }, // North Korea Standard Time
    -    {     82,  1967,  3608, 21600 }, // Omsk Standard Time
    -    {     83,  1986,  4701,-10800 }, // Pacific SA Standard Time
    -    {     84,  2011,  7587,-28800 }, // Pacific Standard Time
    -    {     85,  2033,  7607,-28800 }, // Pacific Standard Time (Mexico)
    -    {     86,  2064,  7093, 18000 }, // Pakistan Standard Time
    -    {     87,  2087,  1225,-14400 }, // Paraguay Standard Time
    -    {     88,  2110,   570,  3600 }, // Romance Standard Time
    -    {     89,  2132,  6875, 14400 }, // Russia Time Zone 3
    -    {     90,  2151,  5762, 39600 }, // Russia Time Zone 10
    -    {     91,  2171,  7623, 43200 }, // Russia Time Zone 11
    -    {     92,  2191,  7638, 10800 }, // Russian Standard Time
    -    {     93,  2213,  4881,-10800 }, // SA Eastern Standard Time
    -    {     94,  2238,  3524,-18000 }, // SA Pacific Standard Time
    -    {     95,  2263,  6195,-14400 }, // SA Western Standard Time
    -    {     96,  2288,  4658,-10800 }, // Saint Pierre Standard Time
    -    {     97,  2315,  5415, 39600 }, // Sakhalin Standard Time
    -    {     98,  2338,  6759, 46800 }, // Samoa Standard Time
    -    {     99,  2358,  6303,     0 }, // Sao Tome Standard Time
    -    {    100,  2381,  6319, 14400 }, // Saratov Standard Time
    -    {    101,  2403,  5206, 25200 }, // SE Asia Standard Time
    -    {    102,  2425,  3825, 28800 }, // Singapore Standard Time
    -    {    103,  2449,  4806,  7200 }, // South Africa Standard Time
    -    {    104,  2476,  1447, 19800 }, // Sri Lanka Standard Time
    -    {    105,  2500,  6334,  7200 }, // Sudan Standard Time
    -    {    106,  2520,  4867,  7200 }, // Syria Standard Time
    -    {    107,  2540,  5588, 28800 }, // Taipei Standard Time
    -    {    108,  2561,  7652, 36000 }, // Tasmania Standard Time
    -    {    109,  2584,  1253,-10800 }, // Tocantins Standard Time
    -    {    110,  2608,  6057, 32400 }, // Tokyo Standard Time
    -    {    111,  2628,  6786, 25200 }, // Tomsk Standard Time
    -    {    112,  2648,  6857, 46800 }, // Tonga Standard Time
    -    {    113,  2668,  5356, 32400 }, // Transbaikal Standard Time
    -    {    114,  2694,  4390,  7200 }, // Turkey Standard Time
    -    {    115,  2715,  2143,-14400 }, // Turks And Caicos Standard Time
    -    {    116,  2746,  7669, 28800 }, // Ulaanbaatar Standard Time
    -    {    117,  2772,  7686,-18000 }, // US Eastern Standard Time
    -    {    118,  2797,  3998,-25200 }, // US Mountain Standard Time
    -    {    119,  2823,  1075,-39600 }, // UTC-11
    -    {    120,  2830,  6280,-32400 }, // UTC-09
    -    {    121,  2837,  5564,-28800 }, // UTC-08
    -    {    122,  2844,  4857, -7200 }, // UTC-02
    -    {    123,  2851,  7707,     0 }, // UTC
    -    {    124,  2855,  3213, 43200 }, // UTC+12
    -    {    125,  2862,  1502, 46800 }, // UTC+13
    -    {    126,  2869,  3703,-16200 }, // Venezuela Standard Time
    -    {    127,  2893,  7715, 36000 }, // Vladivostok Standard Time
    -    {    128,  2919,  6889, 28800 }, // W. Australia Standard Time
    -    {    129,  2946,  5093,  3600 }, // W. Central Africa Standard Time
    -    {    130,  2978,  7732,  3600 }, // W. Europe Standard Time
    -    {    131,  3002,     0, 25200 }, // W. Mongolia Standard Time
    -    {    132,  3028,  7746, 18000 }, // West Asia Standard Time
    -    {    133,  3052,  7760,  7200 }, // West Bank Standard Time
    -    {    134,  3076,   377, 36000 }, // West Pacific Standard Time
    -    {    135,  3103,  7772, 32400 }, // Yakutsk Standard Time
    -    {      0,     0,     0,     0 } // Trailing zeroes
    -};
    -
    -// IANA ID Index, UTC Offset
    -static const QUtcData utcDataTable[] = {
    -    {   7785,     0 }, // UTC
    -    {   7789,-50400 }, // UTC-14:00
    -    {   7799,-46800 }, // UTC-13:00
    -    {   7809,-43200 }, // UTC-12:00
    -    {   7819,-39600 }, // UTC-11:00
    -    {   7829,-36000 }, // UTC-10:00
    -    {   7839,-32400 }, // UTC-09:00
    -    {   7849,-28800 }, // UTC-08:00
    -    {   7859,-25200 }, // UTC-07:00
    -    {   7869,-21600 }, // UTC-06:00
    -    {   7879,-18000 }, // UTC-05:00
    -    {   7889,-16200 }, // UTC-04:30
    -    {   7899,-14400 }, // UTC-04:00
    -    {   7909,-12600 }, // UTC-03:30
    -    {   7919,-10800 }, // UTC-03:00
    -    {   7929, -7200 }, // UTC-02:00
    -    {   7939, -3600 }, // UTC-01:00
    -    {   7949,     0 }, // UTC-00:00
    -    {   7959,     0 }, // UTC+00:00
    -    {   7969,  3600 }, // UTC+01:00
    -    {   7979,  7200 }, // UTC+02:00
    -    {   7989, 10800 }, // UTC+03:00
    -    {   7999, 12600 }, // UTC+03:30
    -    {   8009, 14400 }, // UTC+04:00
    -    {   8019, 16200 }, // UTC+04:30
    -    {   8029, 18000 }, // UTC+05:00
    -    {   8039, 19800 }, // UTC+05:30
    -    {   8049, 20700 }, // UTC+05:45
    -    {   8059, 21600 }, // UTC+06:00
    -    {   8069, 23400 }, // UTC+06:30
    -    {   8079, 25200 }, // UTC+07:00
    -    {   8089, 28800 }, // UTC+08:00
    -    {   8099, 30600 }, // UTC+08:30
    -    {   8109, 32400 }, // UTC+09:00
    -    {   8119, 34200 }, // UTC+09:30
    -    {   8129, 36000 }, // UTC+10:00
    -    {   8139, 39600 }, // UTC+11:00
    -    {   8149, 43200 }, // UTC+12:00
    -    {   8159, 46800 }, // UTC+13:00
    -    {   8169, 50400 }, // UTC+14:00
    -    {     0,      0 } // Trailing zeroes
    -};
    -
    -static const char windowsIdData[] = {
    -0x41, 0x66, 0x67, 0x68, 0x61, 0x6e, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
    -0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x6c, 0x61, 0x73, 0x6b, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
    -0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x6c, 0x65, 0x75, 0x74, 0x69, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61,
    -0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x6c, 0x74, 0x61, 0x69, 0x20, 0x53, 0x74, 0x61,
    -0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x72, 0x61, 0x62, 0x20, 0x53, 0x74, 0x61, 0x6e,
    -0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x72, 0x61, 0x62, 0x69, 0x61, 0x6e, 0x20, 0x53, 0x74,
    -0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x72, 0x61, 0x62, 0x69, 0x63, 0x20, 0x53,
    -0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69,
    -0x6e, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x73, 0x74,
    -0x72, 0x61, 0x6b, 0x68, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65,
    -0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54,
    -0x69, 0x6d, 0x65, 0x0, 0x41, 0x55, 0x53, 0x20, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x53, 0x74, 0x61, 0x6e,
    -0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x75, 0x73, 0x20, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61,
    -0x6c, 0x20, 0x57, 0x2e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41,
    -0x55, 0x53, 0x20, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
    -0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x7a, 0x65, 0x72, 0x62, 0x61, 0x69, 0x6a, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e,
    -0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x7a, 0x6f, 0x72, 0x65, 0x73, 0x20, 0x53, 0x74, 0x61,
    -0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x42, 0x61, 0x68, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61,
    -0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x42, 0x61, 0x6e, 0x67, 0x6c, 0x61, 0x64, 0x65, 0x73,
    -0x68, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x42, 0x65, 0x6c, 0x61,
    -0x72, 0x75, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x42, 0x6f,
    -0x75, 0x67, 0x61, 0x69, 0x6e, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
    -0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x20, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20,
    -0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x61, 0x70, 0x65, 0x20, 0x56,
    -0x65, 0x72, 0x64, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43,
    -0x61, 0x75, 0x63, 0x61, 0x73, 0x75, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d,
    -0x65, 0x0, 0x43, 0x65, 0x6e, 0x2e, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61,
    -0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41,
    -0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65,
    -0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
    -0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x42, 0x72, 0x61, 0x7a,
    -0x69, 0x6c, 0x69, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0,
    -0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
    -0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x45, 0x75, 0x72,
    -0x6f, 0x70, 0x65, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0,
    -0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53, 0x74, 0x61, 0x6e,
    -0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x53, 0x74,
    -0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x28, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x29,
    -0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
    -0x6d, 0x65, 0x0, 0x43, 0x68, 0x69, 0x6e, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
    -0x6d, 0x65, 0x0, 0x43, 0x68, 0x61, 0x74, 0x68, 0x61, 0x6d, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x53,
    -0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x75, 0x62, 0x61, 0x20, 0x53, 0x74,
    -0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x44, 0x61, 0x74, 0x65, 0x6c, 0x69, 0x6e, 0x65,
    -0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x2e, 0x20, 0x41, 0x66,
    -0x72, 0x69, 0x63, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45,
    -0x2e, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
    -0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x2e, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e,
    -0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x2e, 0x20, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x41,
    -0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65,
    -0x0, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
    -0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x53, 0x74, 0x61,
    -0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x53,
    -0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x28, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f,
    -0x29, 0x0, 0x45, 0x67, 0x79, 0x70, 0x74, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d,
    -0x65, 0x0, 0x45, 0x6b, 0x61, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x62, 0x75, 0x72, 0x67, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
    -0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x46, 0x69, 0x6a, 0x69, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
    -0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x46, 0x4c, 0x45, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
    -0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x47, 0x65, 0x6f, 0x72, 0x67, 0x69, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
    -0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x47, 0x4d, 0x54, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72,
    -0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x47, 0x72, 0x65, 0x65, 0x6e, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x74, 0x61,
    -0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x47, 0x72, 0x65, 0x65, 0x6e, 0x77, 0x69, 0x63, 0x68,
    -0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x47, 0x54, 0x42, 0x20, 0x53,
    -0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x48, 0x61, 0x69, 0x74, 0x69, 0x20, 0x53,
    -0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x48, 0x61, 0x77, 0x61, 0x69, 0x69, 0x61,
    -0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x49, 0x6e, 0x64, 0x69,
    -0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x49, 0x72, 0x61, 0x6e,
    -0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x49, 0x73, 0x72, 0x61, 0x65,
    -0x6c, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4a, 0x6f, 0x72, 0x64,
    -0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4b, 0x61, 0x6c,
    -0x69, 0x6e, 0x69, 0x6e, 0x67, 0x72, 0x61, 0x64, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
    -0x6d, 0x65, 0x0, 0x4b, 0x6f, 0x72, 0x65, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
    -0x6d, 0x65, 0x0, 0x4c, 0x69, 0x62, 0x79, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
    -0x6d, 0x65, 0x0, 0x4c, 0x69, 0x6e, 0x65, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e,
    -0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4c, 0x6f, 0x72, 0x64, 0x20, 0x48, 0x6f, 0x77, 0x65, 0x20,
    -0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x61, 0x67, 0x61, 0x64, 0x61,
    -0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x61, 0x67, 0x61,
    -0x6c, 0x6c, 0x61, 0x6e, 0x65, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65,
    -0x0, 0x4d, 0x61, 0x72, 0x71, 0x75, 0x65, 0x73, 0x61, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
    -0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x69, 0x75, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
    -0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x20, 0x45, 0x61, 0x73, 0x74,
    -0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x6f, 0x6e, 0x74, 0x65,
    -0x76, 0x69, 0x64, 0x65, 0x6f, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0,
    -0x4d, 0x6f, 0x72, 0x6f, 0x63, 0x63, 0x6f, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d,
    -0x65, 0x0, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
    -0x54, 0x69, 0x6d, 0x65, 0x20, 0x28, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x29, 0x0, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x61,
    -0x69, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x79, 0x61,
    -0x6e, 0x6d, 0x61, 0x72, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e,
    -0x2e, 0x20, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
    -0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x61, 0x6d, 0x69, 0x62, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61,
    -0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x65, 0x70, 0x61, 0x6c, 0x20, 0x53, 0x74, 0x61,
    -0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x65, 0x77, 0x20, 0x5a, 0x65, 0x61, 0x6c, 0x61,
    -0x6e, 0x64, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x65, 0x77,
    -0x66, 0x6f, 0x75, 0x6e, 0x64, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54,
    -0x69, 0x6d, 0x65, 0x0, 0x4e, 0x6f, 0x72, 0x66, 0x6f, 0x6c, 0x6b, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
    -0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x45, 0x61, 0x73,
    -0x74, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x6f, 0x72, 0x74,
    -0x68, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65,
    -0x0, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x4b, 0x6f, 0x72, 0x65, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72,
    -0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4f, 0x6d, 0x73, 0x6b, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
    -0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53, 0x41, 0x20, 0x53, 0x74, 0x61,
    -0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53,
    -0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
    -0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x28, 0x4d, 0x65, 0x78, 0x69,
    -0x63, 0x6f, 0x29, 0x0, 0x50, 0x61, 0x6b, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72,
    -0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x50, 0x61, 0x72, 0x61, 0x67, 0x75, 0x61, 0x79, 0x20, 0x53, 0x74, 0x61, 0x6e,
    -0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x52, 0x6f, 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x53, 0x74,
    -0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x52, 0x75, 0x73, 0x73, 0x69, 0x61, 0x20, 0x54,
    -0x69, 0x6d, 0x65, 0x20, 0x5a, 0x6f, 0x6e, 0x65, 0x20, 0x33, 0x0, 0x52, 0x75, 0x73, 0x73, 0x69, 0x61, 0x20, 0x54, 0x69,
    -0x6d, 0x65, 0x20, 0x5a, 0x6f, 0x6e, 0x65, 0x20, 0x31, 0x30, 0x0, 0x52, 0x75, 0x73, 0x73, 0x69, 0x61, 0x20, 0x54, 0x69,
    -0x6d, 0x65, 0x20, 0x5a, 0x6f, 0x6e, 0x65, 0x20, 0x31, 0x31, 0x0, 0x52, 0x75, 0x73, 0x73, 0x69, 0x61, 0x6e, 0x20, 0x53,
    -0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x41, 0x20, 0x45, 0x61, 0x73, 0x74,
    -0x65, 0x72, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x41,
    -0x20, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
    -0x6d, 0x65, 0x0, 0x53, 0x41, 0x20, 0x57, 0x65, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
    -0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x61, 0x69, 0x6e, 0x74, 0x20, 0x50, 0x69, 0x65, 0x72, 0x72, 0x65,
    -0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x61, 0x6b, 0x68, 0x61,
    -0x6c, 0x69, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x61,
    -0x6d, 0x6f, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x61,
    -0x6f, 0x20, 0x54, 0x6f, 0x6d, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65,
    -0x0, 0x53, 0x61, 0x72, 0x61, 0x74, 0x6f, 0x76, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
    -0x6d, 0x65, 0x0, 0x53, 0x45, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
    -0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
    -0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63,
    -0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x72, 0x69, 0x20,
    -0x4c, 0x61, 0x6e, 0x6b, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0,
    -0x53, 0x75, 0x64, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0,
    -0x53, 0x79, 0x72, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0,
    -0x54, 0x61, 0x69, 0x70, 0x65, 0x69, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65,
    -0x0, 0x54, 0x61, 0x73, 0x6d, 0x61, 0x6e, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54,
    -0x69, 0x6d, 0x65, 0x0, 0x54, 0x6f, 0x63, 0x61, 0x6e, 0x74, 0x69, 0x6e, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
    -0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x6f, 0x6b, 0x79, 0x6f, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
    -0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x6f, 0x6d, 0x73, 0x6b, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
    -0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x6f, 0x6e, 0x67, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
    -0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x62, 0x61, 0x69, 0x6b, 0x61, 0x6c, 0x20,
    -0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x75, 0x72, 0x6b, 0x65, 0x79,
    -0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x75, 0x72, 0x6b, 0x73,
    -0x20, 0x41, 0x6e, 0x64, 0x20, 0x43, 0x61, 0x69, 0x63, 0x6f, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
    -0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x55, 0x6c, 0x61, 0x61, 0x6e, 0x62, 0x61, 0x61, 0x74, 0x61, 0x72, 0x20, 0x53, 0x74,
    -0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x55, 0x53, 0x20, 0x45, 0x61, 0x73, 0x74, 0x65,
    -0x72, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x55, 0x53, 0x20,
    -0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
    -0x6d, 0x65, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x31, 0x31, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x39, 0x0, 0x55, 0x54, 0x43,
    -0x2d, 0x30, 0x38, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x32, 0x0, 0x55, 0x54, 0x43, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31,
    -0x32, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x33, 0x0, 0x56, 0x65, 0x6e, 0x65, 0x7a, 0x75, 0x65, 0x6c, 0x61, 0x20, 0x53,
    -0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x56, 0x6c, 0x61, 0x64, 0x69, 0x76, 0x6f,
    -0x73, 0x74, 0x6f, 0x6b, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57,
    -0x2e, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
    -0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x2e, 0x20, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x66, 0x72,
    -0x69, 0x63, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x2e,
    -0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d,
    -0x65, 0x0, 0x57, 0x2e, 0x20, 0x4d, 0x6f, 0x6e, 0x67, 0x6f, 0x6c, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
    -0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x65, 0x73, 0x74, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x53, 0x74,
    -0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x65, 0x73, 0x74, 0x20, 0x42, 0x61, 0x6e,
    -0x6b, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x65, 0x73, 0x74,
    -0x20, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
    -0x6d, 0x65, 0x0, 0x59, 0x61, 0x6b, 0x75, 0x74, 0x73, 0x6b, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
    -0x54, 0x69, 0x6d, 0x65, 0x0
    -};
    -
    -static const char ianaIdData[] = {
    -0x41, 0x73, 0x69, 0x61, 0x2f, 0x48, 0x6f, 0x76, 0x64, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x54, 0x61,
    -0x72, 0x61, 0x77, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x2d, 0x61, 0x75,
    -0x2d, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x68, 0x61, 0x6e, 0x67, 0x68, 0x61,
    -0x69, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x42, 0x61, 0x72, 0x74, 0x68, 0x65, 0x6c,
    -0x65, 0x6d, 0x79, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x69, 0x73, 0x68, 0x6b, 0x65, 0x6b, 0x0, 0x41, 0x6e, 0x74,
    -0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x79, 0x6f, 0x77, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69,
    -0x63, 0x2f, 0x43, 0x68, 0x61, 0x74, 0x68, 0x61, 0x6d, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f,
    -0x6e, 0x74, 0x73, 0x65, 0x72, 0x72, 0x61, 0x74, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x42,
    -0x72, 0x69, 0x73, 0x62, 0x61, 0x6e, 0x65, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x4c, 0x69,
    -0x6e, 0x64, 0x65, 0x6d, 0x61, 0x6e, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x34, 0x0, 0x41, 0x73,
    -0x69, 0x61, 0x2f, 0x41, 0x73, 0x68, 0x67, 0x61, 0x62, 0x61, 0x74, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
    -0x4e, 0x6f, 0x72, 0x6f, 0x6e, 0x68, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x6f, 0x73, 0x74,
    -0x61, 0x5f, 0x52, 0x69, 0x63, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x73, 0x6d, 0x65, 0x72, 0x61,
    -0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x73, 0x65, 0x79, 0x0, 0x41, 0x73,
    -0x69, 0x61, 0x2f, 0x4a, 0x61, 0x6b, 0x61, 0x72, 0x74, 0x61, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x50, 0x6f, 0x6e, 0x74,
    -0x69, 0x61, 0x6e, 0x61, 0x6b, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x6f, 0x74,
    -0x68, 0x65, 0x72, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x72, 0x6e, 0x61, 0x75, 0x6c, 0x0, 0x41, 0x6d,
    -0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x77, 0x65, 0x72, 0x5f, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x65, 0x73, 0x0,
    -0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x6f, 0x6d, 0x69, 0x6e, 0x69, 0x63, 0x61, 0x0, 0x50, 0x61, 0x63,
    -0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x5f, 0x4d, 0x6f, 0x72, 0x65, 0x73, 0x62, 0x79, 0x0, 0x41, 0x75,
    -0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x53, 0x79, 0x64, 0x6e, 0x65, 0x79, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72,
    -0x61, 0x6c, 0x69, 0x61, 0x2f, 0x4d, 0x65, 0x6c, 0x62, 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63,
    -0x61, 0x2f, 0x45, 0x6c, 0x5f, 0x41, 0x61, 0x69, 0x75, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53,
    -0x61, 0x6f, 0x5f, 0x50, 0x61, 0x75, 0x6c, 0x6f, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4d, 0x61, 0x6a,
    -0x75, 0x72, 0x6f, 0x20, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4b, 0x77, 0x61, 0x6a, 0x61, 0x6c, 0x65, 0x69,
    -0x6e, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x45, 0x6e, 0x64, 0x65, 0x72, 0x62, 0x75, 0x72, 0x79, 0x0,
    -0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x70, 0x75, 0x74, 0x6f, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
    -0x61, 0x2f, 0x52, 0x69, 0x6f, 0x5f, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
    -0x2f, 0x45, 0x69, 0x72, 0x75, 0x6e, 0x65, 0x70, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x50, 0x61, 0x72,
    -0x69, 0x73, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45, 0x64, 0x6d, 0x6f, 0x6e, 0x74, 0x6f, 0x6e, 0x20,
    -0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x5f, 0x42, 0x61,
    -0x79, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x75, 0x76, 0x69, 0x6b, 0x20, 0x41, 0x6d, 0x65,
    -0x72, 0x69, 0x63, 0x61, 0x2f, 0x59, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6b, 0x6e, 0x69, 0x66, 0x65, 0x0, 0x41, 0x73, 0x69,
    -0x61, 0x2f, 0x52, 0x61, 0x6e, 0x67, 0x6f, 0x6f, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x75,
    -0x69, 0x61, 0x62, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x6d, 0x70, 0x6f, 0x5f, 0x47,
    -0x72, 0x61, 0x6e, 0x64, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, 0x61, 0x64, 0x75, 0x7a, 0x0, 0x45,
    -0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x48, 0x65, 0x6c, 0x73, 0x69, 0x6e, 0x6b, 0x69, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e,
    -0x74, 0x69, 0x63, 0x2f, 0x53, 0x74, 0x61, 0x6e, 0x6c, 0x65, 0x79, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f,
    -0x4e, 0x6f, 0x72, 0x66, 0x6f, 0x6c, 0x6b, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x31, 0x30, 0x0, 0x45,
    -0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x5a, 0x61, 0x67, 0x72, 0x65, 0x62, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61,
    -0x74, 0x6d, 0x61, 0x6e, 0x64, 0x75, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x6f, 0x66, 0x69, 0x61, 0x0,
    -0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x75, 0x73, 0x63, 0x61, 0x74, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4d,
    -0x61, 0x6c, 0x64, 0x69, 0x76, 0x65, 0x73, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x61, 0x64, 0x72, 0x69,
    -0x64, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x65, 0x75, 0x74, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63,
    -0x61, 0x2f, 0x43, 0x6f, 0x6e, 0x61, 0x6b, 0x72, 0x79, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x64, 0x65, 0x6e, 0x0,
    -0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x69, 0x6d, 0x66, 0x65, 0x72, 0x6f, 0x70, 0x6f, 0x6c, 0x0, 0x41, 0x66,
    -0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x62, 0x61, 0x62, 0x61, 0x6e, 0x65, 0x0, 0x41, 0x72, 0x63, 0x74, 0x69, 0x63, 0x2f,
    -0x4c, 0x6f, 0x6e, 0x67, 0x79, 0x65, 0x61, 0x72, 0x62, 0x79, 0x65, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61,
    -0x67, 0x68, 0x64, 0x61, 0x64, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4d, 0x69, 0x64, 0x77, 0x61, 0x79,
    -0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x75, 0x77, 0x61, 0x69, 0x74, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f,
    -0x46, 0x72, 0x65, 0x65, 0x74, 0x6f, 0x77, 0x6e, 0x0, 0x43, 0x53, 0x54, 0x36, 0x43, 0x44, 0x54, 0x0, 0x50, 0x61, 0x63,
    -0x69, 0x66, 0x69, 0x63, 0x2f, 0x52, 0x61, 0x72, 0x6f, 0x74, 0x6f, 0x6e, 0x67, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63,
    -0x61, 0x2f, 0x42, 0x72, 0x61, 0x7a, 0x7a, 0x61, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
    -0x61, 0x2f, 0x50, 0x75, 0x6e, 0x74, 0x61, 0x5f, 0x41, 0x72, 0x65, 0x6e, 0x61, 0x73, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47,
    -0x4d, 0x54, 0x2b, 0x31, 0x31, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x56, 0x61, 0x6e, 0x63, 0x6f, 0x75,
    -0x76, 0x65, 0x72, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x77, 0x73, 0x6f, 0x6e, 0x20, 0x41,
    -0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x57, 0x68, 0x69, 0x74, 0x65, 0x68, 0x6f, 0x72, 0x73, 0x65, 0x0, 0x41, 0x73,
    -0x69, 0x61, 0x2f, 0x59, 0x65, 0x72, 0x65, 0x76, 0x61, 0x6e, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x6f,
    -0x6e, 0x61, 0x63, 0x6f, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x75, 0x73, 0x61, 0x6b, 0x61, 0x0, 0x45,
    -0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4b, 0x69, 0x65, 0x76, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x55, 0x7a,
    -0x68, 0x67, 0x6f, 0x72, 0x6f, 0x64, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x5a, 0x61, 0x70, 0x6f, 0x72, 0x6f,
    -0x7a, 0x68, 0x79, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x73, 0x75, 0x6e, 0x63, 0x69, 0x6f,
    -0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x6d, 0x6d, 0x61, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
    -0x2f, 0x41, 0x72, 0x61, 0x67, 0x75, 0x61, 0x69, 0x6e, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x65, 0x68, 0x72,
    -0x61, 0x6e, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x76, 0x69, 0x73, 0x0,
    -0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x50, 0x72, 0x61, 0x67, 0x75, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
    -0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x5f, 0x6f, 0x66, 0x5f, 0x53, 0x70, 0x61, 0x69, 0x6e, 0x0, 0x41, 0x66, 0x72, 0x69,
    -0x63, 0x61, 0x2f, 0x47, 0x61, 0x62, 0x6f, 0x72, 0x6f, 0x6e, 0x65, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d,
    -0x35, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x75, 0x61, 0x79, 0x61, 0x71, 0x75, 0x69, 0x6c, 0x0,
    -0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x41, 0x74, 0x68, 0x65, 0x6e, 0x73, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e,
    -0x2f, 0x41, 0x6e, 0x74, 0x61, 0x6e, 0x61, 0x6e, 0x61, 0x72, 0x69, 0x76, 0x6f, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69,
    -0x63, 0x2f, 0x4a, 0x6f, 0x68, 0x6e, 0x73, 0x74, 0x6f, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a,
    -0x61, 0x6d, 0x61, 0x69, 0x63, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x43, 0x6f, 0x6c, 0x6f, 0x6d, 0x62, 0x6f, 0x0,
    -0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x65, 0x6c, 0x67, 0x72, 0x61, 0x64, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61,
    -0x2f, 0x41, 0x6c, 0x6d, 0x61, 0x74, 0x79, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x51, 0x6f, 0x73, 0x74, 0x61, 0x6e, 0x61,
    -0x79, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x33, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
    -0x2f, 0x43, 0x6f, 0x72, 0x61, 0x6c, 0x5f, 0x48, 0x61, 0x72, 0x62, 0x6f, 0x75, 0x72, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61,
    -0x6e, 0x2f, 0x43, 0x68, 0x61, 0x67, 0x6f, 0x73, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x48,
    -0x6f, 0x62, 0x61, 0x72, 0x74, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x43, 0x75, 0x72, 0x72,
    -0x69, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x75, 0x65, 0x72, 0x74, 0x6f, 0x5f, 0x52, 0x69,
    -0x63, 0x6f, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x4b, 0x69, 0x74, 0x74, 0x73, 0x0,
    -0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x5a, 0x75, 0x72, 0x69, 0x63, 0x68, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
    -0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x70, 0x6f, 0x6c, 0x69, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69,
    -0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x4d, 0x61, 0x72, 0x65, 0x6e, 0x67, 0x6f, 0x20, 0x41,
    -0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x56, 0x65, 0x76, 0x61, 0x79,
    -0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x6f, 0x6e, 0x61, 0x70, 0x65, 0x20, 0x50, 0x61, 0x63, 0x69,
    -0x66, 0x69, 0x63, 0x2f, 0x4b, 0x6f, 0x73, 0x72, 0x61, 0x65, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x47,
    -0x61, 0x6d, 0x62, 0x69, 0x65, 0x72, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x69, 0x61, 0x6d, 0x65, 0x79,
    -0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x65, 0x72, 0x6d, 0x6f, 0x73, 0x69, 0x6c, 0x6c, 0x6f, 0x0,
    -0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x67, 0x61, 0x64, 0x69, 0x73, 0x68, 0x75, 0x0, 0x45, 0x74, 0x63,
    -0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x37, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x42, 0x65, 0x72, 0x6d,
    -0x75, 0x64, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x72, 0x61, 0x72, 0x65, 0x0, 0x41, 0x73,
    -0x69, 0x61, 0x2f, 0x4d, 0x61, 0x63, 0x61, 0x75, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x6c, 0x61,
    -0x62, 0x6f, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x69, 0x75, 0x73, 0x0,
    -0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x54, 0x61, 0x6c, 0x6c, 0x69, 0x6e, 0x6e, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63,
    -0x61, 0x2f, 0x44, 0x61, 0x6b, 0x61, 0x72, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4f, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x73,
    -0x69, 0x61, 0x2f, 0x41, 0x71, 0x74, 0x61, 0x75, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x71, 0x74, 0x6f, 0x62, 0x65,
    -0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x74, 0x79, 0x72, 0x61, 0x75, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x51, 0x79,
    -0x7a, 0x79, 0x6c, 0x6f, 0x72, 0x64, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x72, 0x75, 0x6d, 0x71, 0x69, 0x0,
    -0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x52, 0x6f, 0x6d, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x49,
    -0x73, 0x6c, 0x65, 0x5f, 0x6f, 0x66, 0x5f, 0x4d, 0x61, 0x6e, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61,
    -0x72, 0x5f, 0x65, 0x73, 0x5f, 0x53, 0x61, 0x6c, 0x61, 0x61, 0x6d, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
    -0x54, 0x68, 0x75, 0x6c, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x6e, 0x6d, 0x61, 0x72,
    -0x6b, 0x73, 0x68, 0x61, 0x76, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x65, 0x67, 0x69, 0x6e,
    -0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x77, 0x69, 0x66, 0x74, 0x5f, 0x43, 0x75, 0x72, 0x72,
    -0x65, 0x6e, 0x74, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x62, 0x79,
    -0x73, 0x75, 0x6e, 0x64, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x73, 0x61, 0x62, 0x6c, 0x61, 0x6e,
    -0x63, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x72, 0x61, 0x6e, 0x64, 0x5f, 0x54, 0x75, 0x72,
    -0x6b, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x6e, 0x6a, 0x75, 0x6c, 0x0, 0x41, 0x66, 0x72, 0x69,
    -0x63, 0x61, 0x2f, 0x4e, 0x64, 0x6a, 0x61, 0x6d, 0x65, 0x6e, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4a, 0x65, 0x72,
    -0x75, 0x73, 0x61, 0x6c, 0x65, 0x6d, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x61,
    -0x6c, 0x6d, 0x65, 0x72, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x45, 0x75, 0x63, 0x6c, 0x61,
    -0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x75, 0x61, 0x0, 0x41, 0x73, 0x69,
    -0x61, 0x2f, 0x4d, 0x61, 0x6e, 0x69, 0x6c, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x53, 0x61, 0x69,
    -0x70, 0x61, 0x6e, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x69, 0x72, 0x6f, 0x0, 0x45, 0x75, 0x72,
    -0x6f, 0x70, 0x65, 0x2f, 0x42, 0x72, 0x75, 0x73, 0x73, 0x65, 0x6c, 0x73, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74,
    -0x69, 0x63, 0x61, 0x2f, 0x4d, 0x63, 0x4d, 0x75, 0x72, 0x64, 0x6f, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42,
    -0x75, 0x63, 0x68, 0x61, 0x72, 0x65, 0x73, 0x74, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x32, 0x0, 0x41,
    -0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x65, 0x77, 0x5f, 0x59, 0x6f, 0x72, 0x6b, 0x20, 0x41, 0x6d, 0x65, 0x72,
    -0x69, 0x63, 0x61, 0x2f, 0x44, 0x65, 0x74, 0x72, 0x6f, 0x69, 0x74, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
    -0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x50, 0x65, 0x74, 0x65, 0x72, 0x73, 0x62, 0x75, 0x72, 0x67, 0x20, 0x41,
    -0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x56, 0x69, 0x6e, 0x63, 0x65,
    -0x6e, 0x6e, 0x65, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61,
    -0x2f, 0x57, 0x69, 0x6e, 0x61, 0x6d, 0x61, 0x63, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x65, 0x6e,
    -0x74, 0x75, 0x63, 0x6b, 0x79, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x69, 0x63, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x41, 0x6d, 0x65,
    -0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x75, 0x69, 0x73, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0, 0x41, 0x66, 0x72, 0x69,
    -0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x6f, 0x2d, 0x4e, 0x6f, 0x76, 0x6f, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x49,
    -0x72, 0x6b, 0x75, 0x74, 0x73, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x6c, 0x61, 0x61, 0x6e, 0x62, 0x61, 0x61,
    -0x74, 0x61, 0x72, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x43, 0x68, 0x6f, 0x69, 0x62, 0x61, 0x6c, 0x73, 0x61, 0x6e, 0x0,
    -0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, 0x69, 0x65, 0x6e, 0x6e, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
    -0x61, 0x2f, 0x54, 0x6f, 0x72, 0x6f, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x71,
    -0x61, 0x6c, 0x75, 0x69, 0x74, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x72, 0x65,
    -0x61, 0x6c, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x69, 0x70, 0x69, 0x67, 0x6f, 0x6e, 0x20, 0x41,
    -0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x61, 0x6e, 0x67, 0x6e, 0x69, 0x72, 0x74, 0x75, 0x6e, 0x67, 0x20, 0x41,
    -0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x68, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x42, 0x61, 0x79, 0x0, 0x41,
    -0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x72, 0x61, 0x6c, 0x65, 0x6e, 0x64, 0x69, 0x6a, 0x6b, 0x0, 0x50, 0x61,
    -0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4e, 0x61, 0x75, 0x72, 0x75, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69,
    -0x63, 0x61, 0x2f, 0x44, 0x75, 0x6d, 0x6f, 0x6e, 0x74, 0x44, 0x55, 0x72, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0, 0x41, 0x73,
    -0x69, 0x61, 0x2f, 0x4d, 0x61, 0x67, 0x61, 0x64, 0x61, 0x6e, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4f, 0x73,
    -0x6c, 0x6f, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x39, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
    -0x2f, 0x47, 0x61, 0x6c, 0x61, 0x70, 0x61, 0x67, 0x6f, 0x73, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x75,
    -0x6a, 0x75, 0x6d, 0x62, 0x75, 0x72, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x6c, 0x69,
    -0x66, 0x61, 0x78, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x6c, 0x61, 0x63, 0x65, 0x5f, 0x42, 0x61,
    -0x79, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x6f, 0x6f, 0x73, 0x65, 0x5f, 0x42, 0x61, 0x79, 0x20,
    -0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x63, 0x74, 0x6f, 0x6e, 0x0, 0x45, 0x74, 0x63, 0x2f,
    -0x47, 0x4d, 0x54, 0x2d, 0x31, 0x31, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x72, 0x65, 0x6e, 0x61,
    -0x64, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4e, 0x6f, 0x75, 0x6d, 0x65, 0x61, 0x0, 0x41, 0x6d,
    -0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x6e, 0x63, 0x75, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
    -0x2f, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a,
    -0x75, 0x6e, 0x65, 0x61, 0x75, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x6d, 0x65, 0x20, 0x41,
    -0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x69, 0x74, 0x6b, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
    -0x2f, 0x59, 0x61, 0x6b, 0x75, 0x74, 0x61, 0x74, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x6f, 0x64,
    -0x74, 0x68, 0x61, 0x62, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x69, 0x73, 0x73, 0x61, 0x75, 0x0, 0x45,
    -0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x6e, 0x5f, 0x4d, 0x61, 0x72, 0x69, 0x6e, 0x6f, 0x0, 0x45, 0x75, 0x72,
    -0x6f, 0x70, 0x65, 0x2f, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, 0x73, 0x74, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
    -0x2f, 0x54, 0x65, 0x67, 0x75, 0x63, 0x69, 0x67, 0x61, 0x6c, 0x70, 0x61, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c,
    -0x69, 0x61, 0x2f, 0x4c, 0x6f, 0x72, 0x64, 0x5f, 0x48, 0x6f, 0x77, 0x65, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54,
    -0x2d, 0x33, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x69, 0x62, 0x72, 0x65, 0x76, 0x69, 0x6c, 0x6c, 0x65,
    -0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x56, 0x69, 0x6e, 0x63, 0x65, 0x6e, 0x74, 0x0,
    -0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x6f, 0x6e, 0x64, 0x6f, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
    -0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x65, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54,
    -0x2d, 0x31, 0x32, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, 0x61, 0x74, 0x69, 0x63, 0x61, 0x6e, 0x0, 0x41,
    -0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x52, 0x65, 0x79, 0x6b, 0x6a, 0x61, 0x76, 0x69, 0x6b, 0x0, 0x41, 0x6d,
    -0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x76, 0x61, 0x6e, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
    -0x2f, 0x4e, 0x61, 0x73, 0x73, 0x61, 0x75, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x53, 0x6f, 0x75,
    -0x74, 0x68, 0x5f, 0x47, 0x65, 0x6f, 0x72, 0x67, 0x69, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45,
    -0x6c, 0x5f, 0x53, 0x61, 0x6c, 0x76, 0x61, 0x64, 0x6f, 0x72, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43,
    -0x68, 0x69, 0x63, 0x61, 0x67, 0x6f, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61,
    -0x6e, 0x61, 0x2f, 0x4b, 0x6e, 0x6f, 0x78, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69,
    -0x61, 0x6e, 0x61, 0x2f, 0x54, 0x65, 0x6c, 0x6c, 0x5f, 0x43, 0x69, 0x74, 0x79, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
    -0x61, 0x2f, 0x4d, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x6e, 0x65, 0x65, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
    -0x4e, 0x6f, 0x72, 0x74, 0x68, 0x5f, 0x44, 0x61, 0x6b, 0x6f, 0x74, 0x61, 0x2f, 0x42, 0x65, 0x75, 0x6c, 0x61, 0x68, 0x20,
    -0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x5f, 0x44, 0x61, 0x6b, 0x6f, 0x74, 0x61,
    -0x2f, 0x43, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x72, 0x74,
    -0x68, 0x5f, 0x44, 0x61, 0x6b, 0x6f, 0x74, 0x61, 0x2f, 0x4e, 0x65, 0x77, 0x5f, 0x53, 0x61, 0x6c, 0x65, 0x6d, 0x0, 0x45,
    -0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x34, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x61, 0x6e,
    -0x61, 0x6d, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6f, 0x67, 0x6f, 0x74, 0x61, 0x0, 0x41,
    -0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x68, 0x75, 0x61, 0x68, 0x75, 0x61, 0x20, 0x41, 0x6d, 0x65,
    -0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x7a, 0x61, 0x74, 0x6c, 0x61, 0x6e, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69,
    -0x63, 0x2f, 0x46, 0x75, 0x6e, 0x61, 0x66, 0x75, 0x74, 0x69, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x47, 0x69,
    -0x62, 0x72, 0x61, 0x6c, 0x74, 0x61, 0x72, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4f, 0x6d, 0x73, 0x6b, 0x0, 0x41, 0x66,
    -0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x72, 0x69, 0x70, 0x6f, 0x6c, 0x69, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74,
    -0x69, 0x63, 0x61, 0x2f, 0x56, 0x6f, 0x73, 0x74, 0x6f, 0x6b, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41,
    -0x72, 0x75, 0x62, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x65, 0x69, 0x72, 0x75, 0x74, 0x0, 0x45, 0x74, 0x63,
    -0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x38, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x57, 0x69, 0x6e, 0x64, 0x68, 0x6f,
    -0x65, 0x6b, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x72, 0x61, 0x63, 0x61, 0x73, 0x0, 0x41,
    -0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x54, 0x68, 0x6f, 0x6d, 0x61, 0x73, 0x0, 0x45, 0x74, 0x63,
    -0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x31, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x6e, 0x74, 0x69, 0x67,
    -0x75, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x69, 0x6d, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f,
    -0x70, 0x65, 0x2f, 0x4d, 0x61, 0x72, 0x69, 0x65, 0x68, 0x61, 0x6d, 0x6e, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69,
    -0x63, 0x2f, 0x53, 0x74, 0x5f, 0x48, 0x65, 0x6c, 0x65, 0x6e, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f,
    -0x54, 0x72, 0x75, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x0,
    -0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x6f, 0x5f, 0x44, 0x6f, 0x6d, 0x69, 0x6e, 0x67,
    -0x6f, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6c, 0x61, 0x6e, 0x74, 0x79, 0x72, 0x65, 0x0, 0x41, 0x6d,
    -0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x5f, 0x43, 0x69, 0x74, 0x79, 0x20, 0x41, 0x6d,
    -0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x68, 0x69, 0x61, 0x5f, 0x42, 0x61, 0x6e, 0x64, 0x65, 0x72, 0x61, 0x73,
    -0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x72, 0x69, 0x64, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72,
    -0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x65, 0x79, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b,
    -0x75, 0x61, 0x6c, 0x61, 0x5f, 0x4c, 0x75, 0x6d, 0x70, 0x75, 0x72, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x75, 0x63,
    -0x68, 0x69, 0x6e, 0x67, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x46, 0x69, 0x6a, 0x69, 0x0, 0x41, 0x6d,
    -0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x68, 0x6f, 0x65, 0x6e, 0x69, 0x78, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54,
    -0x68, 0x69, 0x6d, 0x70, 0x68, 0x75, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x61, 0x6c, 0x74, 0x61, 0x0,
    -0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x6f, 0x73, 0x63, 0x6f, 0x77, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
    -0x2f, 0x4b, 0x69, 0x72, 0x6f, 0x76, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, 0x6f, 0x6c, 0x67, 0x6f, 0x67,
    -0x72, 0x61, 0x64, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x72, 0x74, 0x69, 0x6e, 0x69, 0x71,
    -0x75, 0x65, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x31, 0x32, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x59,
    -0x61, 0x6b, 0x75, 0x74, 0x73, 0x6b, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x68, 0x61, 0x6e, 0x64, 0x79, 0x67, 0x61,
    -0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x62, 0x75, 0x6c, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x20,
    -0x45, 0x74, 0x63, 0x2f, 0x55, 0x54, 0x43, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x74, 0x61,
    -0x6d, 0x6f, 0x72, 0x6f, 0x73, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x34, 0x0, 0x49, 0x6e, 0x64, 0x69,
    -0x61, 0x6e, 0x2f, 0x43, 0x68, 0x72, 0x69, 0x73, 0x74, 0x6d, 0x61, 0x73, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69,
    -0x63, 0x2f, 0x41, 0x7a, 0x6f, 0x72, 0x65, 0x73, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x0, 0x41,
    -0x73, 0x69, 0x61, 0x2f, 0x44, 0x68, 0x61, 0x6b, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x57, 0x69,
    -0x6e, 0x6e, 0x69, 0x70, 0x65, 0x67, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x61, 0x69, 0x6e, 0x79,
    -0x5f, 0x52, 0x69, 0x76, 0x65, 0x72, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x61, 0x6e, 0x6b, 0x69,
    -0x6e, 0x5f, 0x49, 0x6e, 0x6c, 0x65, 0x74, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x65, 0x73, 0x6f,
    -0x6c, 0x75, 0x74, 0x65, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x35, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66,
    -0x69, 0x63, 0x2f, 0x46, 0x61, 0x6b, 0x61, 0x6f, 0x66, 0x6f, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4e, 0x6f, 0x76, 0x6f,
    -0x73, 0x69, 0x62, 0x69, 0x72, 0x73, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x48, 0x65, 0x62, 0x72, 0x6f, 0x6e, 0x20,
    -0x41, 0x73, 0x69, 0x61, 0x2f, 0x47, 0x61, 0x7a, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x49, 0x73, 0x74,
    -0x61, 0x6e, 0x62, 0x75, 0x6c, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x64, 0x61, 0x6b, 0x0, 0x45,
    -0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x37, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x65, 0x6e,
    -0x76, 0x65, 0x72, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6f, 0x69, 0x73, 0x65, 0x0, 0x41, 0x66,
    -0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x64, 0x64, 0x69, 0x73, 0x5f, 0x41, 0x62, 0x61, 0x62, 0x61, 0x0, 0x45, 0x75, 0x72,
    -0x6f, 0x70, 0x65, 0x2f, 0x41, 0x6d, 0x73, 0x74, 0x65, 0x72, 0x64, 0x61, 0x6d, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
    -0x61, 0x2f, 0x4d, 0x61, 0x72, 0x69, 0x67, 0x6f, 0x74, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x69, 0x73,
    -0x62, 0x6f, 0x6e, 0x20, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x4d, 0x61, 0x64, 0x65, 0x69, 0x72, 0x61,
    -0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, 0x69, 0x6c, 0x6e, 0x69, 0x75, 0x73, 0x0, 0x45, 0x75, 0x72, 0x6f,
    -0x70, 0x65, 0x2f, 0x42, 0x65, 0x72, 0x6c, 0x69, 0x6e, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x75, 0x73,
    -0x69, 0x6e, 0x67, 0x65, 0x6e, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4d, 0x61, 0x72, 0x71, 0x75, 0x65,
    -0x73, 0x61, 0x73, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x72, 0x61, 0x73, 0x6e, 0x6f, 0x79, 0x61, 0x72, 0x73, 0x6b,
    -0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4e, 0x6f, 0x76, 0x6f, 0x6b, 0x75, 0x7a, 0x6e, 0x65, 0x74, 0x73, 0x6b, 0x0, 0x50,
    -0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4b, 0x69, 0x72, 0x69, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x0, 0x41, 0x6d,
    -0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x69, 0x71, 0x75, 0x65, 0x6c, 0x6f, 0x6e, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70,
    -0x65, 0x2f, 0x44, 0x75, 0x62, 0x6c, 0x69, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x52, 0x69, 0x79, 0x61, 0x64, 0x68,
    -0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x69, 0x61, 0x67, 0x6f, 0x0, 0x41, 0x73,
    -0x69, 0x61, 0x2f, 0x4b, 0x61, 0x6d, 0x63, 0x68, 0x61, 0x74, 0x6b, 0x61, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x6e,
    -0x61, 0x64, 0x79, 0x72, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x43, 0x6f, 0x6d, 0x6f, 0x72, 0x6f, 0x0, 0x41,
    -0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x75, 0x72, 0x61, 0x63, 0x61, 0x6f, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70,
    -0x65, 0x2f, 0x43, 0x68, 0x69, 0x73, 0x69, 0x6e, 0x61, 0x75, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42,
    -0x65, 0x6c, 0x69, 0x7a, 0x65, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a, 0x6f, 0x68, 0x61, 0x6e, 0x6e, 0x65,
    -0x73, 0x62, 0x75, 0x72, 0x67, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x56, 0x6c, 0x61, 0x64, 0x69, 0x76, 0x6f, 0x73, 0x74,
    -0x6f, 0x6b, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x73, 0x74, 0x2d, 0x4e, 0x65, 0x72, 0x61, 0x0, 0x45, 0x74, 0x63,
    -0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x32, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x61, 0x6d, 0x61, 0x73, 0x63, 0x75, 0x73,
    -0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x79, 0x65, 0x6e, 0x6e, 0x65, 0x0, 0x41, 0x66, 0x72,
    -0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x75, 0x61, 0x6b, 0x63, 0x68, 0x6f, 0x74, 0x74, 0x0, 0x45, 0x53, 0x54, 0x35, 0x45,
    -0x44, 0x54, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x68, 0x69, 0x61, 0x0, 0x50, 0x61, 0x63,
    -0x69, 0x66, 0x69, 0x63, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b,
    -0x33, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x41, 0x73, 0x74, 0x72, 0x61, 0x6b, 0x68, 0x61, 0x6e, 0x20, 0x45,
    -0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x55, 0x6c, 0x79, 0x61, 0x6e, 0x6f, 0x76, 0x73, 0x6b, 0x0, 0x41, 0x6d, 0x65, 0x72,
    -0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x6e, 0x61, 0x75, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42,
    -0x6f, 0x61, 0x5f, 0x56, 0x69, 0x73, 0x74, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72,
    -0x74, 0x6f, 0x5f, 0x56, 0x65, 0x6c, 0x68, 0x6f, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x69, 0x6e, 0x73,
    -0x6b, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x4c, 0x75, 0x63, 0x69, 0x61, 0x0, 0x41,
    -0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x75, 0x61, 0x6e, 0x64, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f,
    -0x4c, 0x61, 0x67, 0x6f, 0x73, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x41, 0x6e, 0x64, 0x6f, 0x72, 0x72, 0x61,
    -0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4b, 0x61, 0x6c, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x72, 0x61, 0x64, 0x0,
    -0x4d, 0x53, 0x54, 0x37, 0x4d, 0x44, 0x54, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x6e, 0x67, 0x75,
    -0x69, 0x6c, 0x6c, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x57, 0x61, 0x6c, 0x6c, 0x69, 0x73, 0x0,
    -0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x75, 0x62, 0x61, 0x69, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43,
    -0x61, 0x79, 0x6d, 0x61, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x6e, 0x67, 0x6b, 0x6f, 0x6b, 0x0, 0x50,
    -0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x47, 0x75, 0x61, 0x64, 0x61, 0x6c, 0x63, 0x61, 0x6e, 0x61, 0x6c, 0x0, 0x41,
    -0x73, 0x69, 0x61, 0x2f, 0x54, 0x62, 0x69, 0x6c, 0x69, 0x73, 0x69, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x50, 0x68, 0x6e,
    -0x6f, 0x6d, 0x5f, 0x50, 0x65, 0x6e, 0x68, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x73, 0x68, 0x6b, 0x65, 0x6e,
    -0x74, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x61, 0x6d, 0x61, 0x72, 0x6b, 0x61, 0x6e, 0x64, 0x0, 0x41, 0x73, 0x69,
    -0x61, 0x2f, 0x46, 0x61, 0x6d, 0x61, 0x67, 0x75, 0x73, 0x74, 0x61, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4e, 0x69, 0x63,
    -0x6f, 0x73, 0x69, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x75, 0x61, 0x64, 0x65, 0x6c, 0x6f,
    -0x75, 0x70, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x61, 0x69, 0x67, 0x6f, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61,
    -0x2f, 0x43, 0x68, 0x69, 0x74, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x72, 0x6f, 0x76,
    -0x69, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x6f, 0x72, 0x74, 0x6f, 0x6c, 0x61, 0x0, 0x41,
    -0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x69, 0x6e, 0x73, 0x68, 0x61, 0x73, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f,
    -0x53, 0x61, 0x6b, 0x68, 0x61, 0x6c, 0x69, 0x6e, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x57, 0x61, 0x6b,
    -0x65, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x63, 0x63, 0x72, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66,
    -0x69, 0x63, 0x2f, 0x41, 0x75, 0x63, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69,
    -0x61, 0x2f, 0x41, 0x64, 0x65, 0x6c, 0x61, 0x69, 0x64, 0x65, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61,
    -0x2f, 0x42, 0x72, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x48, 0x69, 0x6c, 0x6c, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
    -0x2f, 0x54, 0x61, 0x68, 0x69, 0x74, 0x69, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4f, 0x75, 0x61, 0x67, 0x61,
    -0x64, 0x6f, 0x75, 0x67, 0x6f, 0x75, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4b, 0x65, 0x72, 0x67, 0x75, 0x65,
    -0x6c, 0x65, 0x6e, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x38, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
    -0x2f, 0x54, 0x69, 0x72, 0x61, 0x6e, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x69, 0x70, 0x65, 0x69, 0x0,
    -0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x43, 0x6f, 0x70, 0x65, 0x6e, 0x68, 0x61, 0x67, 0x65, 0x6e, 0x0, 0x41, 0x66,
    -0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x61, 0x6d, 0x70, 0x61, 0x6c, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
    -0x2f, 0x42, 0x61, 0x72, 0x62, 0x61, 0x64, 0x6f, 0x73, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x6b, 0x75, 0x0,
    -0x41, 0x73, 0x69, 0x61, 0x2f, 0x48, 0x6f, 0x6e, 0x67, 0x5f, 0x4b, 0x6f, 0x6e, 0x67, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f,
    -0x4a, 0x61, 0x79, 0x61, 0x70, 0x75, 0x72, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x48, 0x6f, 0x6e,
    -0x6f, 0x6c, 0x75, 0x6c, 0x75, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x61, 0x69, 0x72, 0x6f, 0x62, 0x69,
    -0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x47, 0x75, 0x61, 0x6d, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61,
    -0x2f, 0x4a, 0x75, 0x62, 0x61, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x46, 0x61, 0x65, 0x72, 0x6f,
    -0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x72, 0x65, 0x64, 0x6e, 0x65, 0x6b, 0x6f, 0x6c, 0x79, 0x6d, 0x73, 0x6b,
    -0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4e, 0x69, 0x75, 0x65, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61,
    -0x2f, 0x41, 0x6c, 0x67, 0x69, 0x65, 0x72, 0x73, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x69, 0x6c, 0x69, 0x0, 0x41,
    -0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x46, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x65, 0x7a, 0x61, 0x20, 0x41, 0x6d, 0x65,
    -0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x65, 0x6c, 0x65, 0x6d, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d,
    -0x61, 0x63, 0x65, 0x69, 0x6f, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x65, 0x63, 0x69, 0x66, 0x65,
    -0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x61, 0x72, 0x65, 0x6d, 0x0, 0x45, 0x75,
    -0x72, 0x6f, 0x70, 0x65, 0x2f, 0x50, 0x6f, 0x64, 0x67, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63,
    -0x61, 0x2f, 0x44, 0x6f, 0x75, 0x61, 0x6c, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x56, 0x69, 0x65, 0x6e, 0x74, 0x69,
    -0x61, 0x6e, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x69, 0x6a, 0x75, 0x61, 0x6e, 0x61, 0x20,
    -0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x61, 0x5f, 0x49, 0x73, 0x61, 0x62, 0x65, 0x6c,
    -0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x6d, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f,
    -0x52, 0x69, 0x67, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6c, 0x61, 0x6e, 0x63, 0x2d, 0x53,
    -0x61, 0x62, 0x6c, 0x6f, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x75, 0x73, 0x68, 0x61, 0x6e, 0x62, 0x65, 0x0,
    -0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x4a, 0x6f, 0x68, 0x6e, 0x73, 0x0, 0x41, 0x73, 0x69,
    -0x61, 0x2f, 0x54, 0x6f, 0x6b, 0x79, 0x6f, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x36, 0x0, 0x45, 0x75,
    -0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x72, 0x61, 0x6a, 0x65, 0x76, 0x6f, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
    -0x2f, 0x42, 0x72, 0x61, 0x74, 0x69, 0x73, 0x6c, 0x61, 0x76, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
    -0x47, 0x75, 0x79, 0x61, 0x6e, 0x61, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x43, 0x61, 0x6e, 0x61,
    -0x72, 0x79, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x42, 0x6f, 0x75, 0x67, 0x61, 0x69, 0x6e, 0x76, 0x69,
    -0x6c, 0x6c, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x68, 0x72, 0x61, 0x69, 0x6e, 0x0, 0x41, 0x6d, 0x65,
    -0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x75, 0x61, 0x74, 0x65, 0x6d, 0x61, 0x6c, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69,
    -0x63, 0x61, 0x2f, 0x4c, 0x61, 0x5f, 0x50, 0x61, 0x7a, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x50, 0x79, 0x6f, 0x6e, 0x67,
    -0x79, 0x61, 0x6e, 0x67, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x61, 0x67, 0x6f, 0x5f, 0x50, 0x61,
    -0x67, 0x6f, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x52, 0x65, 0x75, 0x6e, 0x69, 0x6f, 0x6e, 0x0, 0x41, 0x66,
    -0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x73, 0x65, 0x72, 0x75, 0x0, 0x50, 0x53, 0x54, 0x38, 0x50, 0x44, 0x54, 0x0,
    -0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x39, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x75, 0x6e,
    -0x69, 0x73, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6f, 0x5f, 0x54, 0x6f, 0x6d, 0x65, 0x0, 0x45,
    -0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x72, 0x61, 0x74, 0x6f, 0x76, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61,
    -0x2f, 0x4b, 0x68, 0x61, 0x72, 0x74, 0x6f, 0x75, 0x6d, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4a, 0x65, 0x72,
    -0x73, 0x65, 0x79, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x63, 0x71, 0x75,
    -0x61, 0x72, 0x69, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4f, 0x6a, 0x69, 0x6e, 0x61, 0x67, 0x61,
    -0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x43, 0x61, 0x70, 0x65, 0x5f, 0x56, 0x65, 0x72, 0x64, 0x65,
    -0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x61, 0x6b, 0x61, 0x73, 0x73, 0x61, 0x72, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70,
    -0x65, 0x2f, 0x4c, 0x6a, 0x75, 0x62, 0x6c, 0x6a, 0x61, 0x6e, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x47,
    -0x75, 0x65, 0x72, 0x6e, 0x73, 0x65, 0x79, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x4d,
    -0x61, 0x77, 0x73, 0x6f, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x75, 0x65, 0x6e, 0x6f, 0x73,
    -0x5f, 0x41, 0x69, 0x72, 0x65, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e,
    -0x74, 0x69, 0x6e, 0x61, 0x2f, 0x4c, 0x61, 0x5f, 0x52, 0x69, 0x6f, 0x6a, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
    -0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x52, 0x69, 0x6f, 0x5f, 0x47, 0x61, 0x6c, 0x6c,
    -0x65, 0x67, 0x6f, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69,
    -0x6e, 0x61, 0x2f, 0x53, 0x61, 0x6c, 0x74, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67,
    -0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x5f, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x41, 0x6d, 0x65, 0x72,
    -0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x5f, 0x4c, 0x75,
    -0x69, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61,
    -0x2f, 0x54, 0x75, 0x63, 0x75, 0x6d, 0x61, 0x6e, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67,
    -0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x55, 0x73, 0x68, 0x75, 0x61, 0x69, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69,
    -0x63, 0x61, 0x2f, 0x43, 0x61, 0x74, 0x61, 0x6d, 0x61, 0x72, 0x63, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
    -0x2f, 0x43, 0x6f, 0x72, 0x64, 0x6f, 0x62, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a, 0x75, 0x6a,
    -0x75, 0x79, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x6e, 0x64, 0x6f, 0x7a, 0x61, 0x0, 0x50,
    -0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x41, 0x70, 0x69, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42,
    -0x61, 0x6e, 0x67, 0x75, 0x69, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x6f, 0x6d, 0x73, 0x6b, 0x0, 0x50, 0x61, 0x63,
    -0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x61, 0x6c, 0x61, 0x75, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61,
    -0x2f, 0x44, 0x61, 0x72, 0x77, 0x69, 0x6e, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x69, 0x74, 0x63,
    -0x61, 0x69, 0x72, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x72, 0x75, 0x6e, 0x65, 0x69, 0x0, 0x50, 0x61, 0x63,
    -0x69, 0x66, 0x69, 0x63, 0x2f, 0x54, 0x6f, 0x6e, 0x67, 0x61, 0x74, 0x61, 0x70, 0x75, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70,
    -0x65, 0x2f, 0x53, 0x61, 0x6d, 0x61, 0x72, 0x61, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x50,
    -0x65, 0x72, 0x74, 0x68, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x57, 0x61, 0x72, 0x73, 0x61, 0x77, 0x0, 0x49,
    -0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x43, 0x6f, 0x63, 0x6f, 0x73, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4d,
    -0x61, 0x68, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x73, 0x5f, 0x41, 0x6e, 0x67, 0x65,
    -0x6c, 0x65, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x74, 0x6c, 0x61, 0x6b, 0x61, 0x74,
    -0x6c, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x43, 0x61, 0x6c, 0x63, 0x75, 0x74, 0x74, 0x61, 0x0, 0x41, 0x66, 0x72,
    -0x69, 0x63, 0x61, 0x2f, 0x41, 0x62, 0x69, 0x64, 0x6a, 0x61, 0x6e, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b,
    -0x36, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x45, 0x66, 0x61, 0x74, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f,
    -0x70, 0x65, 0x2f, 0x4c, 0x75, 0x78, 0x65, 0x6d, 0x62, 0x6f, 0x75, 0x72, 0x67, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61,
    -0x2f, 0x42, 0x61, 0x6d, 0x61, 0x6b, 0x6f, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x69, 0x67, 0x61, 0x6c,
    -0x69, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x51, 0x61, 0x74, 0x61, 0x72, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61,
    -0x72, 0x61, 0x63, 0x68, 0x69, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x30, 0x0, 0x41, 0x66, 0x72,
    -0x69, 0x63, 0x61, 0x2f, 0x44, 0x6a, 0x69, 0x62, 0x6f, 0x75, 0x74, 0x69, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x59, 0x65,
    -0x6b, 0x61, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x62, 0x75, 0x72, 0x67, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
    -0x44, 0x61, 0x77, 0x73, 0x6f, 0x6e, 0x5f, 0x43, 0x72, 0x65, 0x65, 0x6b, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
    -0x2f, 0x43, 0x72, 0x65, 0x73, 0x74, 0x6f, 0x6e, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x46, 0x6f, 0x72,
    -0x74, 0x5f, 0x4e, 0x65, 0x6c, 0x73, 0x6f, 0x6e, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4d, 0x61, 0x79, 0x6f,
    -0x74, 0x74, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x6b, 0x6f, 0x70, 0x6a, 0x65, 0x0, 0x41, 0x73,
    -0x69, 0x61, 0x2f, 0x53, 0x65, 0x6f, 0x75, 0x6c, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x61, 0x72,
    -0x61, 0x6d, 0x61, 0x72, 0x69, 0x62, 0x6f, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x74, 0x6f, 0x63, 0x6b,
    -0x68, 0x6f, 0x6c, 0x6d, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x75, 0x62, 0x75, 0x6d, 0x62, 0x61, 0x73,
    -0x68, 0x69, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x61, 0x67, 0x65,
    -0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x75, 0x65, 0x6e, 0x6f, 0x73, 0x5f, 0x41, 0x69, 0x72, 0x65,
    -0x73, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x41, 0x73, 0x74, 0x72, 0x61, 0x6b, 0x68, 0x61, 0x6e, 0x0, 0x41,
    -0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x6c, 0x69, 0x66, 0x61, 0x78, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72,
    -0x61, 0x6c, 0x69, 0x61, 0x2f, 0x53, 0x79, 0x64, 0x6e, 0x65, 0x79, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
    -0x52, 0x65, 0x67, 0x69, 0x6e, 0x61, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x41, 0x64, 0x65,
    -0x6c, 0x61, 0x69, 0x64, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x6c, 0x6d, 0x61, 0x74, 0x79, 0x0, 0x41, 0x6d,
    -0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x75, 0x69, 0x61, 0x62, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
    -0x2f, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x5f, 0x43, 0x69, 0x74, 0x79, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
    -0x2f, 0x43, 0x68, 0x69, 0x63, 0x61, 0x67, 0x6f, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x42,
    -0x72, 0x69, 0x73, 0x62, 0x61, 0x6e, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x65, 0x77, 0x5f,
    -0x59, 0x6f, 0x72, 0x6b, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4b, 0x69, 0x65, 0x76, 0x0, 0x41, 0x6d, 0x65,
    -0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x68, 0x75, 0x61, 0x68, 0x75, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69,
    -0x63, 0x61, 0x2f, 0x44, 0x65, 0x6e, 0x76, 0x65, 0x72, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x72, 0x61, 0x73, 0x6e,
    -0x6f, 0x79, 0x61, 0x72, 0x73, 0x6b, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x73, 0x5f, 0x41,
    -0x6e, 0x67, 0x65, 0x6c, 0x65, 0x73, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x69, 0x6a, 0x75, 0x61,
    -0x6e, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x6d, 0x63, 0x68, 0x61, 0x74, 0x6b, 0x61, 0x0, 0x45, 0x75,
    -0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x6f, 0x73, 0x63, 0x6f, 0x77, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69,
    -0x61, 0x2f, 0x48, 0x6f, 0x62, 0x61, 0x72, 0x74, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x6c, 0x61, 0x61, 0x6e, 0x62,
    -0x61, 0x61, 0x74, 0x61, 0x72, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e,
    -0x61, 0x70, 0x6f, 0x6c, 0x69, 0x73, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f,
    -0x56, 0x6c, 0x61, 0x64, 0x69, 0x76, 0x6f, 0x73, 0x74, 0x6f, 0x6b, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42,
    -0x65, 0x72, 0x6c, 0x69, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x73, 0x68, 0x6b, 0x65, 0x6e, 0x74, 0x0,
    -0x41, 0x73, 0x69, 0x61, 0x2f, 0x48, 0x65, 0x62, 0x72, 0x6f, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x59, 0x61, 0x6b,
    -0x75, 0x74, 0x73, 0x6b, 0x0, 0x55, 0x54, 0x43, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x31, 0x34, 0x3a, 0x30, 0x30, 0x0, 0x55,
    -0x54, 0x43, 0x2d, 0x31, 0x33, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x31, 0x32, 0x3a, 0x30, 0x30, 0x0, 0x55,
    -0x54, 0x43, 0x2d, 0x31, 0x31, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x31, 0x30, 0x3a, 0x30, 0x30, 0x0, 0x55,
    -0x54, 0x43, 0x2d, 0x30, 0x39, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x38, 0x3a, 0x30, 0x30, 0x0, 0x55,
    -0x54, 0x43, 0x2d, 0x30, 0x37, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x36, 0x3a, 0x30, 0x30, 0x0, 0x55,
    -0x54, 0x43, 0x2d, 0x30, 0x35, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x34, 0x3a, 0x33, 0x30, 0x0, 0x55,
    -0x54, 0x43, 0x2d, 0x30, 0x34, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x33, 0x3a, 0x33, 0x30, 0x0, 0x55,
    -0x54, 0x43, 0x2d, 0x30, 0x33, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x32, 0x3a, 0x30, 0x30, 0x0, 0x55,
    -0x54, 0x43, 0x2d, 0x30, 0x31, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x0, 0x55,
    -0x54, 0x43, 0x2b, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x31, 0x3a, 0x30, 0x30, 0x0, 0x55,
    -0x54, 0x43, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x33, 0x3a, 0x30, 0x30, 0x0, 0x55,
    -0x54, 0x43, 0x2b, 0x30, 0x33, 0x3a, 0x33, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x34, 0x3a, 0x30, 0x30, 0x0, 0x55,
    -0x54, 0x43, 0x2b, 0x30, 0x34, 0x3a, 0x33, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x35, 0x3a, 0x30, 0x30, 0x0, 0x55,
    -0x54, 0x43, 0x2b, 0x30, 0x35, 0x3a, 0x33, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x35, 0x3a, 0x34, 0x35, 0x0, 0x55,
    -0x54, 0x43, 0x2b, 0x30, 0x36, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x36, 0x3a, 0x33, 0x30, 0x0, 0x55,
    -0x54, 0x43, 0x2b, 0x30, 0x37, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x38, 0x3a, 0x30, 0x30, 0x0, 0x55,
    -0x54, 0x43, 0x2b, 0x30, 0x38, 0x3a, 0x33, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x39, 0x3a, 0x30, 0x30, 0x0, 0x55,
    -0x54, 0x43, 0x2b, 0x30, 0x39, 0x3a, 0x33, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x30, 0x3a, 0x30, 0x30, 0x0, 0x55,
    -0x54, 0x43, 0x2b, 0x31, 0x31, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x32, 0x3a, 0x30, 0x30, 0x0, 0x55,
    -0x54, 0x43, 0x2b, 0x31, 0x33, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x34, 0x3a, 0x30, 0x30, 0x0
    -};
    -// GENERATED PART ENDS HERE
    -
    -QT_END_NAMESPACE
    -
    -#endif // QTIMEZONEPRIVATE_DATA_P_H
    diff --git a/src/corelib/tools/qtimezoneprivate_icu.cpp b/src/corelib/tools/qtimezoneprivate_icu.cpp
    deleted file mode 100644
    index 5570ce7571..0000000000
    --- a/src/corelib/tools/qtimezoneprivate_icu.cpp
    +++ /dev/null
    @@ -1,508 +0,0 @@
    -/****************************************************************************
    -**
    -** Copyright (C) 2013 John Layt 
    -** Contact: https://www.qt.io/licensing/
    -**
    -** This file is part of the QtCore module of the Qt Toolkit.
    -**
    -** $QT_BEGIN_LICENSE:LGPL$
    -** Commercial License Usage
    -** Licensees holding valid commercial Qt licenses may use this file in
    -** accordance with the commercial license agreement provided with the
    -** Software or, alternatively, in accordance with the terms contained in
    -** a written agreement between you and The Qt Company. For licensing terms
    -** and conditions see https://www.qt.io/terms-conditions. For further
    -** information use the contact form at https://www.qt.io/contact-us.
    -**
    -** GNU Lesser General Public License Usage
    -** Alternatively, this file may be used under the terms of the GNU Lesser
    -** General Public License version 3 as published by the Free Software
    -** Foundation and appearing in the file LICENSE.LGPL3 included in the
    -** packaging of this file. Please review the following information to
    -** ensure the GNU Lesser General Public License version 3 requirements
    -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
    -**
    -** GNU General Public License Usage
    -** Alternatively, this file may be used under the terms of the GNU
    -** General Public License version 2.0 or (at your option) the GNU General
    -** Public license version 3 or any later version approved by the KDE Free
    -** Qt Foundation. The licenses are as published by the Free Software
    -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
    -** included in the packaging of this file. Please review the following
    -** information to ensure the GNU General Public License requirements will
    -** be met: https://www.gnu.org/licenses/gpl-2.0.html and
    -** https://www.gnu.org/licenses/gpl-3.0.html.
    -**
    -** $QT_END_LICENSE$
    -**
    -****************************************************************************/
    -
    -#include "qtimezone.h"
    -#include "qtimezoneprivate_p.h"
    -
    -#include 
    -
    -#include 
    -#include 
    -
    -#include 
    -
    -QT_BEGIN_NAMESPACE
    -
    -/*
    -    Private
    -
    -    ICU implementation
    -*/
    -
    -// ICU utilities
    -
    -// Convert TimeType and NameType into ICU UCalendarDisplayNameType
    -static UCalendarDisplayNameType ucalDisplayNameType(QTimeZone::TimeType timeType, QTimeZone::NameType nameType)
    -{
    -    // TODO ICU C UCalendarDisplayNameType does not support full set of C++ TimeZone::EDisplayType
    -    switch (nameType) {
    -    case QTimeZone::ShortName :
    -    case QTimeZone::OffsetName :
    -        if (timeType == QTimeZone::DaylightTime)
    -            return UCAL_SHORT_DST;
    -        // Includes GenericTime
    -        return UCAL_SHORT_STANDARD;
    -    case QTimeZone::DefaultName :
    -    case QTimeZone::LongName :
    -        if (timeType == QTimeZone::DaylightTime)
    -            return UCAL_DST;
    -        // Includes GenericTime
    -        return UCAL_STANDARD;
    -    }
    -    return UCAL_STANDARD;
    -}
    -
    -// Qt wrapper around ucal_getDefaultTimeZone()
    -static QByteArray ucalDefaultTimeZoneId()
    -{
    -    int32_t size = 30;
    -    QString result(size, Qt::Uninitialized);
    -    UErrorCode status = U_ZERO_ERROR;
    -
    -    // size = ucal_getDefaultTimeZone(result, resultLength, status)
    -    size = ucal_getDefaultTimeZone(reinterpret_cast(result.data()), size, &status);
    -
    -    // If overflow, then resize and retry
    -    if (status == U_BUFFER_OVERFLOW_ERROR) {
    -        result.resize(size);
    -        status = U_ZERO_ERROR;
    -        size = ucal_getDefaultTimeZone(reinterpret_cast(result.data()), size, &status);
    -    }
    -
    -    // If successful on first or second go, resize and return
    -    if (U_SUCCESS(status)) {
    -        result.resize(size);
    -        return std::move(result).toUtf8();
    -    }
    -
    -    return QByteArray();
    -}
    -
    -// Qt wrapper around ucal_getTimeZoneDisplayName()
    -static QString ucalTimeZoneDisplayName(UCalendar *ucal, QTimeZone::TimeType timeType,
    -                                       QTimeZone::NameType nameType,
    -                                       const QString &localeCode)
    -{
    -    int32_t size = 50;
    -    QString result(size, Qt::Uninitialized);
    -    UErrorCode status = U_ZERO_ERROR;
    -
    -    // size = ucal_getTimeZoneDisplayName(cal, type, locale, result, resultLength, status)
    -    size = ucal_getTimeZoneDisplayName(ucal,
    -                                       ucalDisplayNameType(timeType, nameType),
    -                                       localeCode.toUtf8(),
    -                                       reinterpret_cast(result.data()),
    -                                       size,
    -                                       &status);
    -
    -    // If overflow, then resize and retry
    -    if (status == U_BUFFER_OVERFLOW_ERROR) {
    -        result.resize(size);
    -        status = U_ZERO_ERROR;
    -        size = ucal_getTimeZoneDisplayName(ucal,
    -                                           ucalDisplayNameType(timeType, nameType),
    -                                           localeCode.toUtf8(),
    -                                           reinterpret_cast(result.data()),
    -                                           size,
    -                                           &status);
    -    }
    -
    -    // If successful on first or second go, resize and return
    -    if (U_SUCCESS(status)) {
    -        result.resize(size);
    -        return result;
    -    }
    -
    -    return QString();
    -}
    -
    -// Qt wrapper around ucal_get() for offsets
    -static bool ucalOffsetsAtTime(UCalendar *m_ucal, qint64 atMSecsSinceEpoch,
    -                              int *utcOffset, int *dstOffset)
    -{
    -    *utcOffset = 0;
    -    *dstOffset = 0;
    -
    -    // Clone the ucal so we don't change the shared object
    -    UErrorCode status = U_ZERO_ERROR;
    -    UCalendar *ucal = ucal_clone(m_ucal, &status);
    -    if (!U_SUCCESS(status))
    -        return false;
    -
    -    // Set the date to find the offset for
    -    status = U_ZERO_ERROR;
    -    ucal_setMillis(ucal, atMSecsSinceEpoch, &status);
    -
    -    int32_t utc = 0;
    -    if (U_SUCCESS(status)) {
    -        status = U_ZERO_ERROR;
    -        // Returns msecs
    -        utc = ucal_get(ucal, UCAL_ZONE_OFFSET, &status) / 1000;
    -    }
    -
    -    int32_t dst = 0;
    -    if (U_SUCCESS(status)) {
    -        status = U_ZERO_ERROR;
    -        // Returns msecs
    -        dst = ucal_get(ucal, UCAL_DST_OFFSET, &status) / 1000;
    -    }
    -
    -    ucal_close(ucal);
    -    if (U_SUCCESS(status)) {
    -        *utcOffset = utc;
    -        *dstOffset = dst;
    -        return true;
    -    }
    -    return false;
    -}
    -
    -// ICU Draft api in v50, should be stable in ICU v51. Available in C++ api from ICU v3.8
    -#if U_ICU_VERSION_MAJOR_NUM == 50
    -// Qt wrapper around qt_ucal_getTimeZoneTransitionDate & ucal_get
    -static QTimeZonePrivate::Data ucalTimeZoneTransition(UCalendar *m_ucal,
    -                                                     UTimeZoneTransitionType type,
    -                                                     qint64 atMSecsSinceEpoch)
    -{
    -    QTimeZonePrivate::Data tran = QTimeZonePrivate::invalidData();
    -
    -    // Clone the ucal so we don't change the shared object
    -    UErrorCode status = U_ZERO_ERROR;
    -    UCalendar *ucal = ucal_clone(m_ucal, &status);
    -    if (!U_SUCCESS(status))
    -        return tran;
    -
    -    // Set the date to find the transition for
    -    status = U_ZERO_ERROR;
    -    ucal_setMillis(ucal, atMSecsSinceEpoch, &status);
    -
    -    // Find the transition time
    -    UDate tranMSecs = 0;
    -    status = U_ZERO_ERROR;
    -    bool ok = ucal_getTimeZoneTransitionDate(ucal, type, &tranMSecs, &status);
    -
    -    // Set the transition time to find the offsets for
    -    if (U_SUCCESS(status) && ok) {
    -        status = U_ZERO_ERROR;
    -        ucal_setMillis(ucal, tranMSecs, &status);
    -    }
    -
    -    int32_t utc = 0;
    -    if (U_SUCCESS(status) && ok) {
    -        status = U_ZERO_ERROR;
    -        utc = ucal_get(ucal, UCAL_ZONE_OFFSET, &status) / 1000;
    -    }
    -
    -    int32_t dst = 0;
    -    if (U_SUCCESS(status) && ok) {
    -        status = U_ZERO_ERROR;
    -        dst = ucal_get(ucal, UCAL_DST_OFFSET, &status) / 1000;
    -    }
    -
    -    ucal_close(ucal);
    -    if (!U_SUCCESS(status) || !ok)
    -        return tran;
    -    tran.atMSecsSinceEpoch = tranMSecs;
    -    tran.offsetFromUtc = utc + dst;
    -    tran.standardTimeOffset = utc;
    -    tran.daylightTimeOffset = dst;
    -    // TODO No ICU API, use short name instead
    -    if (dst == 0)
    -        tran.abbreviation = ucalTimeZoneDisplayName(m_ucal, QTimeZone::StandardTime,
    -                                                    QTimeZone::ShortName, QLocale().name());
    -    else
    -        tran.abbreviation = ucalTimeZoneDisplayName(m_ucal, QTimeZone::DaylightTime,
    -                                                    QTimeZone::ShortName, QLocale().name());
    -    return tran;
    -}
    -#endif // U_ICU_VERSION_SHORT
    -
    -// Convert a uenum to a QList
    -static QList uenumToIdList(UEnumeration *uenum)
    -{
    -    QList list;
    -    int32_t size = 0;
    -    UErrorCode status = U_ZERO_ERROR;
    -    // TODO Perhaps use uenum_unext instead?
    -    QByteArray result = uenum_next(uenum, &size, &status);
    -    while (U_SUCCESS(status) && !result.isEmpty()) {
    -        list << result;
    -        status = U_ZERO_ERROR;
    -        result = uenum_next(uenum, &size, &status);
    -    }
    -    std::sort(list.begin(), list.end());
    -    list.erase(std::unique(list.begin(), list.end()), list.end());
    -    return list;
    -}
    -
    -// Qt wrapper around ucal_getDSTSavings()
    -static int ucalDaylightOffset(const QByteArray &id)
    -{
    -    UErrorCode status = U_ZERO_ERROR;
    -    const int32_t dstMSecs = ucal_getDSTSavings(reinterpret_cast(id.data()), &status);
    -    if (U_SUCCESS(status))
    -        return (dstMSecs / 1000);
    -    else
    -        return 0;
    -}
    -
    -// Create the system default time zone
    -QIcuTimeZonePrivate::QIcuTimeZonePrivate()
    -    : m_ucal(0)
    -{
    -    // TODO No ICU C API to obtain sysem tz, assume default hasn't been changed
    -    init(ucalDefaultTimeZoneId());
    -}
    -
    -// Create a named time zone
    -QIcuTimeZonePrivate::QIcuTimeZonePrivate(const QByteArray &ianaId)
    -    : m_ucal(0)
    -{
    -    // Need to check validity here as ICu will create a GMT tz if name is invalid
    -    if (availableTimeZoneIds().contains(ianaId))
    -        init(ianaId);
    -}
    -
    -QIcuTimeZonePrivate::QIcuTimeZonePrivate(const QIcuTimeZonePrivate &other)
    -    : QTimeZonePrivate(other), m_ucal(0)
    -{
    -    // Clone the ucal so we don't close the shared object
    -    UErrorCode status = U_ZERO_ERROR;
    -    m_ucal = ucal_clone(other.m_ucal, &status);
    -    if (!U_SUCCESS(status)) {
    -        m_id.clear();
    -        m_ucal = 0;
    -    }
    -}
    -
    -QIcuTimeZonePrivate::~QIcuTimeZonePrivate()
    -{
    -    ucal_close(m_ucal);
    -}
    -
    -QIcuTimeZonePrivate *QIcuTimeZonePrivate::clone() const
    -{
    -    return new QIcuTimeZonePrivate(*this);
    -}
    -
    -void QIcuTimeZonePrivate::init(const QByteArray &ianaId)
    -{
    -    m_id = ianaId;
    -
    -    const QString id = QString::fromUtf8(m_id);
    -    UErrorCode status = U_ZERO_ERROR;
    -    //TODO Use UCAL_GREGORIAN for now to match QLocale, change to UCAL_DEFAULT once full ICU support
    -    m_ucal = ucal_open(reinterpret_cast(id.data()), id.size(),
    -                       QLocale().name().toUtf8(), UCAL_GREGORIAN, &status);
    -
    -    if (!U_SUCCESS(status)) {
    -        m_id.clear();
    -        m_ucal = 0;
    -    }
    -}
    -
    -QString QIcuTimeZonePrivate::displayName(QTimeZone::TimeType timeType,
    -                                         QTimeZone::NameType nameType,
    -                                         const QLocale &locale) const
    -{
    -    // Return standard offset format name as ICU C api doesn't support it yet
    -    if (nameType == QTimeZone::OffsetName) {
    -        const Data nowData = data(QDateTime::currentMSecsSinceEpoch());
    -        // We can't use transitions reliably to find out right dst offset
    -        // Instead use dst offset api to try get it if needed
    -        if (timeType == QTimeZone::DaylightTime)
    -            return isoOffsetFormat(nowData.standardTimeOffset + ucalDaylightOffset(m_id));
    -        else
    -            return isoOffsetFormat(nowData.standardTimeOffset);
    -    }
    -    return ucalTimeZoneDisplayName(m_ucal, timeType, nameType, locale.name());
    -}
    -
    -QString QIcuTimeZonePrivate::abbreviation(qint64 atMSecsSinceEpoch) const
    -{
    -    // TODO No ICU API, use short name instead
    -    if (isDaylightTime(atMSecsSinceEpoch))
    -        return displayName(QTimeZone::DaylightTime, QTimeZone::ShortName, QString());
    -    else
    -        return displayName(QTimeZone::StandardTime, QTimeZone::ShortName, QString());
    -}
    -
    -int QIcuTimeZonePrivate::offsetFromUtc(qint64 atMSecsSinceEpoch) const
    -{
    -    int stdOffset = 0;
    -    int dstOffset = 0;
    -    ucalOffsetsAtTime(m_ucal, atMSecsSinceEpoch, &stdOffset, & dstOffset);
    -    return stdOffset + dstOffset;
    -}
    -
    -int QIcuTimeZonePrivate::standardTimeOffset(qint64 atMSecsSinceEpoch) const
    -{
    -    int stdOffset = 0;
    -    int dstOffset = 0;
    -    ucalOffsetsAtTime(m_ucal, atMSecsSinceEpoch, &stdOffset, & dstOffset);
    -    return stdOffset;
    -}
    -
    -int QIcuTimeZonePrivate::daylightTimeOffset(qint64 atMSecsSinceEpoch) const
    -{
    -    int stdOffset = 0;
    -    int dstOffset = 0;
    -    ucalOffsetsAtTime(m_ucal, atMSecsSinceEpoch, &stdOffset, & dstOffset);
    -    return dstOffset;
    -}
    -
    -bool QIcuTimeZonePrivate::hasDaylightTime() const
    -{
    -    // TODO No direct ICU C api, work-around below not reliable?  Find a better way?
    -    return (ucalDaylightOffset(m_id) != 0);
    -}
    -
    -bool QIcuTimeZonePrivate::isDaylightTime(qint64 atMSecsSinceEpoch) const
    -{
    -    // Clone the ucal so we don't change the shared object
    -    UErrorCode status = U_ZERO_ERROR;
    -    UCalendar *ucal = ucal_clone(m_ucal, &status);
    -    if (!U_SUCCESS(status))
    -        return false;
    -
    -    // Set the date to find the offset for
    -    status = U_ZERO_ERROR;
    -    ucal_setMillis(ucal, atMSecsSinceEpoch, &status);
    -
    -    bool result = false;
    -    if (U_SUCCESS(status)) {
    -        status = U_ZERO_ERROR;
    -        result = ucal_inDaylightTime(ucal, &status);
    -    }
    -
    -    ucal_close(ucal);
    -    return result;
    -}
    -
    -QTimeZonePrivate::Data QIcuTimeZonePrivate::data(qint64 forMSecsSinceEpoch) const
    -{
    -    // Available in ICU C++ api, and draft C api in v50
    -    // TODO When v51 released see if api is stable
    -    QTimeZonePrivate::Data data = invalidData();
    -#if U_ICU_VERSION_MAJOR_NUM == 50
    -    data = ucalTimeZoneTransition(m_ucal, UCAL_TZ_TRANSITION_PREVIOUS_INCLUSIVE,
    -                                  forMSecsSinceEpoch);
    -#else
    -    ucalOffsetsAtTime(m_ucal, forMSecsSinceEpoch, &data.standardTimeOffset,
    -                      &data.daylightTimeOffset);
    -    data.offsetFromUtc = data.standardTimeOffset + data.daylightTimeOffset;
    -    data.abbreviation = abbreviation(forMSecsSinceEpoch);
    -#endif // U_ICU_VERSION_MAJOR_NUM == 50
    -    data.atMSecsSinceEpoch = forMSecsSinceEpoch;
    -    return data;
    -}
    -
    -bool QIcuTimeZonePrivate::hasTransitions() const
    -{
    -    // Available in ICU C++ api, and draft C api in v50
    -    // TODO When v51 released see if api is stable
    -#if U_ICU_VERSION_MAJOR_NUM == 50
    -    return true;
    -#else
    -    return false;
    -#endif // U_ICU_VERSION_MAJOR_NUM == 50
    -}
    -
    -QTimeZonePrivate::Data QIcuTimeZonePrivate::nextTransition(qint64 afterMSecsSinceEpoch) const
    -{
    -    // Available in ICU C++ api, and draft C api in v50
    -    // TODO When v51 released see if api is stable
    -#if U_ICU_VERSION_MAJOR_NUM == 50
    -    return ucalTimeZoneTransition(m_ucal, UCAL_TZ_TRANSITION_NEXT, afterMSecsSinceEpoch);
    -#else
    -    Q_UNUSED(afterMSecsSinceEpoch)
    -    return invalidData();
    -#endif // U_ICU_VERSION_MAJOR_NUM == 50
    -}
    -
    -QTimeZonePrivate::Data QIcuTimeZonePrivate::previousTransition(qint64 beforeMSecsSinceEpoch) const
    -{
    -    // Available in ICU C++ api, and draft C api in v50
    -    // TODO When v51 released see if api is stable
    -#if U_ICU_VERSION_MAJOR_NUM == 50
    -    return ucalTimeZoneTransition(m_ucal, UCAL_TZ_TRANSITION_PREVIOUS, beforeMSecsSinceEpoch);
    -#else
    -    Q_UNUSED(beforeMSecsSinceEpoch)
    -    return invalidData();
    -#endif // U_ICU_VERSION_MAJOR_NUM == 50
    -}
    -
    -QByteArray QIcuTimeZonePrivate::systemTimeZoneId() const
    -{
    -    // No ICU C API to obtain sysem tz
    -    // TODO Assume default hasn't been changed and is the latests system
    -    return ucalDefaultTimeZoneId();
    -}
    -
    -QList QIcuTimeZonePrivate::availableTimeZoneIds() const
    -{
    -    UErrorCode status = U_ZERO_ERROR;
    -    UEnumeration *uenum = ucal_openTimeZones(&status);
    -    QList result;
    -    if (U_SUCCESS(status))
    -        result = uenumToIdList(uenum);
    -    uenum_close(uenum);
    -    return result;
    -}
    -
    -QList QIcuTimeZonePrivate::availableTimeZoneIds(QLocale::Country country) const
    -{
    -    const QLatin1String regionCode = QLocalePrivate::countryToCode(country);
    -    const QByteArray regionCodeUtf8 = QString(regionCode).toUtf8();
    -    UErrorCode status = U_ZERO_ERROR;
    -    UEnumeration *uenum = ucal_openCountryTimeZones(regionCodeUtf8.data(), &status);
    -    QList result;
    -    if (U_SUCCESS(status))
    -        result = uenumToIdList(uenum);
    -    uenum_close(uenum);
    -    return result;
    -}
    -
    -QList QIcuTimeZonePrivate::availableTimeZoneIds(int offsetFromUtc) const
    -{
    -// TODO Available directly in C++ api but not C api, from 4.8 onwards new filter method works
    -#if U_ICU_VERSION_MAJOR_NUM >= 49 || (U_ICU_VERSION_MAJOR_NUM == 4 && U_ICU_VERSION_MINOR_NUM == 8)
    -    UErrorCode status = U_ZERO_ERROR;
    -    UEnumeration *uenum = ucal_openTimeZoneIDEnumeration(UCAL_ZONE_TYPE_ANY, 0,
    -                                                         &offsetFromUtc, &status);
    -    QList result;
    -    if (U_SUCCESS(status))
    -        result = uenumToIdList(uenum);
    -    uenum_close(uenum);
    -    return result;
    -#else
    -    return QTimeZonePrivate::availableTimeZoneIds(offsetFromUtc);
    -#endif
    -}
    -
    -QT_END_NAMESPACE
    diff --git a/src/corelib/tools/qtimezoneprivate_mac.mm b/src/corelib/tools/qtimezoneprivate_mac.mm
    deleted file mode 100644
    index d3c4fbe5da..0000000000
    --- a/src/corelib/tools/qtimezoneprivate_mac.mm
    +++ /dev/null
    @@ -1,333 +0,0 @@
    -/****************************************************************************
    -**
    -** Copyright (C) 2013 John Layt 
    -** Contact: https://www.qt.io/licensing/
    -**
    -** This file is part of the QtCore module of the Qt Toolkit.
    -**
    -** $QT_BEGIN_LICENSE:LGPL$
    -** Commercial License Usage
    -** Licensees holding valid commercial Qt licenses may use this file in
    -** accordance with the commercial license agreement provided with the
    -** Software or, alternatively, in accordance with the terms contained in
    -** a written agreement between you and The Qt Company. For licensing terms
    -** and conditions see https://www.qt.io/terms-conditions. For further
    -** information use the contact form at https://www.qt.io/contact-us.
    -**
    -** GNU Lesser General Public License Usage
    -** Alternatively, this file may be used under the terms of the GNU Lesser
    -** General Public License version 3 as published by the Free Software
    -** Foundation and appearing in the file LICENSE.LGPL3 included in the
    -** packaging of this file. Please review the following information to
    -** ensure the GNU Lesser General Public License version 3 requirements
    -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
    -**
    -** GNU General Public License Usage
    -** Alternatively, this file may be used under the terms of the GNU
    -** General Public License version 2.0 or (at your option) the GNU General
    -** Public license version 3 or any later version approved by the KDE Free
    -** Qt Foundation. The licenses are as published by the Free Software
    -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
    -** included in the packaging of this file. Please review the following
    -** information to ensure the GNU General Public License requirements will
    -** be met: https://www.gnu.org/licenses/gpl-2.0.html and
    -** https://www.gnu.org/licenses/gpl-3.0.html.
    -**
    -** $QT_END_LICENSE$
    -**
    -****************************************************************************/
    -
    -#include "qtimezone.h"
    -#include "qtimezoneprivate_p.h"
    -
    -#include "private/qcore_mac_p.h"
    -#include "qstringlist.h"
    -
    -#include 
    -
    -#include 
    -
    -#include 
    -
    -QT_BEGIN_NAMESPACE
    -
    -/*
    -    Private
    -
    -    OS X system implementation
    -*/
    -
    -// Create the system default time zone
    -QMacTimeZonePrivate::QMacTimeZonePrivate()
    -    : m_nstz(0)
    -{
    -    init(systemTimeZoneId());
    -}
    -
    -// Create a named time zone
    -QMacTimeZonePrivate::QMacTimeZonePrivate(const QByteArray &ianaId)
    -    : m_nstz(0)
    -{
    -    init(ianaId);
    -}
    -
    -QMacTimeZonePrivate::QMacTimeZonePrivate(const QMacTimeZonePrivate &other)
    -    : QTimeZonePrivate(other), m_nstz(0)
    -{
    -    m_nstz = [other.m_nstz copy];
    -}
    -
    -QMacTimeZonePrivate::~QMacTimeZonePrivate()
    -{
    -    [m_nstz release];
    -}
    -
    -QMacTimeZonePrivate *QMacTimeZonePrivate::clone() const
    -{
    -    return new QMacTimeZonePrivate(*this);
    -}
    -
    -void QMacTimeZonePrivate::init(const QByteArray &ianaId)
    -{
    -    if (availableTimeZoneIds().contains(ianaId)) {
    -        m_nstz = [[NSTimeZone timeZoneWithName:QString::fromUtf8(ianaId).toNSString()] retain];
    -        if (m_nstz)
    -            m_id = ianaId;
    -    }
    -}
    -
    -QString QMacTimeZonePrivate::comment() const
    -{
    -    return QString::fromNSString([m_nstz description]);
    -}
    -
    -QString QMacTimeZonePrivate::displayName(QTimeZone::TimeType timeType,
    -                                         QTimeZone::NameType nameType,
    -                                         const QLocale &locale) const
    -{
    -    // TODO Mac doesn't support OffsetName yet so use standard offset name
    -    if (nameType == QTimeZone::OffsetName) {
    -        const Data nowData = data(QDateTime::currentMSecsSinceEpoch());
    -        // TODO Cheat for now, assume if has dst the offset if 1 hour
    -        if (timeType == QTimeZone::DaylightTime && hasDaylightTime())
    -            return isoOffsetFormat(nowData.standardTimeOffset + 3600);
    -        else
    -            return isoOffsetFormat(nowData.standardTimeOffset);
    -    }
    -
    -    NSTimeZoneNameStyle style = NSTimeZoneNameStyleStandard;
    -
    -    switch (nameType) {
    -    case QTimeZone::ShortName :
    -        if (timeType == QTimeZone::DaylightTime)
    -            style = NSTimeZoneNameStyleShortDaylightSaving;
    -        else if (timeType == QTimeZone::GenericTime)
    -            style = NSTimeZoneNameStyleShortGeneric;
    -        else
    -            style = NSTimeZoneNameStyleShortStandard;
    -        break;
    -    case QTimeZone::DefaultName :
    -    case QTimeZone::LongName :
    -        if (timeType == QTimeZone::DaylightTime)
    -            style = NSTimeZoneNameStyleDaylightSaving;
    -        else if (timeType == QTimeZone::GenericTime)
    -            style = NSTimeZoneNameStyleGeneric;
    -        else
    -            style = NSTimeZoneNameStyleStandard;
    -        break;
    -    case QTimeZone::OffsetName :
    -        // Unreachable
    -        break;
    -    }
    -
    -    NSString *macLocaleCode = locale.name().toNSString();
    -    NSLocale *macLocale = [[NSLocale alloc] initWithLocaleIdentifier:macLocaleCode];
    -    const QString result = QString::fromNSString([m_nstz localizedName:style locale:macLocale]);
    -    [macLocale release];
    -    return result;
    -}
    -
    -QString QMacTimeZonePrivate::abbreviation(qint64 atMSecsSinceEpoch) const
    -{
    -    const NSTimeInterval seconds = atMSecsSinceEpoch / 1000.0;
    -    return QString::fromNSString([m_nstz abbreviationForDate:[NSDate dateWithTimeIntervalSince1970:seconds]]);
    -}
    -
    -int QMacTimeZonePrivate::offsetFromUtc(qint64 atMSecsSinceEpoch) const
    -{
    -    const NSTimeInterval seconds = atMSecsSinceEpoch / 1000.0;
    -    return [m_nstz secondsFromGMTForDate:[NSDate dateWithTimeIntervalSince1970:seconds]];
    -}
    -
    -int QMacTimeZonePrivate::standardTimeOffset(qint64 atMSecsSinceEpoch) const
    -{
    -    return offsetFromUtc(atMSecsSinceEpoch) - daylightTimeOffset(atMSecsSinceEpoch);
    -}
    -
    -int QMacTimeZonePrivate::daylightTimeOffset(qint64 atMSecsSinceEpoch) const
    -{
    -    const NSTimeInterval seconds = atMSecsSinceEpoch / 1000.0;
    -    return [m_nstz daylightSavingTimeOffsetForDate:[NSDate dateWithTimeIntervalSince1970:seconds]];
    -}
    -
    -bool QMacTimeZonePrivate::hasDaylightTime() const
    -{
    -    // TODO No Mac API, assume if has transitions
    -    return hasTransitions();
    -}
    -
    -bool QMacTimeZonePrivate::isDaylightTime(qint64 atMSecsSinceEpoch) const
    -{
    -    const NSTimeInterval seconds = atMSecsSinceEpoch / 1000.0;
    -    return [m_nstz isDaylightSavingTimeForDate:[NSDate dateWithTimeIntervalSince1970:seconds]];
    -}
    -
    -QTimeZonePrivate::Data QMacTimeZonePrivate::data(qint64 forMSecsSinceEpoch) const
    -{
    -    const NSTimeInterval seconds = forMSecsSinceEpoch / 1000.0;
    -    NSDate *date = [NSDate dateWithTimeIntervalSince1970:seconds];
    -    Data data;
    -    data.atMSecsSinceEpoch = forMSecsSinceEpoch;
    -    data.offsetFromUtc = [m_nstz secondsFromGMTForDate:date];
    -    data.daylightTimeOffset = [m_nstz daylightSavingTimeOffsetForDate:date];
    -    data.standardTimeOffset = data.offsetFromUtc - data.daylightTimeOffset;
    -    data.abbreviation = QString::fromNSString([m_nstz abbreviationForDate:date]);
    -    return data;
    -}
    -
    -bool QMacTimeZonePrivate::hasTransitions() const
    -{
    -    // TODO No direct Mac API, so return if has next after 1970, i.e. since start of tz
    -    // TODO Not sure what is returned in event of no transitions, assume will be before requested date
    -    NSDate *epoch = [NSDate dateWithTimeIntervalSince1970:0];
    -    const NSDate *date = [m_nstz nextDaylightSavingTimeTransitionAfterDate:epoch];
    -    const bool result = ([date timeIntervalSince1970] > [epoch timeIntervalSince1970]);
    -    return result;
    -}
    -
    -QTimeZonePrivate::Data QMacTimeZonePrivate::nextTransition(qint64 afterMSecsSinceEpoch) const
    -{
    -    QTimeZonePrivate::Data tran;
    -    const NSTimeInterval seconds = afterMSecsSinceEpoch / 1000.0;
    -    NSDate *nextDate = [NSDate dateWithTimeIntervalSince1970:seconds];
    -    nextDate = [m_nstz nextDaylightSavingTimeTransitionAfterDate:nextDate];
    -    const NSTimeInterval nextSecs = [nextDate timeIntervalSince1970];
    -    if (nextDate == nil || nextSecs <= seconds) {
    -        [nextDate release];
    -        return invalidData();
    -    }
    -    tran.atMSecsSinceEpoch = nextSecs * 1000;
    -    tran.offsetFromUtc = [m_nstz secondsFromGMTForDate:nextDate];
    -    tran.daylightTimeOffset = [m_nstz daylightSavingTimeOffsetForDate:nextDate];
    -    tran.standardTimeOffset = tran.offsetFromUtc - tran.daylightTimeOffset;
    -    tran.abbreviation = QString::fromNSString([m_nstz abbreviationForDate:nextDate]);
    -    return tran;
    -}
    -
    -QTimeZonePrivate::Data QMacTimeZonePrivate::previousTransition(qint64 beforeMSecsSinceEpoch) const
    -{
    -    // The native API only lets us search forward, so we need to find an early-enough start:
    -    const NSTimeInterval lowerBound = std::numeric_limits::lowest();
    -    const qint64 endSecs = beforeMSecsSinceEpoch / 1000;
    -    const int year = 366 * 24 * 3600; // a (long) year, in seconds
    -    NSTimeInterval prevSecs = endSecs; // sentinel for later check
    -    NSTimeInterval nextSecs = prevSecs - year;
    -    NSTimeInterval tranSecs = lowerBound; // time at a transition; may be > endSecs
    -
    -    NSDate *nextDate = [NSDate dateWithTimeIntervalSince1970:nextSecs];
    -    nextDate = [m_nstz nextDaylightSavingTimeTransitionAfterDate:nextDate];
    -    if (nextDate != nil
    -        && (tranSecs = [nextDate timeIntervalSince1970]) < endSecs) {
    -        // There's a transition within the last year before endSecs:
    -        nextSecs = tranSecs;
    -    } else {
    -        // Need to start our search earlier:
    -        nextDate = [NSDate dateWithTimeIntervalSince1970:lowerBound];
    -        nextDate = [m_nstz nextDaylightSavingTimeTransitionAfterDate:nextDate];
    -        if (nextDate != nil) {
    -            NSTimeInterval lateSecs = nextSecs;
    -            nextSecs = [nextDate timeIntervalSince1970];
    -            Q_ASSERT(nextSecs <= endSecs - year || nextSecs == tranSecs);
    -            /*
    -              We're looking at the first ever transition for our zone, at
    -              nextSecs (and our zone *does* have at least one transition).  If
    -              it's later than endSecs - year, then we must have found it on the
    -              initial check and therefore set tranSecs to the same transition
    -              time (which, we can infer here, is >= endSecs).  In this case, we
    -              won't enter the binary-chop loop, below.
    -
    -              In the loop, nextSecs < lateSecs < endSecs: we have a transition
    -              at nextSecs and there is no transition between lateSecs and
    -              endSecs.  The loop narrows the interval between nextSecs and
    -              lateSecs by looking for a transition after their mid-point; if it
    -              finds one < endSecs, nextSecs moves to this transition; otherwise,
    -              lateSecs moves to the mid-point.  This soon enough narrows the gap
    -              to within a year, after which walking forward one transition at a
    -              time (the "Wind through" loop, below) is good enough.
    -            */
    -
    -            // Binary chop to within a year of last transition before endSecs:
    -            while (nextSecs + year < lateSecs) {
    -                // Careful about overflow, not fussy about rounding errors:
    -                NSTimeInterval middle = nextSecs / 2 + lateSecs / 2;
    -                NSDate *split = [NSDate dateWithTimeIntervalSince1970:middle];
    -                split = [m_nstz nextDaylightSavingTimeTransitionAfterDate:split];
    -                if (split != nil
    -                    && (tranSecs = [split timeIntervalSince1970]) < endSecs) {
    -                    nextDate = split;
    -                    nextSecs = tranSecs;
    -                } else {
    -                    lateSecs = middle;
    -                }
    -            }
    -            Q_ASSERT(nextDate != nil);
    -            // ... and nextSecs < endSecs unless first transition ever was >= endSecs.
    -        } // else: we have no data - prevSecs is still endSecs, nextDate is still nil
    -    }
    -    // Either nextDate is nil or nextSecs is at its transition.
    -
    -    // Wind through remaining transitions (spanning at most a year), one at a time:
    -    while (nextDate != nil && nextSecs < endSecs) {
    -        prevSecs = nextSecs;
    -        nextDate = [m_nstz nextDaylightSavingTimeTransitionAfterDate:nextDate];
    -        nextSecs = [nextDate timeIntervalSince1970];
    -        if (nextSecs <= prevSecs) // presumably no later data available
    -            break;
    -    }
    -    if (prevSecs < endSecs) // i.e. we did make it into that while loop
    -        return data(qint64(prevSecs * 1e3));
    -
    -    // No transition data; or first transition later than requested time.
    -    return invalidData();
    -}
    -
    -QByteArray QMacTimeZonePrivate::systemTimeZoneId() const
    -{
    -    // Reset the cached system tz then return the name
    -    [NSTimeZone resetSystemTimeZone];
    -    return QString::fromNSString([[NSTimeZone systemTimeZone] name]).toUtf8();
    -}
    -
    -QList QMacTimeZonePrivate::availableTimeZoneIds() const
    -{
    -    NSEnumerator *enumerator = [[NSTimeZone knownTimeZoneNames] objectEnumerator];
    -    QByteArray tzid = QString::fromNSString([enumerator nextObject]).toUtf8();
    -
    -    QList list;
    -    while (!tzid.isEmpty()) {
    -        list << tzid;
    -        tzid = QString::fromNSString([enumerator nextObject]).toUtf8();
    -    }
    -
    -    std::sort(list.begin(), list.end());
    -    list.erase(std::unique(list.begin(), list.end()), list.end());
    -
    -    return list;
    -}
    -
    -NSTimeZone *QMacTimeZonePrivate::nsTimeZone() const
    -{
    -    return m_nstz;
    -}
    -
    -QT_END_NAMESPACE
    diff --git a/src/corelib/tools/qtimezoneprivate_p.h b/src/corelib/tools/qtimezoneprivate_p.h
    deleted file mode 100644
    index b5e9286f6a..0000000000
    --- a/src/corelib/tools/qtimezoneprivate_p.h
    +++ /dev/null
    @@ -1,493 +0,0 @@
    -/****************************************************************************
    -**
    -** Copyright (C) 2013 John Layt 
    -** Contact: https://www.qt.io/licensing/
    -**
    -** This file is part of the QtCore module of the Qt Toolkit.
    -**
    -** $QT_BEGIN_LICENSE:LGPL$
    -** Commercial License Usage
    -** Licensees holding valid commercial Qt licenses may use this file in
    -** accordance with the commercial license agreement provided with the
    -** Software or, alternatively, in accordance with the terms contained in
    -** a written agreement between you and The Qt Company. For licensing terms
    -** and conditions see https://www.qt.io/terms-conditions. For further
    -** information use the contact form at https://www.qt.io/contact-us.
    -**
    -** GNU Lesser General Public License Usage
    -** Alternatively, this file may be used under the terms of the GNU Lesser
    -** General Public License version 3 as published by the Free Software
    -** Foundation and appearing in the file LICENSE.LGPL3 included in the
    -** packaging of this file. Please review the following information to
    -** ensure the GNU Lesser General Public License version 3 requirements
    -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
    -**
    -** GNU General Public License Usage
    -** Alternatively, this file may be used under the terms of the GNU
    -** General Public License version 2.0 or (at your option) the GNU General
    -** Public license version 3 or any later version approved by the KDE Free
    -** Qt Foundation. The licenses are as published by the Free Software
    -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
    -** included in the packaging of this file. Please review the following
    -** information to ensure the GNU General Public License requirements will
    -** be met: https://www.gnu.org/licenses/gpl-2.0.html and
    -** https://www.gnu.org/licenses/gpl-3.0.html.
    -**
    -** $QT_END_LICENSE$
    -**
    -****************************************************************************/
    -
    -
    -#ifndef QTIMEZONEPRIVATE_P_H
    -#define QTIMEZONEPRIVATE_P_H
    -
    -//
    -//  W A R N I N G
    -//  -------------
    -//
    -// This file is not part of the Qt API.  It exists for the convenience
    -// of internal files.  This header file may change from version to version
    -// without notice, or even be removed.
    -//
    -// We mean it.
    -//
    -
    -#include "qtimezone.h"
    -#include "qlocale_p.h"
    -#include "qvector.h"
    -
    -#if QT_CONFIG(icu)
    -#include 
    -#endif
    -
    -#ifdef Q_OS_DARWIN
    -Q_FORWARD_DECLARE_OBJC_CLASS(NSTimeZone);
    -#endif // Q_OS_DARWIN
    -
    -#ifdef Q_OS_WIN
    -#include 
    -#endif // Q_OS_WIN
    -
    -#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
    -#include 
    -#endif
    -
    -QT_BEGIN_NAMESPACE
    -
    -class Q_AUTOTEST_EXPORT QTimeZonePrivate : public QSharedData
    -{
    -public:
    -    //Version of QTimeZone::OffsetData struct using msecs for efficiency
    -    struct Data {
    -        QString abbreviation;
    -        qint64 atMSecsSinceEpoch;
    -        int offsetFromUtc;
    -        int standardTimeOffset;
    -        int daylightTimeOffset;
    -    };
    -    typedef QVector DataList;
    -
    -    // Create null time zone
    -    QTimeZonePrivate();
    -    QTimeZonePrivate(const QTimeZonePrivate &other);
    -    virtual ~QTimeZonePrivate();
    -
    -    virtual QTimeZonePrivate *clone() const;
    -
    -    bool operator==(const QTimeZonePrivate &other) const;
    -    bool operator!=(const QTimeZonePrivate &other) const;
    -
    -    bool isValid() const;
    -
    -    QByteArray id() const;
    -    virtual QLocale::Country country() const;
    -    virtual QString comment() const;
    -
    -    virtual QString displayName(qint64 atMSecsSinceEpoch,
    -                                QTimeZone::NameType nameType,
    -                                const QLocale &locale) const;
    -    virtual QString displayName(QTimeZone::TimeType timeType,
    -                                QTimeZone::NameType nameType,
    -                                const QLocale &locale) const;
    -    virtual QString abbreviation(qint64 atMSecsSinceEpoch) const;
    -
    -    virtual int offsetFromUtc(qint64 atMSecsSinceEpoch) const;
    -    virtual int standardTimeOffset(qint64 atMSecsSinceEpoch) const;
    -    virtual int daylightTimeOffset(qint64 atMSecsSinceEpoch) const;
    -
    -    virtual bool hasDaylightTime() const;
    -    virtual bool isDaylightTime(qint64 atMSecsSinceEpoch) const;
    -
    -    virtual Data data(qint64 forMSecsSinceEpoch) const;
    -    Data dataForLocalTime(qint64 forLocalMSecs, int hint) const;
    -
    -    virtual bool hasTransitions() const;
    -    virtual Data nextTransition(qint64 afterMSecsSinceEpoch) const;
    -    virtual Data previousTransition(qint64 beforeMSecsSinceEpoch) const;
    -    DataList transitions(qint64 fromMSecsSinceEpoch, qint64 toMSecsSinceEpoch) const;
    -
    -    virtual QByteArray systemTimeZoneId() const;
    -
    -    virtual bool isTimeZoneIdAvailable(const QByteArray &ianaId) const;
    -    virtual QList availableTimeZoneIds() const;
    -    virtual QList availableTimeZoneIds(QLocale::Country country) const;
    -    virtual QList availableTimeZoneIds(int utcOffset) const;
    -
    -    virtual void serialize(QDataStream &ds) const;
    -
    -    // Static Utility Methods
    -    static inline qint64 maxMSecs() { return std::numeric_limits::max(); }
    -    static inline qint64 minMSecs() { return std::numeric_limits::min() + 1; }
    -    static inline qint64 invalidMSecs() { return std::numeric_limits::min(); }
    -    static inline qint64 invalidSeconds() { return std::numeric_limits::min(); }
    -    static Data invalidData();
    -    static QTimeZone::OffsetData invalidOffsetData();
    -    static QTimeZone::OffsetData toOffsetData(const Data &data);
    -    static bool isValidId(const QByteArray &ianaId);
    -    static QString isoOffsetFormat(int offsetFromUtc);
    -
    -    static QByteArray ianaIdToWindowsId(const QByteArray &ianaId);
    -    static QByteArray windowsIdToDefaultIanaId(const QByteArray &windowsId);
    -    static QByteArray windowsIdToDefaultIanaId(const QByteArray &windowsId,
    -                                                QLocale::Country country);
    -    static QList windowsIdToIanaIds(const QByteArray &windowsId);
    -    static QList windowsIdToIanaIds(const QByteArray &windowsId,
    -                                                 QLocale::Country country);
    -
    -    // returns "UTC" QString and QByteArray
    -    Q_REQUIRED_RESULT static inline QString utcQString()
    -    {
    -        return QStringLiteral("UTC");
    -    }
    -
    -    Q_REQUIRED_RESULT static inline QByteArray utcQByteArray()
    -    {
    -        return QByteArrayLiteral("UTC");
    -    }
    -
    -protected:
    -    QByteArray m_id;
    -};
    -Q_DECLARE_TYPEINFO(QTimeZonePrivate::Data, Q_MOVABLE_TYPE);
    -
    -template<> QTimeZonePrivate *QSharedDataPointer::clone();
    -
    -class Q_AUTOTEST_EXPORT QUtcTimeZonePrivate final : public QTimeZonePrivate
    -{
    -public:
    -    // Create default UTC time zone
    -    QUtcTimeZonePrivate();
    -    // Create named time zone
    -    QUtcTimeZonePrivate(const QByteArray &utcId);
    -    // Create offset from UTC
    -    QUtcTimeZonePrivate(int offsetSeconds);
    -    // Create custom offset from UTC
    -    QUtcTimeZonePrivate(const QByteArray &zoneId, int offsetSeconds, const QString &name,
    -                        const QString &abbreviation, QLocale::Country country,
    -                        const QString &comment);
    -    QUtcTimeZonePrivate(const QUtcTimeZonePrivate &other);
    -    virtual ~QUtcTimeZonePrivate();
    -
    -    QUtcTimeZonePrivate *clone() const override;
    -
    -    Data data(qint64 forMSecsSinceEpoch) const override;
    -
    -    QLocale::Country country() const override;
    -    QString comment() const override;
    -
    -    QString displayName(QTimeZone::TimeType timeType,
    -                        QTimeZone::NameType nameType,
    -                        const QLocale &locale) const override;
    -    QString abbreviation(qint64 atMSecsSinceEpoch) const override;
    -
    -    int standardTimeOffset(qint64 atMSecsSinceEpoch) const override;
    -    int daylightTimeOffset(qint64 atMSecsSinceEpoch) const override;
    -
    -    QByteArray systemTimeZoneId() const override;
    -
    -    bool isTimeZoneIdAvailable(const QByteArray &ianaId) const override;
    -    QList availableTimeZoneIds() const override;
    -    QList availableTimeZoneIds(QLocale::Country country) const override;
    -    QList availableTimeZoneIds(int utcOffset) const override;
    -
    -    void serialize(QDataStream &ds) const override;
    -
    -private:
    -    void init(const QByteArray &zoneId);
    -    void init(const QByteArray &zoneId, int offsetSeconds, const QString &name,
    -              const QString &abbreviation, QLocale::Country country,
    -              const QString &comment);
    -
    -    QString m_name;
    -    QString m_abbreviation;
    -    QString m_comment;
    -    QLocale::Country m_country;
    -    int m_offsetFromUtc;
    -};
    -
    -#if QT_CONFIG(icu)
    -class Q_AUTOTEST_EXPORT QIcuTimeZonePrivate final : public QTimeZonePrivate
    -{
    -public:
    -    // Create default time zone
    -    QIcuTimeZonePrivate();
    -    // Create named time zone
    -    QIcuTimeZonePrivate(const QByteArray &ianaId);
    -    QIcuTimeZonePrivate(const QIcuTimeZonePrivate &other);
    -    ~QIcuTimeZonePrivate();
    -
    -    QIcuTimeZonePrivate *clone() const override;
    -
    -    QString displayName(QTimeZone::TimeType timeType, QTimeZone::NameType nameType,
    -                        const QLocale &locale) const override;
    -    QString abbreviation(qint64 atMSecsSinceEpoch) const override;
    -
    -    int offsetFromUtc(qint64 atMSecsSinceEpoch) const override;
    -    int standardTimeOffset(qint64 atMSecsSinceEpoch) const override;
    -    int daylightTimeOffset(qint64 atMSecsSinceEpoch) const override;
    -
    -    bool hasDaylightTime() const override;
    -    bool isDaylightTime(qint64 atMSecsSinceEpoch) const override;
    -
    -    Data data(qint64 forMSecsSinceEpoch) const override;
    -
    -    bool hasTransitions() const override;
    -    Data nextTransition(qint64 afterMSecsSinceEpoch) const override;
    -    Data previousTransition(qint64 beforeMSecsSinceEpoch) const override;
    -
    -    QByteArray systemTimeZoneId() const override;
    -
    -    QList availableTimeZoneIds() const override;
    -    QList availableTimeZoneIds(QLocale::Country country) const override;
    -    QList availableTimeZoneIds(int offsetFromUtc) const override;
    -
    -private:
    -    void init(const QByteArray &ianaId);
    -
    -    UCalendar *m_ucal;
    -};
    -#endif
    -
    -#if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_EMBEDDED))
    -struct QTzTransitionTime
    -{
    -    qint64 atMSecsSinceEpoch;
    -    quint8 ruleIndex;
    -};
    -Q_DECLARE_TYPEINFO(QTzTransitionTime, Q_PRIMITIVE_TYPE);
    -struct QTzTransitionRule
    -{
    -    int stdOffset;
    -    int dstOffset;
    -    quint8 abbreviationIndex;
    -};
    -Q_DECLARE_TYPEINFO(QTzTransitionRule, Q_PRIMITIVE_TYPE);
    -Q_DECL_CONSTEXPR inline bool operator==(const QTzTransitionRule &lhs, const QTzTransitionRule &rhs) noexcept
    -{ return lhs.stdOffset == rhs.stdOffset && lhs.dstOffset == rhs.dstOffset && lhs.abbreviationIndex == rhs.abbreviationIndex; }
    -Q_DECL_CONSTEXPR inline bool operator!=(const QTzTransitionRule &lhs, const QTzTransitionRule &rhs) noexcept
    -{ return !operator==(lhs, rhs); }
    -
    -class Q_AUTOTEST_EXPORT QTzTimeZonePrivate final : public QTimeZonePrivate
    -{
    -    QTzTimeZonePrivate(const QTzTimeZonePrivate &) = default;
    -public:
    -    // Create default time zone
    -    QTzTimeZonePrivate();
    -    // Create named time zone
    -    QTzTimeZonePrivate(const QByteArray &ianaId);
    -    ~QTzTimeZonePrivate();
    -
    -    QTzTimeZonePrivate *clone() const override;
    -
    -    QLocale::Country country() const override;
    -    QString comment() const override;
    -
    -    QString displayName(qint64 atMSecsSinceEpoch,
    -                        QTimeZone::NameType nameType,
    -                        const QLocale &locale) const override;
    -    QString displayName(QTimeZone::TimeType timeType,
    -                        QTimeZone::NameType nameType,
    -                        const QLocale &locale) const override;
    -    QString abbreviation(qint64 atMSecsSinceEpoch) const override;
    -
    -    int offsetFromUtc(qint64 atMSecsSinceEpoch) const override;
    -    int standardTimeOffset(qint64 atMSecsSinceEpoch) const override;
    -    int daylightTimeOffset(qint64 atMSecsSinceEpoch) const override;
    -
    -    bool hasDaylightTime() const override;
    -    bool isDaylightTime(qint64 atMSecsSinceEpoch) const override;
    -
    -    Data data(qint64 forMSecsSinceEpoch) const override;
    -
    -    bool hasTransitions() const override;
    -    Data nextTransition(qint64 afterMSecsSinceEpoch) const override;
    -    Data previousTransition(qint64 beforeMSecsSinceEpoch) const override;
    -
    -    QByteArray systemTimeZoneId() const override;
    -
    -    bool isTimeZoneIdAvailable(const QByteArray &ianaId) const override;
    -    QList availableTimeZoneIds() const override;
    -    QList availableTimeZoneIds(QLocale::Country country) const override;
    -
    -private:
    -    void init(const QByteArray &ianaId);
    -    QVector getPosixTransitions(qint64 msNear) const;
    -
    -    Data dataForTzTransition(QTzTransitionTime tran) const;
    -    QVector m_tranTimes;
    -    QVector m_tranRules;
    -    QList m_abbreviations;
    -#if QT_CONFIG(icu)
    -    mutable QSharedDataPointer m_icu;
    -#endif
    -    QByteArray m_posixRule;
    -};
    -#endif // Q_OS_UNIX
    -
    -#ifdef Q_OS_MAC
    -class Q_AUTOTEST_EXPORT QMacTimeZonePrivate final : public QTimeZonePrivate
    -{
    -public:
    -    // Create default time zone
    -    QMacTimeZonePrivate();
    -    // Create named time zone
    -    QMacTimeZonePrivate(const QByteArray &ianaId);
    -    QMacTimeZonePrivate(const QMacTimeZonePrivate &other);
    -    ~QMacTimeZonePrivate();
    -
    -    QMacTimeZonePrivate *clone() const override;
    -
    -    QString comment() const override;
    -
    -    QString displayName(QTimeZone::TimeType timeType, QTimeZone::NameType nameType,
    -                        const QLocale &locale) const override;
    -    QString abbreviation(qint64 atMSecsSinceEpoch) const override;
    -
    -    int offsetFromUtc(qint64 atMSecsSinceEpoch) const override;
    -    int standardTimeOffset(qint64 atMSecsSinceEpoch) const override;
    -    int daylightTimeOffset(qint64 atMSecsSinceEpoch) const override;
    -
    -    bool hasDaylightTime() const override;
    -    bool isDaylightTime(qint64 atMSecsSinceEpoch) const override;
    -
    -    Data data(qint64 forMSecsSinceEpoch) const override;
    -
    -    bool hasTransitions() const override;
    -    Data nextTransition(qint64 afterMSecsSinceEpoch) const override;
    -    Data previousTransition(qint64 beforeMSecsSinceEpoch) const override;
    -
    -    QByteArray systemTimeZoneId() const override;
    -
    -    QList availableTimeZoneIds() const override;
    -
    -    NSTimeZone *nsTimeZone() const;
    -
    -private:
    -    void init(const QByteArray &zoneId);
    -
    -    NSTimeZone *m_nstz;
    -};
    -#endif // Q_OS_MAC
    -
    -#ifdef Q_OS_WIN
    -class Q_AUTOTEST_EXPORT QWinTimeZonePrivate final : public QTimeZonePrivate
    -{
    -public:
    -    struct QWinTransitionRule {
    -        int startYear;
    -        int standardTimeBias;
    -        int daylightTimeBias;
    -        SYSTEMTIME standardTimeRule;
    -        SYSTEMTIME daylightTimeRule;
    -    };
    -
    -    // Create default time zone
    -    QWinTimeZonePrivate();
    -    // Create named time zone
    -    QWinTimeZonePrivate(const QByteArray &ianaId);
    -    QWinTimeZonePrivate(const QWinTimeZonePrivate &other);
    -    ~QWinTimeZonePrivate();
    -
    -    QWinTimeZonePrivate *clone() const override;
    -
    -    QString comment() const override;
    -
    -    QString displayName(QTimeZone::TimeType timeType, QTimeZone::NameType nameType,
    -                        const QLocale &locale) const override;
    -    QString abbreviation(qint64 atMSecsSinceEpoch) const override;
    -
    -    int offsetFromUtc(qint64 atMSecsSinceEpoch) const override;
    -    int standardTimeOffset(qint64 atMSecsSinceEpoch) const override;
    -    int daylightTimeOffset(qint64 atMSecsSinceEpoch) const override;
    -
    -    bool hasDaylightTime() const override;
    -    bool isDaylightTime(qint64 atMSecsSinceEpoch) const override;
    -
    -    Data data(qint64 forMSecsSinceEpoch) const override;
    -
    -    bool hasTransitions() const override;
    -    Data nextTransition(qint64 afterMSecsSinceEpoch) const override;
    -    Data previousTransition(qint64 beforeMSecsSinceEpoch) const override;
    -
    -    QByteArray systemTimeZoneId() const override;
    -
    -    QList availableTimeZoneIds() const override;
    -
    -private:
    -    void init(const QByteArray &ianaId);
    -    QTimeZonePrivate::Data ruleToData(const QWinTransitionRule &rule, qint64 atMSecsSinceEpoch,
    -                                      QTimeZone::TimeType type, bool fakeDst = false) const;
    -
    -    QByteArray m_windowsId;
    -    QString m_displayName;
    -    QString m_standardName;
    -    QString m_daylightName;
    -    QList m_tranRules;
    -};
    -#endif // Q_OS_WIN
    -
    -#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
    -class QAndroidTimeZonePrivate final : public QTimeZonePrivate
    -{
    -public:
    -    // Create default time zone
    -    QAndroidTimeZonePrivate();
    -    // Create named time zone
    -    QAndroidTimeZonePrivate(const QByteArray &ianaId);
    -    QAndroidTimeZonePrivate(const QAndroidTimeZonePrivate &other);
    -    ~QAndroidTimeZonePrivate();
    -
    -    QAndroidTimeZonePrivate *clone() const override;
    -
    -    QString displayName(QTimeZone::TimeType timeType, QTimeZone::NameType nameType,
    -                        const QLocale &locale) const override;
    -    QString abbreviation(qint64 atMSecsSinceEpoch) const override;
    -
    -    int offsetFromUtc(qint64 atMSecsSinceEpoch) const override;
    -    int standardTimeOffset(qint64 atMSecsSinceEpoch) const override;
    -    int daylightTimeOffset(qint64 atMSecsSinceEpoch) const override;
    -
    -    bool hasDaylightTime() const override;
    -    bool isDaylightTime(qint64 atMSecsSinceEpoch) const override;
    -
    -    Data data(qint64 forMSecsSinceEpoch) const override;
    -
    -    bool hasTransitions() const override;
    -    Data nextTransition(qint64 afterMSecsSinceEpoch) const override;
    -    Data previousTransition(qint64 beforeMSecsSinceEpoch) const override;
    -
    -    QByteArray systemTimeZoneId() const override;
    -
    -    QList availableTimeZoneIds() const override;
    -
    -private:
    -    void init(const QByteArray &zoneId);
    -
    -    QJNIObjectPrivate androidTimeZone;
    -
    -};
    -#endif // Q_OS_ANDROID
    -
    -QT_END_NAMESPACE
    -
    -#endif // QTIMEZONEPRIVATE_P_H
    diff --git a/src/corelib/tools/qtimezoneprivate_tz.cpp b/src/corelib/tools/qtimezoneprivate_tz.cpp
    deleted file mode 100644
    index f5440799ab..0000000000
    --- a/src/corelib/tools/qtimezoneprivate_tz.cpp
    +++ /dev/null
    @@ -1,1155 +0,0 @@
    -/****************************************************************************
    -**
    -** Copyright (C) 2013 John Layt 
    -** Contact: https://www.qt.io/licensing/
    -**
    -** This file is part of the QtCore module of the Qt Toolkit.
    -**
    -** $QT_BEGIN_LICENSE:LGPL$
    -** Commercial License Usage
    -** Licensees holding valid commercial Qt licenses may use this file in
    -** accordance with the commercial license agreement provided with the
    -** Software or, alternatively, in accordance with the terms contained in
    -** a written agreement between you and The Qt Company. For licensing terms
    -** and conditions see https://www.qt.io/terms-conditions. For further
    -** information use the contact form at https://www.qt.io/contact-us.
    -**
    -** GNU Lesser General Public License Usage
    -** Alternatively, this file may be used under the terms of the GNU Lesser
    -** General Public License version 3 as published by the Free Software
    -** Foundation and appearing in the file LICENSE.LGPL3 included in the
    -** packaging of this file. Please review the following information to
    -** ensure the GNU Lesser General Public License version 3 requirements
    -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
    -**
    -** GNU General Public License Usage
    -** Alternatively, this file may be used under the terms of the GNU
    -** General Public License version 2.0 or (at your option) the GNU General
    -** Public license version 3 or any later version approved by the KDE Free
    -** Qt Foundation. The licenses are as published by the Free Software
    -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
    -** included in the packaging of this file. Please review the following
    -** information to ensure the GNU General Public License requirements will
    -** be met: https://www.gnu.org/licenses/gpl-2.0.html and
    -** https://www.gnu.org/licenses/gpl-3.0.html.
    -**
    -** $QT_END_LICENSE$
    -**
    -****************************************************************************/
    -
    -#include "qtimezone.h"
    -#include "qtimezoneprivate_p.h"
    -#include "qdatetime_p.h" // ### Qt 5.14: remove once YearRange is on QDateTime
    -
    -#include 
    -#include 
    -#include 
    -#include 
    -
    -#include 
    -
    -#include "qlocale_tools_p.h"
    -
    -#include 
    -
    -QT_BEGIN_NAMESPACE
    -
    -/*
    -    Private
    -
    -    tz file implementation
    -*/
    -
    -struct QTzTimeZone {
    -    QLocale::Country country;
    -    QByteArray comment;
    -};
    -
    -// Define as a type as Q_GLOBAL_STATIC doesn't like it
    -typedef QHash QTzTimeZoneHash;
    -
    -// Parse zone.tab table, assume lists all installed zones, if not will need to read directories
    -static QTzTimeZoneHash loadTzTimeZones()
    -{
    -    QString path = QStringLiteral("/usr/share/zoneinfo/zone.tab");
    -    if (!QFile::exists(path))
    -        path = QStringLiteral("/usr/lib/zoneinfo/zone.tab");
    -
    -    QFile tzif(path);
    -    if (!tzif.open(QIODevice::ReadOnly))
    -        return QTzTimeZoneHash();
    -
    -    QTzTimeZoneHash zonesHash;
    -    // TODO QTextStream inefficient, replace later
    -    QTextStream ts(&tzif);
    -    while (!ts.atEnd()) {
    -        const QString line = ts.readLine();
    -        // Comment lines are prefixed with a #
    -        if (!line.isEmpty() && line.at(0) != '#') {
    -            // Data rows are tab-separated columns Region, Coordinates, ID, Optional Comments
    -            const auto parts = line.splitRef(QLatin1Char('\t'));
    -            QTzTimeZone zone;
    -            zone.country = QLocalePrivate::codeToCountry(parts.at(0));
    -            if (parts.size() > 3)
    -                zone.comment = parts.at(3).toUtf8();
    -            zonesHash.insert(parts.at(2).toUtf8(), zone);
    -        }
    -    }
    -    return zonesHash;
    -}
    -
    -// Hash of available system tz files as loaded by loadTzTimeZones()
    -Q_GLOBAL_STATIC_WITH_ARGS(const QTzTimeZoneHash, tzZones, (loadTzTimeZones()));
    -
    -/*
    -    The following is copied and modified from tzfile.h which is in the public domain.
    -    Copied as no compatibility guarantee and is never system installed.
    -    See https://github.com/eggert/tz/blob/master/tzfile.h
    -*/
    -
    -#define TZ_MAGIC      "TZif"
    -#define TZ_MAX_TIMES  1200
    -#define TZ_MAX_TYPES   256  // Limited by what (unsigned char)'s can hold
    -#define TZ_MAX_CHARS    50  // Maximum number of abbreviation characters
    -#define TZ_MAX_LEAPS    50  // Maximum number of leap second corrections
    -
    -struct QTzHeader {
    -    char       tzh_magic[4];        // TZ_MAGIC
    -    char       tzh_version;         // '\0' or '2' as of 2005
    -    char       tzh_reserved[15];    // reserved--must be zero
    -    quint32    tzh_ttisgmtcnt;      // number of trans. time flags
    -    quint32    tzh_ttisstdcnt;      // number of trans. time flags
    -    quint32    tzh_leapcnt;         // number of leap seconds
    -    quint32    tzh_timecnt;         // number of transition times
    -    quint32    tzh_typecnt;         // number of local time types
    -    quint32    tzh_charcnt;         // number of abbr. chars
    -};
    -
    -struct QTzTransition {
    -    qint64 tz_time;     // Transition time
    -    quint8 tz_typeind;  // Type Index
    -};
    -Q_DECLARE_TYPEINFO(QTzTransition, Q_PRIMITIVE_TYPE);
    -
    -struct QTzType {
    -    int tz_gmtoff;  // UTC offset in seconds
    -    bool   tz_isdst;   // Is DST
    -    quint8 tz_abbrind; // abbreviation list index
    -};
    -Q_DECLARE_TYPEINFO(QTzType, Q_PRIMITIVE_TYPE);
    -
    -
    -// TZ File parsing
    -
    -static QTzHeader parseTzHeader(QDataStream &ds, bool *ok)
    -{
    -    QTzHeader hdr;
    -    quint8 ch;
    -    *ok = false;
    -
    -    // Parse Magic, 4 bytes
    -    ds.readRawData(hdr.tzh_magic, 4);
    -
    -    if (memcmp(hdr.tzh_magic, TZ_MAGIC, 4) != 0 || ds.status() != QDataStream::Ok)
    -        return hdr;
    -
    -    // Parse Version, 1 byte, before 2005 was '\0', since 2005 a '2', since 2013 a '3'
    -    ds >> ch;
    -    hdr.tzh_version = ch;
    -    if (ds.status() != QDataStream::Ok
    -        || (hdr.tzh_version != '2' && hdr.tzh_version != '\0' && hdr.tzh_version != '3')) {
    -        return hdr;
    -    }
    -
    -    // Parse reserved space, 15 bytes
    -    ds.readRawData(hdr.tzh_reserved, 15);
    -    if (ds.status() != QDataStream::Ok)
    -        return hdr;
    -
    -    // Parse rest of header, 6 x 4-byte transition counts
    -    ds >> hdr.tzh_ttisgmtcnt >> hdr.tzh_ttisstdcnt >> hdr.tzh_leapcnt >> hdr.tzh_timecnt
    -       >> hdr.tzh_typecnt >> hdr.tzh_charcnt;
    -
    -    // Check defined maximums
    -    if (ds.status() != QDataStream::Ok
    -        || hdr.tzh_timecnt > TZ_MAX_TIMES
    -        || hdr.tzh_typecnt > TZ_MAX_TYPES
    -        || hdr.tzh_charcnt > TZ_MAX_CHARS
    -        || hdr.tzh_leapcnt > TZ_MAX_LEAPS
    -        || hdr.tzh_ttisgmtcnt > hdr.tzh_typecnt
    -        || hdr.tzh_ttisstdcnt > hdr.tzh_typecnt) {
    -        return hdr;
    -    }
    -
    -    *ok = true;
    -    return hdr;
    -}
    -
    -static QVector parseTzTransitions(QDataStream &ds, int tzh_timecnt, bool longTran)
    -{
    -    QVector transitions(tzh_timecnt);
    -
    -    if (longTran) {
    -        // Parse tzh_timecnt x 8-byte transition times
    -        for (int i = 0; i < tzh_timecnt && ds.status() == QDataStream::Ok; ++i) {
    -            ds >> transitions[i].tz_time;
    -            if (ds.status() != QDataStream::Ok)
    -                transitions.resize(i);
    -        }
    -    } else {
    -        // Parse tzh_timecnt x 4-byte transition times
    -        qint32 val;
    -        for (int i = 0; i < tzh_timecnt && ds.status() == QDataStream::Ok; ++i) {
    -            ds >> val;
    -            transitions[i].tz_time = val;
    -            if (ds.status() != QDataStream::Ok)
    -                transitions.resize(i);
    -        }
    -    }
    -
    -    // Parse tzh_timecnt x 1-byte transition type index
    -    for (int i = 0; i < tzh_timecnt && ds.status() == QDataStream::Ok; ++i) {
    -        quint8 typeind;
    -        ds >> typeind;
    -        if (ds.status() == QDataStream::Ok)
    -            transitions[i].tz_typeind = typeind;
    -    }
    -
    -    return transitions;
    -}
    -
    -static QVector parseTzTypes(QDataStream &ds, int tzh_typecnt)
    -{
    -    QVector types(tzh_typecnt);
    -
    -    // Parse tzh_typecnt x transition types
    -    for (int i = 0; i < tzh_typecnt && ds.status() == QDataStream::Ok; ++i) {
    -        QTzType &type = types[i];
    -        // Parse UTC Offset, 4 bytes
    -        ds >> type.tz_gmtoff;
    -        // Parse Is DST flag, 1 byte
    -        if (ds.status() == QDataStream::Ok)
    -            ds >> type.tz_isdst;
    -        // Parse Abbreviation Array Index, 1 byte
    -        if (ds.status() == QDataStream::Ok)
    -            ds >> type.tz_abbrind;
    -        if (ds.status() != QDataStream::Ok)
    -            types.resize(i);
    -    }
    -
    -    return types;
    -}
    -
    -static QMap parseTzAbbreviations(QDataStream &ds, int tzh_charcnt, const QVector &types)
    -{
    -    // Parse the abbreviation list which is tzh_charcnt long with '\0' separated strings. The
    -    // QTzType.tz_abbrind index points to the first char of the abbreviation in the array, not the
    -    // occurrence in the list. It can also point to a partial string so we need to use the actual typeList
    -    // index values when parsing.  By using a map with tz_abbrind as ordered key we get both index
    -    // methods in one data structure and can convert the types afterwards.
    -    QMap map;
    -    quint8 ch;
    -    QByteArray input;
    -    // First parse the full abbrev string
    -    for (int i = 0; i < tzh_charcnt && ds.status() == QDataStream::Ok; ++i) {
    -        ds >> ch;
    -        if (ds.status() == QDataStream::Ok)
    -            input.append(char(ch));
    -        else
    -            return map;
    -    }
    -    // Then extract all the substrings pointed to by types
    -    for (const QTzType &type : types) {
    -        QByteArray abbrev;
    -        for (int i = type.tz_abbrind; input.at(i) != '\0'; ++i)
    -            abbrev.append(input.at(i));
    -        // Have reached end of an abbreviation, so add to map
    -        map[type.tz_abbrind] = abbrev;
    -    }
    -    return map;
    -}
    -
    -static void parseTzLeapSeconds(QDataStream &ds, int tzh_leapcnt, bool longTran)
    -{
    -    // Parse tzh_leapcnt x pairs of leap seconds
    -    // We don't use leap seconds, so only read and don't store
    -    qint32 val;
    -    if (longTran) {
    -        // v2 file format, each entry is 12 bytes long
    -        qint64 time;
    -        for (int i = 0; i < tzh_leapcnt && ds.status() == QDataStream::Ok; ++i) {
    -            // Parse Leap Occurrence Time, 8 bytes
    -            ds >> time;
    -            // Parse Leap Seconds To Apply, 4 bytes
    -            if (ds.status() == QDataStream::Ok)
    -                ds >> val;
    -        }
    -    } else {
    -        // v0 file format, each entry is 8 bytes long
    -        for (int i = 0; i < tzh_leapcnt && ds.status() == QDataStream::Ok; ++i) {
    -            // Parse Leap Occurrence Time, 4 bytes
    -            ds >> val;
    -            // Parse Leap Seconds To Apply, 4 bytes
    -            if (ds.status() == QDataStream::Ok)
    -                ds >> val;
    -        }
    -    }
    -}
    -
    -static QVector parseTzIndicators(QDataStream &ds, const QVector &types, int tzh_ttisstdcnt, int tzh_ttisgmtcnt)
    -{
    -    QVector result = types;
    -    bool temp;
    -    /*
    -      Scan and discard indicators.
    -
    -      These indicators are only of use (by the date program) when "handling
    -      POSIX-style time zone environment variables".  The flags here say whether
    -      the *specification* of the zone gave the time in UTC, local standard time
    -      or local wall time; but whatever was specified has been digested for us,
    -      already, by the zone-info compiler (zic), so that the tz_time values read
    -      from the file (by parseTzTransitions) are all in UTC.
    -     */
    -
    -    // Scan tzh_ttisstdcnt x 1-byte standard/wall indicators
    -    for (int i = 0; i < tzh_ttisstdcnt && ds.status() == QDataStream::Ok; ++i)
    -        ds >> temp;
    -
    -    // Scan tzh_ttisgmtcnt x 1-byte UTC/local indicators
    -    for (int i = 0; i < tzh_ttisgmtcnt && ds.status() == QDataStream::Ok; ++i)
    -        ds >> temp;
    -
    -    return result;
    -}
    -
    -static QByteArray parseTzPosixRule(QDataStream &ds)
    -{
    -    // Parse POSIX rule, variable length '\n' enclosed
    -    QByteArray rule;
    -
    -    quint8 ch;
    -    ds >> ch;
    -    if (ch != '\n' || ds.status() != QDataStream::Ok)
    -        return rule;
    -    ds >> ch;
    -    while (ch != '\n' && ds.status() == QDataStream::Ok) {
    -        rule.append((char)ch);
    -        ds >> ch;
    -    }
    -
    -    return rule;
    -}
    -
    -static QDate calculateDowDate(int year, int month, int dayOfWeek, int week)
    -{
    -    QDate date(year, month, 1);
    -    int startDow = date.dayOfWeek();
    -    if (startDow <= dayOfWeek)
    -        date = date.addDays(dayOfWeek - startDow - 7);
    -    else
    -        date = date.addDays(dayOfWeek - startDow);
    -    date = date.addDays(week * 7);
    -    while (date.month() != month)
    -        date = date.addDays(-7);
    -    return date;
    -}
    -
    -static QDate calculatePosixDate(const QByteArray &dateRule, int year)
    -{
    -    // Can start with M, J, or a digit
    -    if (dateRule.at(0) == 'M') {
    -        // nth week in month format "Mmonth.week.dow"
    -        QList dateParts = dateRule.split('.');
    -        int month = dateParts.at(0).mid(1).toInt();
    -        int week = dateParts.at(1).toInt();
    -        int dow = dateParts.at(2).toInt();
    -        if (dow == 0)
    -            ++dow;
    -        return calculateDowDate(year, month, dow, week);
    -    } else if (dateRule.at(0) == 'J') {
    -        // Day of Year ignores Feb 29
    -        int doy = dateRule.mid(1).toInt();
    -        QDate date = QDate(year, 1, 1).addDays(doy - 1);
    -        if (QDate::isLeapYear(date.year()))
    -            date = date.addDays(-1);
    -        return date;
    -    } else {
    -        // Day of Year includes Feb 29
    -        int doy = dateRule.toInt();
    -        return QDate(year, 1, 1).addDays(doy - 1);
    -    }
    -}
    -
    -// returns the time in seconds, INT_MIN if we failed to parse
    -static int parsePosixTime(const char *begin, const char *end)
    -{
    -    // Format "hh[:mm[:ss]]"
    -    int hour, min = 0, sec = 0;
    -
    -    // Note that the calls to qstrtoll do *not* check the end pointer, which
    -    // means they proceed until they find a non-digit. We check that we're
    -    // still in range at the end, but we may have read from past end. It's the
    -    // caller's responsibility to ensure that begin is part of a
    -    // null-terminated string.
    -
    -    bool ok = false;
    -    hour = qstrtoll(begin, &begin, 10, &ok);
    -    if (!ok || hour < 0)
    -        return INT_MIN;
    -    if (begin < end && *begin == ':') {
    -        // minutes
    -        ++begin;
    -        min = qstrtoll(begin, &begin, 10, &ok);
    -        if (!ok || min < 0)
    -            return INT_MIN;
    -
    -        if (begin < end && *begin == ':') {
    -            // seconds
    -            ++begin;
    -            sec = qstrtoll(begin, &begin, 10, &ok);
    -            if (!ok || sec < 0)
    -                return INT_MIN;
    -        }
    -    }
    -
    -    // we must have consumed everything
    -    if (begin != end)
    -        return INT_MIN;
    -
    -    return (hour * 60 + min) * 60 + sec;
    -}
    -
    -static QTime parsePosixTransitionTime(const QByteArray &timeRule)
    -{
    -    // Format "hh[:mm[:ss]]"
    -    int value = parsePosixTime(timeRule.constBegin(), timeRule.constEnd());
    -    if (value == INT_MIN) {
    -        // if we failed to parse, return 02:00
    -        return QTime(2, 0, 0);
    -    }
    -    return QTime::fromMSecsSinceStartOfDay(value * 1000);
    -}
    -
    -static int parsePosixOffset(const char *begin, const char *end)
    -{
    -    // Format "[+|-]hh[:mm[:ss]]"
    -    // note that the sign is inverted because POSIX counts in hours West of GMT
    -    bool negate = true;
    -    if (*begin == '+') {
    -        ++begin;
    -    } else if (*begin == '-') {
    -        negate = false;
    -        ++begin;
    -    }
    -
    -    int value = parsePosixTime(begin, end);
    -    if (value == INT_MIN)
    -        return value;
    -    return negate ? -value : value;
    -}
    -
    -static inline bool asciiIsLetter(char ch)
    -{
    -    ch |= 0x20; // lowercases if it is a letter, otherwise just corrupts ch
    -    return ch >= 'a' && ch <= 'z';
    -}
    -
    -namespace {
    -
    -struct PosixZone
    -{
    -    enum {
    -        InvalidOffset = INT_MIN,
    -    };
    -
    -    QString name;
    -    int offset;
    -
    -    static PosixZone invalid() { return {QString(), InvalidOffset}; }
    -    static PosixZone parse(const char *&pos, const char *end);
    -
    -    bool hasValidOffset() const noexcept { return offset != InvalidOffset; }
    -};
    -
    -} // unnamed namespace
    -
    -// Returns the zone name, the offset (in seconds) and advances \a begin to
    -// where the parsing ended. Returns a zone of INT_MIN in case an offset
    -// couldn't be read.
    -PosixZone PosixZone::parse(const char *&pos, const char *end)
    -{
    -    static const char offsetChars[] = "0123456789:";
    -
    -    const char *nameBegin = pos;
    -    const char *nameEnd;
    -    Q_ASSERT(pos < end);
    -
    -    if (*pos == '<') {
    -        nameBegin = pos + 1;    // skip the '<'
    -        nameEnd = nameBegin;
    -        while (nameEnd < end && *nameEnd != '>') {
    -            // POSIX says only alphanumeric, but we allow anything
    -            ++nameEnd;
    -        }
    -        pos = nameEnd + 1;      // skip the '>'
    -    } else {
    -        nameBegin = pos;
    -        nameEnd = nameBegin;
    -        while (nameEnd < end && asciiIsLetter(*nameEnd))
    -            ++nameEnd;
    -        pos = nameEnd;
    -    }
    -    if (nameEnd - nameBegin < 3)
    -        return invalid();  // name must be at least 3 characters long
    -
    -    // zone offset, form [+-]hh:mm:ss
    -    const char *zoneBegin = pos;
    -    const char *zoneEnd = pos;
    -    if (zoneEnd < end && (zoneEnd[0] == '+' || zoneEnd[0] == '-'))
    -        ++zoneEnd;
    -    while (zoneEnd < end) {
    -        if (strchr(offsetChars, char(*zoneEnd)) == NULL)
    -            break;
    -        ++zoneEnd;
    -    }
    -
    -    QString name = QString::fromUtf8(nameBegin, nameEnd - nameBegin);
    -    const int offset = zoneEnd > zoneBegin ? parsePosixOffset(zoneBegin, zoneEnd) : InvalidOffset;
    -    pos = zoneEnd;
    -    // UTC+hh:mm:ss or GMT+hh:mm:ss should be read as offsets from UTC, not as a
    -    // POSIX rule naming a zone as UTC or GMT and specifying a non-zero offset.
    -    if (offset != 0 && (name == QLatin1String("UTC") || name == QLatin1String("GMT")))
    -        return invalid();
    -    return {std::move(name), offset};
    -}
    -
    -static QVector calculatePosixTransitions(const QByteArray &posixRule,
    -                                                                 int startYear, int endYear,
    -                                                                 qint64 lastTranMSecs)
    -{
    -    QVector result;
    -
    -    // POSIX Format is like "TZ=CST6CDT,M3.2.0/2:00:00,M11.1.0/2:00:00"
    -    // i.e. "std offset dst [offset],start[/time],end[/time]"
    -    // See the section about TZ at
    -    // http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html
    -    QList parts = posixRule.split(',');
    -
    -    PosixZone stdZone, dstZone = PosixZone::invalid();
    -    {
    -        const QByteArray &zoneinfo = parts.at(0);
    -        const char *begin = zoneinfo.constBegin();
    -
    -        stdZone = PosixZone::parse(begin, zoneinfo.constEnd());
    -        if (!stdZone.hasValidOffset()) {
    -            stdZone.offset = 0;     // reset to UTC if we failed to parse
    -        } else if (begin < zoneinfo.constEnd()) {
    -            dstZone = PosixZone::parse(begin, zoneinfo.constEnd());
    -            if (!dstZone.hasValidOffset()) {
    -                // if the dst offset isn't provided, it is 1 hour ahead of the standard offset
    -                dstZone.offset = stdZone.offset + (60 * 60);
    -            }
    -        }
    -    }
    -
    -    // If only the name part then no transitions
    -    if (parts.count() == 1) {
    -        QTimeZonePrivate::Data data;
    -        data.atMSecsSinceEpoch = lastTranMSecs;
    -        data.offsetFromUtc = stdZone.offset;
    -        data.standardTimeOffset = stdZone.offset;
    -        data.daylightTimeOffset = 0;
    -        data.abbreviation = stdZone.name;
    -        result << data;
    -        return result;
    -    }
    -
    -
    -    // Get the std to dst transtion details
    -    QList dstParts = parts.at(1).split('/');
    -    QByteArray dstDateRule = dstParts.at(0);
    -    QTime dstTime;
    -    if (dstParts.count() > 1)
    -        dstTime = parsePosixTransitionTime(dstParts.at(1));
    -    else
    -        dstTime = QTime(2, 0, 0);
    -
    -    // Get the dst to std transtion details
    -    QList stdParts = parts.at(2).split('/');
    -    QByteArray stdDateRule = stdParts.at(0);
    -    QTime stdTime;
    -    if (stdParts.count() > 1)
    -        stdTime = parsePosixTransitionTime(stdParts.at(1));
    -    else
    -        stdTime = QTime(2, 0, 0);
    -
    -    // Limit year to the range QDateTime can represent:
    -    const int minYear = int(QDateTimePrivate::YearRange::First);
    -    const int maxYear = int(QDateTimePrivate::YearRange::Last);
    -    startYear = qBound(minYear, startYear, maxYear);
    -    endYear = qBound(minYear, endYear, maxYear);
    -    Q_ASSERT(startYear <= endYear);
    -
    -    for (int year = startYear; year <= endYear; ++year) {
    -        QTimeZonePrivate::Data dstData;
    -        QDateTime dst(calculatePosixDate(dstDateRule, year), dstTime, Qt::UTC);
    -        dstData.atMSecsSinceEpoch = dst.toMSecsSinceEpoch() - (stdZone.offset * 1000);
    -        dstData.offsetFromUtc = dstZone.offset;
    -        dstData.standardTimeOffset = stdZone.offset;
    -        dstData.daylightTimeOffset = dstZone.offset - stdZone.offset;
    -        dstData.abbreviation = dstZone.name;
    -        QTimeZonePrivate::Data stdData;
    -        QDateTime std(calculatePosixDate(stdDateRule, year), stdTime, Qt::UTC);
    -        stdData.atMSecsSinceEpoch = std.toMSecsSinceEpoch() - (dstZone.offset * 1000);
    -        stdData.offsetFromUtc = stdZone.offset;
    -        stdData.standardTimeOffset = stdZone.offset;
    -        stdData.daylightTimeOffset = 0;
    -        stdData.abbreviation = stdZone.name;
    -        // Part of maxYear will overflow (likewise for minYear, below):
    -        if (year == maxYear && (dstData.atMSecsSinceEpoch < 0 || stdData.atMSecsSinceEpoch < 0)) {
    -            if (dstData.atMSecsSinceEpoch > 0) {
    -                result << dstData;
    -            } else if (stdData.atMSecsSinceEpoch > 0) {
    -                result << stdData;
    -            }
    -        } else if (year < 1970) { // We ignore DST before the epoch.
    -            if (year > minYear || stdData.atMSecsSinceEpoch != QTimeZonePrivate::invalidMSecs())
    -                result << stdData;
    -        } else if (dst < std) {
    -            result << dstData << stdData;
    -        } else {
    -            result << stdData << dstData;
    -        }
    -    }
    -    return result;
    -}
    -
    -// Create the system default time zone
    -QTzTimeZonePrivate::QTzTimeZonePrivate()
    -{
    -    init(systemTimeZoneId());
    -}
    -
    -// Create a named time zone
    -QTzTimeZonePrivate::QTzTimeZonePrivate(const QByteArray &ianaId)
    -{
    -    init(ianaId);
    -}
    -
    -QTzTimeZonePrivate::~QTzTimeZonePrivate()
    -{
    -}
    -
    -QTzTimeZonePrivate *QTzTimeZonePrivate::clone() const
    -{
    -    return new QTzTimeZonePrivate(*this);
    -}
    -
    -void QTzTimeZonePrivate::init(const QByteArray &ianaId)
    -{
    -    QFile tzif;
    -    if (ianaId.isEmpty()) {
    -        // Open system tz
    -        tzif.setFileName(QStringLiteral("/etc/localtime"));
    -        if (!tzif.open(QIODevice::ReadOnly))
    -            return;
    -    } else {
    -        // Open named tz, try modern path first, if fails try legacy path
    -        tzif.setFileName(QLatin1String("/usr/share/zoneinfo/") + QString::fromLocal8Bit(ianaId));
    -        if (!tzif.open(QIODevice::ReadOnly)) {
    -            tzif.setFileName(QLatin1String("/usr/lib/zoneinfo/") + QString::fromLocal8Bit(ianaId));
    -            if (!tzif.open(QIODevice::ReadOnly)) {
    -                // ianaId may be a POSIX rule, taken from $TZ or /etc/TZ
    -                const QByteArray zoneInfo = ianaId.split(',').at(0);
    -                const char *begin = zoneInfo.constBegin();
    -                if (PosixZone::parse(begin, zoneInfo.constEnd()).hasValidOffset()
    -                    && (begin == zoneInfo.constEnd()
    -                        || PosixZone::parse(begin, zoneInfo.constEnd()).hasValidOffset())) {
    -                    m_id = m_posixRule = ianaId;
    -                }
    -                return;
    -            }
    -        }
    -    }
    -
    -    QDataStream ds(&tzif);
    -
    -    // Parse the old version block of data
    -    bool ok = false;
    -    QTzHeader hdr = parseTzHeader(ds, &ok);
    -    if (!ok || ds.status() != QDataStream::Ok)
    -        return;
    -    QVector tranList = parseTzTransitions(ds, hdr.tzh_timecnt, false);
    -    if (ds.status() != QDataStream::Ok)
    -        return;
    -    QVector typeList = parseTzTypes(ds, hdr.tzh_typecnt);
    -    if (ds.status() != QDataStream::Ok)
    -        return;
    -    QMap abbrevMap = parseTzAbbreviations(ds, hdr.tzh_charcnt, typeList);
    -    if (ds.status() != QDataStream::Ok)
    -        return;
    -    parseTzLeapSeconds(ds, hdr.tzh_leapcnt, false);
    -    if (ds.status() != QDataStream::Ok)
    -        return;
    -    typeList = parseTzIndicators(ds, typeList, hdr.tzh_ttisstdcnt, hdr.tzh_ttisgmtcnt);
    -    if (ds.status() != QDataStream::Ok)
    -        return;
    -
    -    // If version 2 then parse the second block of data
    -    if (hdr.tzh_version == '2' || hdr.tzh_version == '3') {
    -        ok = false;
    -        QTzHeader hdr2 = parseTzHeader(ds, &ok);
    -        if (!ok || ds.status() != QDataStream::Ok)
    -            return;
    -        tranList = parseTzTransitions(ds, hdr2.tzh_timecnt, true);
    -        if (ds.status() != QDataStream::Ok)
    -            return;
    -        typeList = parseTzTypes(ds, hdr2.tzh_typecnt);
    -        if (ds.status() != QDataStream::Ok)
    -            return;
    -        abbrevMap = parseTzAbbreviations(ds, hdr2.tzh_charcnt, typeList);
    -        if (ds.status() != QDataStream::Ok)
    -            return;
    -        parseTzLeapSeconds(ds, hdr2.tzh_leapcnt, true);
    -        if (ds.status() != QDataStream::Ok)
    -            return;
    -        typeList = parseTzIndicators(ds, typeList, hdr2.tzh_ttisstdcnt, hdr2.tzh_ttisgmtcnt);
    -        if (ds.status() != QDataStream::Ok)
    -            return;
    -        m_posixRule = parseTzPosixRule(ds);
    -        if (ds.status() != QDataStream::Ok)
    -            return;
    -    }
    -
    -    // Translate the TZ file into internal format
    -
    -    // Translate the array index based tz_abbrind into list index
    -    const int size = abbrevMap.size();
    -    m_abbreviations.clear();
    -    m_abbreviations.reserve(size);
    -    QVector abbrindList;
    -    abbrindList.reserve(size);
    -    for (auto it = abbrevMap.cbegin(), end = abbrevMap.cend(); it != end; ++it) {
    -        m_abbreviations.append(it.value());
    -        abbrindList.append(it.key());
    -    }
    -    for (int i = 0; i < typeList.size(); ++i)
    -        typeList[i].tz_abbrind = abbrindList.indexOf(typeList.at(i).tz_abbrind);
    -
    -    // Offsets are stored as total offset, want to know separate UTC and DST offsets
    -    // so find the first non-dst transition to use as base UTC Offset
    -    int utcOffset = 0;
    -    for (const QTzTransition &tran : qAsConst(tranList)) {
    -        if (!typeList.at(tran.tz_typeind).tz_isdst) {
    -            utcOffset = typeList.at(tran.tz_typeind).tz_gmtoff;
    -            break;
    -        }
    -    }
    -
    -    // Now for each transition time calculate and store our rule:
    -    const int tranCount = tranList.count();;
    -    m_tranTimes.reserve(tranCount);
    -    // The DST offset when in effect: usually stable, usually an hour:
    -    int lastDstOff = 3600;
    -    for (int i = 0; i < tranCount; i++) {
    -        const QTzTransition &tz_tran = tranList.at(i);
    -        QTzTransitionTime tran;
    -        QTzTransitionRule rule;
    -        const QTzType tz_type = typeList.at(tz_tran.tz_typeind);
    -
    -        // Calculate the associated Rule
    -        if (!tz_type.tz_isdst) {
    -            utcOffset = tz_type.tz_gmtoff;
    -        } else if (Q_UNLIKELY(tz_type.tz_gmtoff != utcOffset + lastDstOff)) {
    -            /*
    -              This might be a genuine change in DST offset, but could also be
    -              DST starting at the same time as the standard offset changed.  See
    -              if DST's end gives a more plausible utcOffset (i.e. one closer to
    -              the last we saw, or a simple whole hour):
    -            */
    -            // Standard offset inferred from net offset and expected DST offset:
    -            const int inferStd = tz_type.tz_gmtoff - lastDstOff; // != utcOffset
    -            for (int j = i + 1; j < tranCount; j++) {
    -                const QTzType new_type = typeList.at(tranList.at(j).tz_typeind);
    -                if (!new_type.tz_isdst) {
    -                    const int newUtc = new_type.tz_gmtoff;
    -                    if (newUtc == utcOffset) {
    -                        // DST-end can't help us, avoid lots of messy checks.
    -                    // else: See if the end matches the familiar DST offset:
    -                    } else if (newUtc == inferStd) {
    -                        utcOffset = newUtc;
    -                    // else: let either end shift us to one hour as DST offset:
    -                    } else if (tz_type.tz_gmtoff - 3600 == utcOffset) {
    -                        // Start does it
    -                    } else if (tz_type.tz_gmtoff - 3600 == newUtc) {
    -                        utcOffset = newUtc; // End does it
    -                    // else: prefer whichever end gives DST offset closer to
    -                    // last, but consider any offset > 0 "closer" than any <= 0:
    -                    } else if (newUtc < tz_type.tz_gmtoff
    -                               ? (utcOffset >= tz_type.tz_gmtoff
    -                                  || qAbs(newUtc - inferStd) < qAbs(utcOffset - inferStd))
    -                               : (utcOffset >= tz_type.tz_gmtoff
    -                                  && qAbs(newUtc - inferStd) < qAbs(utcOffset - inferStd))) {
    -                        utcOffset = newUtc;
    -                    }
    -                    break;
    -                }
    -            }
    -            lastDstOff = tz_type.tz_gmtoff - utcOffset;
    -        }
    -        rule.stdOffset = utcOffset;
    -        rule.dstOffset = tz_type.tz_gmtoff - utcOffset;
    -        rule.abbreviationIndex = tz_type.tz_abbrind;
    -
    -        // If the rule already exist then use that, otherwise add it
    -        int ruleIndex = m_tranRules.indexOf(rule);
    -        if (ruleIndex == -1) {
    -            m_tranRules.append(rule);
    -            tran.ruleIndex = m_tranRules.size() - 1;
    -        } else {
    -            tran.ruleIndex = ruleIndex;
    -        }
    -
    -        tran.atMSecsSinceEpoch = tz_tran.tz_time * 1000;
    -        m_tranTimes.append(tran);
    -    }
    -    if (m_tranTimes.isEmpty() && m_posixRule.isEmpty())
    -        return; // Invalid after all !
    -
    -    if (ianaId.isEmpty())
    -        m_id = systemTimeZoneId();
    -    else
    -        m_id = ianaId;
    -}
    -
    -QLocale::Country QTzTimeZonePrivate::country() const
    -{
    -    return tzZones->value(m_id).country;
    -}
    -
    -QString QTzTimeZonePrivate::comment() const
    -{
    -    return QString::fromUtf8(tzZones->value(m_id).comment);
    -}
    -
    -QString QTzTimeZonePrivate::displayName(qint64 atMSecsSinceEpoch,
    -                                        QTimeZone::NameType nameType,
    -                                        const QLocale &locale) const
    -{
    -#if QT_CONFIG(icu)
    -    if (!m_icu)
    -        m_icu = new QIcuTimeZonePrivate(m_id);
    -    // TODO small risk may not match if tran times differ due to outdated files
    -    // TODO Some valid TZ names are not valid ICU names, use translation table?
    -    if (m_icu->isValid())
    -        return m_icu->displayName(atMSecsSinceEpoch, nameType, locale);
    -#else
    -    Q_UNUSED(nameType)
    -    Q_UNUSED(locale)
    -#endif
    -    return abbreviation(atMSecsSinceEpoch);
    -}
    -
    -QString QTzTimeZonePrivate::displayName(QTimeZone::TimeType timeType,
    -                                        QTimeZone::NameType nameType,
    -                                        const QLocale &locale) const
    -{
    -#if QT_CONFIG(icu)
    -    if (!m_icu)
    -        m_icu = new QIcuTimeZonePrivate(m_id);
    -    // TODO small risk may not match if tran times differ due to outdated files
    -    // TODO Some valid TZ names are not valid ICU names, use translation table?
    -    if (m_icu->isValid())
    -        return m_icu->displayName(timeType, nameType, locale);
    -#else
    -    Q_UNUSED(timeType)
    -    Q_UNUSED(nameType)
    -    Q_UNUSED(locale)
    -#endif
    -    // If no ICU available then have to use abbreviations instead
    -    // Abbreviations don't have GenericTime
    -    if (timeType == QTimeZone::GenericTime)
    -        timeType = QTimeZone::StandardTime;
    -
    -    // Get current tran, if valid and is what we want, then use it
    -    const qint64 currentMSecs = QDateTime::currentMSecsSinceEpoch();
    -    QTimeZonePrivate::Data tran = data(currentMSecs);
    -    if (tran.atMSecsSinceEpoch != invalidMSecs()
    -        && ((timeType == QTimeZone::DaylightTime && tran.daylightTimeOffset != 0)
    -        || (timeType == QTimeZone::StandardTime && tran.daylightTimeOffset == 0))) {
    -        return tran.abbreviation;
    -    }
    -
    -    // Otherwise get next tran and if valid and is what we want, then use it
    -    tran = nextTransition(currentMSecs);
    -    if (tran.atMSecsSinceEpoch != invalidMSecs()
    -        && ((timeType == QTimeZone::DaylightTime && tran.daylightTimeOffset != 0)
    -        || (timeType == QTimeZone::StandardTime && tran.daylightTimeOffset == 0))) {
    -        return tran.abbreviation;
    -    }
    -
    -    // Otherwise get prev tran and if valid and is what we want, then use it
    -    tran = previousTransition(currentMSecs);
    -    if (tran.atMSecsSinceEpoch != invalidMSecs())
    -        tran = previousTransition(tran.atMSecsSinceEpoch);
    -    if (tran.atMSecsSinceEpoch != invalidMSecs()
    -        && ((timeType == QTimeZone::DaylightTime && tran.daylightTimeOffset != 0)
    -        || (timeType == QTimeZone::StandardTime && tran.daylightTimeOffset == 0))) {
    -        return tran.abbreviation;
    -    }
    -
    -    // Otherwise is strange sequence, so work backwards through trans looking for first match, if any
    -    auto it = std::partition_point(m_tranTimes.cbegin(), m_tranTimes.cend(),
    -                                   [currentMSecs](const QTzTransitionTime &at) {
    -                                       return at.atMSecsSinceEpoch <= currentMSecs;
    -                                   });
    -
    -    while (it != m_tranTimes.cbegin()) {
    -        --it;
    -        tran = dataForTzTransition(*it);
    -        int offset = tran.daylightTimeOffset;
    -        if ((timeType == QTimeZone::DaylightTime) != (offset == 0))
    -            return tran.abbreviation;
    -    }
    -
    -    // Otherwise if no match use current data
    -    return data(currentMSecs).abbreviation;
    -}
    -
    -QString QTzTimeZonePrivate::abbreviation(qint64 atMSecsSinceEpoch) const
    -{
    -    return data(atMSecsSinceEpoch).abbreviation;
    -}
    -
    -int QTzTimeZonePrivate::offsetFromUtc(qint64 atMSecsSinceEpoch) const
    -{
    -    const QTimeZonePrivate::Data tran = data(atMSecsSinceEpoch);
    -    return tran.offsetFromUtc; // == tran.standardTimeOffset + tran.daylightTimeOffset
    -}
    -
    -int QTzTimeZonePrivate::standardTimeOffset(qint64 atMSecsSinceEpoch) const
    -{
    -    return data(atMSecsSinceEpoch).standardTimeOffset;
    -}
    -
    -int QTzTimeZonePrivate::daylightTimeOffset(qint64 atMSecsSinceEpoch) const
    -{
    -    return data(atMSecsSinceEpoch).daylightTimeOffset;
    -}
    -
    -bool QTzTimeZonePrivate::hasDaylightTime() const
    -{
    -    // TODO Perhaps cache as frequently accessed?
    -    for (const QTzTransitionRule &rule : m_tranRules) {
    -        if (rule.dstOffset != 0)
    -            return true;
    -    }
    -    return false;
    -}
    -
    -bool QTzTimeZonePrivate::isDaylightTime(qint64 atMSecsSinceEpoch) const
    -{
    -    return (daylightTimeOffset(atMSecsSinceEpoch) != 0);
    -}
    -
    -QTimeZonePrivate::Data QTzTimeZonePrivate::dataForTzTransition(QTzTransitionTime tran) const
    -{
    -    QTimeZonePrivate::Data data;
    -    data.atMSecsSinceEpoch = tran.atMSecsSinceEpoch;
    -    QTzTransitionRule rule = m_tranRules.at(tran.ruleIndex);
    -    data.standardTimeOffset = rule.stdOffset;
    -    data.daylightTimeOffset = rule.dstOffset;
    -    data.offsetFromUtc = rule.stdOffset + rule.dstOffset;
    -    data.abbreviation = QString::fromUtf8(m_abbreviations.at(rule.abbreviationIndex));
    -    return data;
    -}
    -
    -QVector QTzTimeZonePrivate::getPosixTransitions(qint64 msNear) const
    -{
    -    const int year = QDateTime::fromMSecsSinceEpoch(msNear, Qt::UTC).date().year();
    -    // The Data::atMSecsSinceEpoch of the single entry if zone is constant:
    -    qint64 atTime = m_tranTimes.isEmpty() ? msNear : m_tranTimes.last().atMSecsSinceEpoch;
    -    return calculatePosixTransitions(m_posixRule, year - 1, year + 1, atTime);
    -}
    -
    -QTimeZonePrivate::Data QTzTimeZonePrivate::data(qint64 forMSecsSinceEpoch) const
    -{
    -    // If the required time is after the last transition (or there were none)
    -    // and we have a POSIX rule, then use it:
    -    if (!m_posixRule.isEmpty()
    -        && (m_tranTimes.isEmpty() || m_tranTimes.last().atMSecsSinceEpoch < forMSecsSinceEpoch)) {
    -        QVector posixTrans = getPosixTransitions(forMSecsSinceEpoch);
    -        auto it = std::partition_point(posixTrans.cbegin(), posixTrans.cend(),
    -                                       [forMSecsSinceEpoch] (const QTimeZonePrivate::Data &at) {
    -                                           return at.atMSecsSinceEpoch <= forMSecsSinceEpoch;
    -                                       });
    -        // Use most recent, if any in the past; or the first if we have no other rules:
    -        if (it > posixTrans.cbegin() || (m_tranTimes.isEmpty() && it < posixTrans.cend())) {
    -            QTimeZonePrivate::Data data = *(it > posixTrans.cbegin() ? it - 1 : it);
    -            data.atMSecsSinceEpoch = forMSecsSinceEpoch;
    -            return data;
    -        }
    -    }
    -    if (m_tranTimes.isEmpty()) // Only possible if !isValid()
    -        return invalidData();
    -
    -    // Otherwise, use the rule for the most recent or first transition:
    -    auto last = std::partition_point(m_tranTimes.cbegin(), m_tranTimes.cend(),
    -                                     [forMSecsSinceEpoch] (const QTzTransitionTime &at) {
    -                                         return at.atMSecsSinceEpoch <= forMSecsSinceEpoch;
    -                                     });
    -    if (last > m_tranTimes.cbegin())
    -        --last;
    -    Data data = dataForTzTransition(*last);
    -    data.atMSecsSinceEpoch = forMSecsSinceEpoch;
    -    return data;
    -}
    -
    -bool QTzTimeZonePrivate::hasTransitions() const
    -{
    -    return true;
    -}
    -
    -QTimeZonePrivate::Data QTzTimeZonePrivate::nextTransition(qint64 afterMSecsSinceEpoch) const
    -{
    -    // If the required time is after the last transition (or there were none)
    -    // and we have a POSIX rule, then use it:
    -    if (!m_posixRule.isEmpty()
    -        && (m_tranTimes.isEmpty() || m_tranTimes.last().atMSecsSinceEpoch < afterMSecsSinceEpoch)) {
    -        QVector posixTrans = getPosixTransitions(afterMSecsSinceEpoch);
    -        auto it = std::partition_point(posixTrans.cbegin(), posixTrans.cend(),
    -                                       [afterMSecsSinceEpoch] (const QTimeZonePrivate::Data &at) {
    -                                           return at.atMSecsSinceEpoch <= afterMSecsSinceEpoch;
    -                                       });
    -
    -        return it == posixTrans.cend() ? invalidData() : *it;
    -    }
    -
    -    // Otherwise, if we can find a valid tran, use its rule:
    -    auto last = std::partition_point(m_tranTimes.cbegin(), m_tranTimes.cend(),
    -                                     [afterMSecsSinceEpoch] (const QTzTransitionTime &at) {
    -                                         return at.atMSecsSinceEpoch <= afterMSecsSinceEpoch;
    -                                     });
    -    return last != m_tranTimes.cend() ? dataForTzTransition(*last) : invalidData();
    -}
    -
    -QTimeZonePrivate::Data QTzTimeZonePrivate::previousTransition(qint64 beforeMSecsSinceEpoch) const
    -{
    -    // If the required time is after the last transition (or there were none)
    -    // and we have a POSIX rule, then use it:
    -    if (!m_posixRule.isEmpty()
    -        && (m_tranTimes.isEmpty() || m_tranTimes.last().atMSecsSinceEpoch < beforeMSecsSinceEpoch)) {
    -        QVector posixTrans = getPosixTransitions(beforeMSecsSinceEpoch);
    -        auto it = std::partition_point(posixTrans.cbegin(), posixTrans.cend(),
    -                                       [beforeMSecsSinceEpoch] (const QTimeZonePrivate::Data &at) {
    -                                           return at.atMSecsSinceEpoch < beforeMSecsSinceEpoch;
    -                                       });
    -        if (it > posixTrans.cbegin())
    -            return *--it;
    -        // It fell between the last transition (if any) and the first of the POSIX rule:
    -        return m_tranTimes.isEmpty() ? invalidData() : dataForTzTransition(m_tranTimes.last());
    -    }
    -
    -    // Otherwise if we can find a valid tran then use its rule
    -    auto last = std::partition_point(m_tranTimes.cbegin(), m_tranTimes.cend(),
    -                                     [beforeMSecsSinceEpoch] (const QTzTransitionTime &at) {
    -                                         return at.atMSecsSinceEpoch < beforeMSecsSinceEpoch;
    -                                     });
    -    return last > m_tranTimes.cbegin() ? dataForTzTransition(*--last) : invalidData();
    -}
    -
    -// TODO Could cache the value and monitor the required files for any changes
    -QByteArray QTzTimeZonePrivate::systemTimeZoneId() const
    -{
    -    // Check TZ env var first, if not populated try find it
    -    QByteArray ianaId = qgetenv("TZ");
    -    if (!ianaId.isEmpty() && ianaId.at(0) == ':')
    -        ianaId = ianaId.mid(1);
    -
    -    // The TZ value can be ":/etc/localtime" which libc considers
    -    // to be a "default timezone", in which case it will be read
    -    // by one of the blocks below, so unset it here so it is not
    -    // considered as a valid/found ianaId
    -    if (ianaId == "/etc/localtime")
    -        ianaId.clear();
    -
    -    // On most distros /etc/localtime is a symlink to a real file so extract name from the path
    -    if (ianaId.isEmpty()) {
    -        const QString path = QFile::symLinkTarget(QStringLiteral("/etc/localtime"));
    -        if (!path.isEmpty()) {
    -            // /etc/localtime is a symlink to the current TZ file, so extract from path
    -            int index = path.indexOf(QLatin1String("/zoneinfo/"));
    -            if (index != -1)
    -                ianaId = path.mid(index + 10).toUtf8();
    -        }
    -    }
    -
    -    // On Debian Etch up to Jessie, /etc/localtime is a regular file while the actual name is in /etc/timezone
    -    if (ianaId.isEmpty()) {
    -        QFile tzif(QStringLiteral("/etc/timezone"));
    -        if (tzif.open(QIODevice::ReadOnly)) {
    -            // TODO QTextStream inefficient, replace later
    -            QTextStream ts(&tzif);
    -            if (!ts.atEnd())
    -                ianaId = ts.readLine().toUtf8();
    -        }
    -    }
    -
    -    // On some Red Hat distros /etc/localtime is real file with name held in /etc/sysconfig/clock
    -    // in a line like ZONE="Europe/Oslo" or TIMEZONE="Europe/Oslo"
    -    if (ianaId.isEmpty()) {
    -        QFile tzif(QStringLiteral("/etc/sysconfig/clock"));
    -        if (tzif.open(QIODevice::ReadOnly)) {
    -            // TODO QTextStream inefficient, replace later
    -            QTextStream ts(&tzif);
    -            QString line;
    -            while (ianaId.isEmpty() && !ts.atEnd() && ts.status() == QTextStream::Ok) {
    -                line = ts.readLine();
    -                if (line.startsWith(QLatin1String("ZONE="))) {
    -                    ianaId = line.mid(6, line.size() - 7).toUtf8();
    -                } else if (line.startsWith(QLatin1String("TIMEZONE="))) {
    -                    ianaId = line.mid(10, line.size() - 11).toUtf8();
    -                }
    -            }
    -        }
    -    }
    -
    -    // Some systems (e.g. uClibc) have a default value for $TZ in /etc/TZ:
    -    if (ianaId.isEmpty()) {
    -        QFile zone(QStringLiteral("/etc/TZ"));
    -        if (zone.open(QIODevice::ReadOnly))
    -            ianaId = zone.readAll().trimmed();
    -    }
    -
    -    // Give up for now and return UTC
    -    if (ianaId.isEmpty())
    -        ianaId = utcQByteArray();
    -
    -    return ianaId;
    -}
    -
    -bool QTzTimeZonePrivate::isTimeZoneIdAvailable(const QByteArray &ianaId) const
    -{
    -    return tzZones->contains(ianaId);
    -}
    -
    -QList QTzTimeZonePrivate::availableTimeZoneIds() const
    -{
    -    QList result = tzZones->keys();
    -    std::sort(result.begin(), result.end());
    -    return result;
    -}
    -
    -QList QTzTimeZonePrivate::availableTimeZoneIds(QLocale::Country country) const
    -{
    -    // TODO AnyCountry
    -    QList result;
    -    for (auto it = tzZones->cbegin(), end = tzZones->cend(); it != end; ++it) {
    -        if (it.value().country == country)
    -            result << it.key();
    -    }
    -    std::sort(result.begin(), result.end());
    -    return result;
    -}
    -
    -QT_END_NAMESPACE
    diff --git a/src/corelib/tools/qtimezoneprivate_win.cpp b/src/corelib/tools/qtimezoneprivate_win.cpp
    deleted file mode 100644
    index 1bf2366748..0000000000
    --- a/src/corelib/tools/qtimezoneprivate_win.cpp
    +++ /dev/null
    @@ -1,927 +0,0 @@
    -/****************************************************************************
    -**
    -** Copyright (C) 2013 John Layt 
    -** Contact: https://www.qt.io/licensing/
    -**
    -** This file is part of the QtCore module of the Qt Toolkit.
    -**
    -** $QT_BEGIN_LICENSE:LGPL$
    -** Commercial License Usage
    -** Licensees holding valid commercial Qt licenses may use this file in
    -** accordance with the commercial license agreement provided with the
    -** Software or, alternatively, in accordance with the terms contained in
    -** a written agreement between you and The Qt Company. For licensing terms
    -** and conditions see https://www.qt.io/terms-conditions. For further
    -** information use the contact form at https://www.qt.io/contact-us.
    -**
    -** GNU Lesser General Public License Usage
    -** Alternatively, this file may be used under the terms of the GNU Lesser
    -** General Public License version 3 as published by the Free Software
    -** Foundation and appearing in the file LICENSE.LGPL3 included in the
    -** packaging of this file. Please review the following information to
    -** ensure the GNU Lesser General Public License version 3 requirements
    -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
    -**
    -** GNU General Public License Usage
    -** Alternatively, this file may be used under the terms of the GNU
    -** General Public License version 2.0 or (at your option) the GNU General
    -** Public license version 3 or any later version approved by the KDE Free
    -** Qt Foundation. The licenses are as published by the Free Software
    -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
    -** included in the packaging of this file. Please review the following
    -** information to ensure the GNU General Public License requirements will
    -** be met: https://www.gnu.org/licenses/gpl-2.0.html and
    -** https://www.gnu.org/licenses/gpl-3.0.html.
    -**
    -** $QT_END_LICENSE$
    -**
    -****************************************************************************/
    -
    -#include "qtimezone.h"
    -#include "qtimezoneprivate_p.h"
    -
    -#include "qdatetime.h"
    -
    -#include "qdebug.h"
    -
    -#include 
    -
    -QT_BEGIN_NAMESPACE
    -
    -#ifndef Q_OS_WINRT
    -// The registry-based timezone backend is not available on WinRT, which falls back to equivalent APIs.
    -#define QT_USE_REGISTRY_TIMEZONE 1
    -#endif
    -
    -/*
    -    Private
    -
    -    Windows system implementation
    -*/
    -
    -#define MAX_KEY_LENGTH 255
    -#define FILETIME_UNIX_EPOCH Q_UINT64_C(116444736000000000)
    -
    -// MSDN home page for Time support
    -// http://msdn.microsoft.com/en-us/library/windows/desktop/ms724962%28v=vs.85%29.aspx
    -
    -// For Windows XP and later refer to MSDN docs on TIME_ZONE_INFORMATION structure
    -// http://msdn.microsoft.com/en-gb/library/windows/desktop/ms725481%28v=vs.85%29.aspx
    -
    -// Vista introduced support for historic data, see MSDN docs on DYNAMIC_TIME_ZONE_INFORMATION
    -// http://msdn.microsoft.com/en-gb/library/windows/desktop/ms724253%28v=vs.85%29.aspx
    -#ifdef QT_USE_REGISTRY_TIMEZONE
    -static const char tzRegPath[] = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones";
    -static const char currTzRegPath[] = "SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation";
    -#endif
    -
    -enum {
    -    MIN_YEAR = -292275056,
    -    MAX_YEAR = 292278994,
    -    MSECS_PER_DAY = 86400000,
    -    TIME_T_MAX = 2145916799,  // int maximum 2037-12-31T23:59:59 UTC
    -    JULIAN_DAY_FOR_EPOCH = 2440588 // result of julianDayFromDate(1970, 1, 1)
    -};
    -
    -// Copied from MSDN, see above for link
    -typedef struct _REG_TZI_FORMAT
    -{
    -    LONG Bias;
    -    LONG StandardBias;
    -    LONG DaylightBias;
    -    SYSTEMTIME StandardDate;
    -    SYSTEMTIME DaylightDate;
    -} REG_TZI_FORMAT;
    -
    -namespace {
    -
    -// Fast and reliable conversion from msecs to date for all values
    -// Adapted from QDateTime msecsToDate
    -QDate msecsToDate(qint64 msecs)
    -{
    -    qint64 jd = JULIAN_DAY_FOR_EPOCH;
    -
    -    if (qAbs(msecs) >= MSECS_PER_DAY) {
    -        jd += (msecs / MSECS_PER_DAY);
    -        msecs %= MSECS_PER_DAY;
    -    }
    -
    -    if (msecs < 0) {
    -        qint64 ds = MSECS_PER_DAY - msecs - 1;
    -        jd -= ds / MSECS_PER_DAY;
    -    }
    -
    -    return QDate::fromJulianDay(jd);
    -}
    -
    -bool equalSystemtime(const SYSTEMTIME &t1, const SYSTEMTIME &t2)
    -{
    -    return (t1.wYear == t2.wYear
    -            && t1.wMonth == t2.wMonth
    -            && t1.wDay == t2.wDay
    -            && t1.wDayOfWeek == t2.wDayOfWeek
    -            && t1.wHour == t2.wHour
    -            && t1.wMinute == t2.wMinute
    -            && t1.wSecond == t2.wSecond
    -            && t1.wMilliseconds == t2.wMilliseconds);
    -}
    -
    -bool equalTzi(const TIME_ZONE_INFORMATION &tzi1, const TIME_ZONE_INFORMATION &tzi2)
    -{
    -    return(tzi1.Bias == tzi2.Bias
    -           && tzi1.StandardBias == tzi2.StandardBias
    -           && equalSystemtime(tzi1.StandardDate, tzi2.StandardDate)
    -           && wcscmp(tzi1.StandardName, tzi2.StandardName) == 0
    -           && tzi1.DaylightBias == tzi2.DaylightBias
    -           && equalSystemtime(tzi1.DaylightDate, tzi2.DaylightDate)
    -           && wcscmp(tzi1.DaylightName, tzi2.DaylightName) == 0);
    -}
    -
    -#ifdef QT_USE_REGISTRY_TIMEZONE
    -bool openRegistryKey(const QString &keyPath, HKEY *key)
    -{
    -    return RegOpenKeyEx(HKEY_LOCAL_MACHINE, reinterpret_cast(keyPath.utf16()),
    -                        0, KEY_READ, key) == ERROR_SUCCESS;
    -}
    -
    -QString readRegistryString(const HKEY &key, const wchar_t *value)
    -{
    -    wchar_t buffer[MAX_PATH] = {0};
    -    DWORD size = sizeof(wchar_t) * MAX_PATH;
    -    RegQueryValueEx(key, value, nullptr, nullptr, reinterpret_cast(buffer), &size);
    -    return QString::fromWCharArray(buffer);
    -}
    -
    -int readRegistryValue(const HKEY &key, const wchar_t *value)
    -{
    -    DWORD buffer;
    -    DWORD size = sizeof(buffer);
    -    RegQueryValueEx(key, value, nullptr, nullptr, reinterpret_cast(&buffer), &size);
    -    return buffer;
    -}
    -
    -QWinTimeZonePrivate::QWinTransitionRule readRegistryRule(const HKEY &key,
    -                                                         const wchar_t *value, bool *ok)
    -{
    -    *ok = false;
    -    QWinTimeZonePrivate::QWinTransitionRule rule;
    -    REG_TZI_FORMAT tzi;
    -    DWORD tziSize = sizeof(tzi);
    -    if (RegQueryValueEx(key, value, nullptr, nullptr, reinterpret_cast(&tzi), &tziSize)
    -        == ERROR_SUCCESS) {
    -        rule.startYear = 0;
    -        rule.standardTimeBias = tzi.Bias + tzi.StandardBias;
    -        rule.daylightTimeBias = tzi.Bias + tzi.DaylightBias - rule.standardTimeBias;
    -        rule.standardTimeRule = tzi.StandardDate;
    -        rule.daylightTimeRule = tzi.DaylightDate;
    -        *ok = true;
    -    }
    -    return rule;
    -}
    -
    -TIME_ZONE_INFORMATION getRegistryTzi(const QByteArray &windowsId, bool *ok)
    -{
    -    *ok = false;
    -    TIME_ZONE_INFORMATION tzi;
    -    REG_TZI_FORMAT regTzi;
    -    DWORD regTziSize = sizeof(regTzi);
    -    HKEY key = NULL;
    -    const QString tziKeyPath = QString::fromUtf8(tzRegPath) + QLatin1Char('\\')
    -                               + QString::fromUtf8(windowsId);
    -
    -    if (openRegistryKey(tziKeyPath, &key)) {
    -
    -        DWORD size = sizeof(tzi.DaylightName);
    -        RegQueryValueEx(key, L"Dlt", nullptr, nullptr, reinterpret_cast(tzi.DaylightName), &size);
    -
    -        size = sizeof(tzi.StandardName);
    -        RegQueryValueEx(key, L"Std", nullptr, nullptr, reinterpret_cast(tzi.StandardName), &size);
    -
    -        if (RegQueryValueEx(key, L"TZI", nullptr, nullptr, reinterpret_cast(®Tzi), ®TziSize)
    -            == ERROR_SUCCESS) {
    -            tzi.Bias = regTzi.Bias;
    -            tzi.StandardBias = regTzi.StandardBias;
    -            tzi.DaylightBias = regTzi.DaylightBias;
    -            tzi.StandardDate = regTzi.StandardDate;
    -            tzi.DaylightDate = regTzi.DaylightDate;
    -            *ok = true;
    -        }
    -
    -        RegCloseKey(key);
    -    }
    -
    -    return tzi;
    -}
    -#else // QT_USE_REGISTRY_TIMEZONE
    -struct QWinDynamicTimeZone
    -{
    -    QString standardName;
    -    QString daylightName;
    -    QString timezoneName;
    -    qint32 bias;
    -    bool daylightTime;
    -};
    -
    -typedef QHash QWinRTTimeZoneHash;
    -
    -Q_GLOBAL_STATIC(QWinRTTimeZoneHash, gTimeZones)
    -
    -void enumerateTimeZones()
    -{
    -    DYNAMIC_TIME_ZONE_INFORMATION dtzInfo;
    -    quint32 index = 0;
    -    QString prevTimeZoneKeyName;
    -    while (SUCCEEDED(EnumDynamicTimeZoneInformation(index++, &dtzInfo))) {
    -        QWinDynamicTimeZone item;
    -        item.timezoneName = QString::fromWCharArray(dtzInfo.TimeZoneKeyName);
    -        // As soon as key name repeats, break. Some systems continue to always
    -        // return the last item independent of index being out of range
    -        if (item.timezoneName == prevTimeZoneKeyName)
    -            break;
    -        item.standardName = QString::fromWCharArray(dtzInfo.StandardName);
    -        item.daylightName = QString::fromWCharArray(dtzInfo.DaylightName);
    -        item.daylightTime = !dtzInfo.DynamicDaylightTimeDisabled;
    -        item.bias = dtzInfo.Bias;
    -        gTimeZones->insert(item.timezoneName.toUtf8(), item);
    -        prevTimeZoneKeyName = item.timezoneName;
    -    }
    -}
    -
    -DYNAMIC_TIME_ZONE_INFORMATION dynamicInfoForId(const QByteArray &windowsId)
    -{
    -    DYNAMIC_TIME_ZONE_INFORMATION dtzInfo;
    -    quint32 index = 0;
    -    QString prevTimeZoneKeyName;
    -    while (SUCCEEDED(EnumDynamicTimeZoneInformation(index++, &dtzInfo))) {
    -        const QString timeZoneName = QString::fromWCharArray(dtzInfo.TimeZoneKeyName);
    -        if (timeZoneName == QLatin1String(windowsId))
    -            break;
    -        if (timeZoneName == prevTimeZoneKeyName)
    -            break;
    -        prevTimeZoneKeyName = timeZoneName;
    -    }
    -    return dtzInfo;
    -}
    -
    -QWinTimeZonePrivate::QWinTransitionRule
    -readDynamicRule(DYNAMIC_TIME_ZONE_INFORMATION &dtzi, int year, bool *ok)
    -{
    -    TIME_ZONE_INFORMATION tzi;
    -    QWinTimeZonePrivate::QWinTransitionRule rule;
    -    *ok = GetTimeZoneInformationForYear(year, &dtzi, &tzi);
    -    if (*ok) {
    -        rule.startYear = 0;
    -        rule.standardTimeBias = tzi.Bias + tzi.StandardBias;
    -        rule.daylightTimeBias = tzi.Bias + tzi.DaylightBias - rule.standardTimeBias;
    -        rule.standardTimeRule = tzi.StandardDate;
    -        rule.daylightTimeRule = tzi.DaylightDate;
    -    }
    -    return rule;
    -}
    -#endif // QT_USE_REGISTRY_TIMEZONE
    -
    -bool isSameRule(const QWinTimeZonePrivate::QWinTransitionRule &last,
    -                       const QWinTimeZonePrivate::QWinTransitionRule &rule)
    -{
    -    // In particular, when this is true and either wYear is 0, so is the other;
    -    // so if one rule is recurrent and they're equal, so is the other.  If
    -    // either rule *isn't* recurrent, it has non-0 wYear which shall be
    -    // different from the other's.  Note that we don't compare .startYear, since
    -    // that will always be different.
    -    return equalSystemtime(last.standardTimeRule, rule.standardTimeRule)
    -        && equalSystemtime(last.daylightTimeRule, rule.daylightTimeRule)
    -        && last.standardTimeBias == rule.standardTimeBias
    -        && last.daylightTimeBias == rule.daylightTimeBias;
    -}
    -
    -QList availableWindowsIds()
    -{
    -#ifdef QT_USE_REGISTRY_TIMEZONE
    -    // TODO Consider caching results in a global static, very unlikely to change.
    -    QList list;
    -    HKEY key = NULL;
    -    if (openRegistryKey(QString::fromUtf8(tzRegPath), &key)) {
    -        DWORD idCount = 0;
    -        if (RegQueryInfoKey(key, 0, 0, 0, &idCount, 0, 0, 0, 0, 0, 0, 0) == ERROR_SUCCESS
    -            && idCount > 0) {
    -            for (DWORD i = 0; i < idCount; ++i) {
    -                DWORD maxLen = MAX_KEY_LENGTH;
    -                TCHAR buffer[MAX_KEY_LENGTH];
    -                if (RegEnumKeyEx(key, i, buffer, &maxLen, 0, 0, 0, 0) == ERROR_SUCCESS)
    -                    list.append(QString::fromWCharArray(buffer).toUtf8());
    -            }
    -        }
    -        RegCloseKey(key);
    -    }
    -    return list;
    -#else // QT_USE_REGISTRY_TIMEZONE
    -    if (gTimeZones->isEmpty())
    -        enumerateTimeZones();
    -    return gTimeZones->keys();
    -#endif // QT_USE_REGISTRY_TIMEZONE
    -}
    -
    -QByteArray windowsSystemZoneId()
    -{
    -#ifdef QT_USE_REGISTRY_TIMEZONE
    -    // On Vista and later is held in the value TimeZoneKeyName in key currTzRegPath
    -    QString id;
    -    HKEY key = NULL;
    -    QString tziKeyPath = QString::fromUtf8(currTzRegPath);
    -    if (openRegistryKey(tziKeyPath, &key)) {
    -        id = readRegistryString(key, L"TimeZoneKeyName");
    -        RegCloseKey(key);
    -        if (!id.isEmpty())
    -            return std::move(id).toUtf8();
    -    }
    -
    -    // On XP we have to iterate over the zones until we find a match on
    -    // names/offsets with the current data
    -    TIME_ZONE_INFORMATION sysTzi;
    -    GetTimeZoneInformation(&sysTzi);
    -    bool ok = false;
    -    const auto winIds = availableWindowsIds();
    -    for (const QByteArray &winId : winIds) {
    -        if (equalTzi(getRegistryTzi(winId, &ok), sysTzi))
    -            return winId;
    -    }
    -#else // QT_USE_REGISTRY_TIMEZONE
    -    DYNAMIC_TIME_ZONE_INFORMATION dtzi;
    -    if (SUCCEEDED(GetDynamicTimeZoneInformation(&dtzi)))
    -        return QString::fromWCharArray(dtzi.TimeZoneKeyName).toLocal8Bit();
    -#endif // QT_USE_REGISTRY_TIMEZONE
    -
    -    // If we can't determine the current ID use UTC
    -    return QTimeZonePrivate::utcQByteArray();
    -}
    -
    -QDate calculateTransitionLocalDate(const SYSTEMTIME &rule, int year)
    -{
    -    // If month is 0 then there is no date
    -    if (rule.wMonth == 0)
    -        return QDate();
    -
    -    // Interpret SYSTEMTIME according to the slightly quirky rules in:
    -    // https://msdn.microsoft.com/en-us/library/windows/desktop/ms725481(v=vs.85).aspx
    -
    -    // If the year is set, the rule gives an absolute date:
    -    if (rule.wYear)
    -        return QDate(rule.wYear, rule.wMonth, rule.wDay);
    -
    -    // Otherwise, the rule date is annual and relative:
    -    const int dayOfWeek = rule.wDayOfWeek == 0 ? 7 : rule.wDayOfWeek;
    -    QDate date(year, rule.wMonth, 1);
    -    // How many days before was last dayOfWeek before target month ?
    -    int adjust = dayOfWeek - date.dayOfWeek(); // -6 <= adjust < 7
    -    if (adjust >= 0) // Ensure -7 <= adjust < 0:
    -        adjust -= 7;
    -    // Normally, wDay is day-within-month; but here it is 1 for the first
    -    // of the given dayOfWeek in the month, through 4 for the fourth or ...
    -    adjust += (rule.wDay < 1 ? 1 : rule.wDay > 4 ? 5 : rule.wDay) * 7;
    -    date = date.addDays(adjust);
    -    // ... 5 for the last; so back up by weeks to get within the month:
    -    if (date.month() != rule.wMonth) {
    -        Q_ASSERT(rule.wDay > 4);
    -        // (Note that, with adjust < 0, date <= 28th of our target month
    -        // is guaranteed when wDay <= 4, or after our first -7 here.)
    -        date = date.addDays(-7);
    -        Q_ASSERT(date.month() == rule.wMonth);
    -    }
    -    return date;
    -}
    -
    -// Converts a date/time value into msecs
    -inline qint64 timeToMSecs(const QDate &date, const QTime &time)
    -{
    -    return ((date.toJulianDay() - JULIAN_DAY_FOR_EPOCH) * MSECS_PER_DAY)
    -           + time.msecsSinceStartOfDay();
    -}
    -
    -qint64 calculateTransitionForYear(const SYSTEMTIME &rule, int year, int bias)
    -{
    -    // TODO Consider caching the calculated values - i.e. replace SYSTEMTIME in
    -    // WinTransitionRule; do this in init() once and store the results.
    -    const QDate date = calculateTransitionLocalDate(rule, year);
    -    const QTime time = QTime(rule.wHour, rule.wMinute, rule.wSecond);
    -    if (date.isValid() && time.isValid())
    -        return timeToMSecs(date, time) + bias * 60000;
    -    return QTimeZonePrivate::invalidMSecs();
    -}
    -
    -struct TransitionTimePair
    -{
    -    // Transition times after the epoch, in ms:
    -    qint64 std, dst;
    -    // If either is invalidMSecs(), which shall then be < the other, there is no
    -    // DST and the other describes a change in actual standard offset.
    -
    -    TransitionTimePair(const QWinTimeZonePrivate::QWinTransitionRule &rule,
    -                       int year, int oldYearOffset)
    -        // The local time in Daylight Time of the switch to Standard Time
    -        : std(calculateTransitionForYear(rule.standardTimeRule, year,
    -                                         rule.standardTimeBias + rule.daylightTimeBias)),
    -          // The local time in Standard Time of the switch to Daylight Time
    -          dst(calculateTransitionForYear(rule.daylightTimeRule, year, rule.standardTimeBias))
    -    {
    -        /*
    -          Check for potential "fake DST", used by MS's APIs because the
    -          TIME_ZONE_INFORMATION spec either expresses no transitions in the
    -          year, or expresses a transition of each kind, even if standard time
    -          did change in a year with no DST.  We've seen year-start fake-DST
    -          (whose offset matches prior standard offset, in which the previous
    -          year ended); and conjecture that similar might be used at a year-end.
    -          (This might be used for a southern-hemisphere zone, where the start of
    -          the year usually is in DST, when applicable.)  Note that, here, wDay
    -          identifies an instance of a given day-of-week in the month, with 5
    -          meaning last.
    -
    -          Either the alleged standardTimeRule or the alleged daylightTimeRule
    -          may be faked; either way, the transition is actually a change to the
    -          current standard offset; but the unfaked half of the rule contains the
    -          useful bias data, so we have to go along with its lies.
    -
    -          Example: Russia/Moscow
    -          Format: -bias +( -stdBias, stdDate | -dstBias, dstDate ) notes
    -          Last year of DST, 2010: 180 +( 0, 0-10-5 3:0 | 60, 0-3-5 2:0 ) normal DST
    -          Zone change in 2011: 180 +( 0, 0-1-1 0:0 | 60 0-3-5 2:0 ) fake DST at transition
    -          Fixed standard in 2012: 240 +( 0, 0-0-0 0:0 | 60, 0-0-0 0:0 ) standard time years
    -          Zone change in 2014: 180 +( 0, 0-10-5 2:0 | 60, 0-1-1 0:0 ) fake DST at year-start
    -          The last of these is missing on Win7 VMs (too old to know about it).
    -        */
    -        if (rule.daylightTimeRule.wMonth == 1 && rule.daylightTimeRule.wDay == 1) {
    -            // Fake "DST transition" at start of year producing the same offset as
    -            // previous year ended in.
    -            if (rule.standardTimeBias + rule.daylightTimeBias == oldYearOffset)
    -                dst = QTimeZonePrivate::invalidMSecs();
    -        } else if (rule.daylightTimeRule.wMonth == 12 && rule.daylightTimeRule.wDay > 3) {
    -            // Similar, conjectured, for end of year, not changing offset.
    -            if (rule.daylightTimeBias == 0)
    -                dst = QTimeZonePrivate::invalidMSecs();
    -        }
    -        if (rule.standardTimeRule.wMonth == 1 && rule.standardTimeRule.wDay == 1) {
    -            // Fake "transition out of DST" at start of year producing the same
    -            // offset as previous year ended in.
    -            if (rule.standardTimeBias == oldYearOffset)
    -                std = QTimeZonePrivate::invalidMSecs();
    -        } else if (rule.standardTimeRule.wMonth == 12 && rule.standardTimeRule.wDay > 3) {
    -            // Similar, conjectured, for end of year, not changing offset.
    -            if (rule.daylightTimeBias == 0)
    -                std = QTimeZonePrivate::invalidMSecs();
    -        }
    -    }
    -
    -    bool fakesDst() const
    -    {
    -        return std == QTimeZonePrivate::invalidMSecs()
    -            || dst == QTimeZonePrivate::invalidMSecs();
    -    }
    -};
    -
    -int yearEndOffset(const QWinTimeZonePrivate::QWinTransitionRule &rule, int year)
    -{
    -    int offset = rule.standardTimeBias;
    -    // Only needed to help another TransitionTimePair work out year + 1's start
    -    // offset; and the oldYearOffset we use only affects an alleged transition
    -    // at the *start* of this year, so it doesn't matter if we guess wrong here:
    -    TransitionTimePair pair(rule, year, offset);
    -    if (pair.dst > pair.std)
    -        offset += rule.daylightTimeBias;
    -    return offset;
    -}
    -
    -QLocale::Country userCountry()
    -{
    -    const GEOID id = GetUserGeoID(GEOCLASS_NATION);
    -    wchar_t code[3];
    -    const int size = GetGeoInfo(id, GEO_ISO2, code, 3, 0);
    -    return (size == 3) ? QLocalePrivate::codeToCountry(QStringView(code, size))
    -                       : QLocale::AnyCountry;
    -}
    -
    -// Index of last rule in rules with .startYear <= year:
    -int ruleIndexForYear(const QList &rules, int year)
    -{
    -    if (rules.last().startYear <= year)
    -        return rules.count() - 1;
    -    // We don't have a rule for before the first, but the first is the best we can offer:
    -    if (rules.first().startYear > year)
    -        return 0;
    -
    -    // Otherwise, use binary chop:
    -    int lo = 0, hi = rules.count();
    -    // invariant: rules[i].startYear <= year < rules[hi].startYear
    -    // subject to treating rules[rules.count()] as "off the end of time"
    -    while (lo + 1 < hi) {
    -        const int mid = (lo + hi) / 2;
    -        // lo + 2 <= hi, so lo + 1 <= mid <= hi - 1, so lo < mid < hi
    -        // In particular, mid < rules.count()
    -        const int midYear = rules.at(mid).startYear;
    -        if (midYear > year)
    -            hi = mid;
    -        else if (midYear < year)
    -            lo = mid;
    -        else // No two rules have the same startYear:
    -            return mid;
    -    }
    -    return lo;
    -}
    -
    -} // anonymous namespace
    -
    -// Create the system default time zone
    -QWinTimeZonePrivate::QWinTimeZonePrivate()
    -                   : QTimeZonePrivate()
    -{
    -    init(QByteArray());
    -}
    -
    -// Create a named time zone
    -QWinTimeZonePrivate::QWinTimeZonePrivate(const QByteArray &ianaId)
    -                   : QTimeZonePrivate()
    -{
    -    init(ianaId);
    -}
    -
    -QWinTimeZonePrivate::QWinTimeZonePrivate(const QWinTimeZonePrivate &other)
    -                   : QTimeZonePrivate(other), m_windowsId(other.m_windowsId),
    -                     m_displayName(other.m_displayName), m_standardName(other.m_standardName),
    -                     m_daylightName(other.m_daylightName), m_tranRules(other.m_tranRules)
    -{
    -}
    -
    -QWinTimeZonePrivate::~QWinTimeZonePrivate()
    -{
    -}
    -
    -QWinTimeZonePrivate *QWinTimeZonePrivate::clone() const
    -{
    -    return new QWinTimeZonePrivate(*this);
    -}
    -
    -void QWinTimeZonePrivate::init(const QByteArray &ianaId)
    -{
    -    if (ianaId.isEmpty()) {
    -        m_windowsId = windowsSystemZoneId();
    -        m_id = systemTimeZoneId();
    -    } else {
    -        m_windowsId = ianaIdToWindowsId(ianaId);
    -        m_id = ianaId;
    -    }
    -
    -    bool badMonth = false; // Only warn once per zone, if at all.
    -    if (!m_windowsId.isEmpty()) {
    -#ifdef QT_USE_REGISTRY_TIMEZONE
    -        // Open the base TZI for the time zone
    -        HKEY baseKey = NULL;
    -        const QString baseKeyPath = QString::fromUtf8(tzRegPath) + QLatin1Char('\\')
    -                                   + QString::fromUtf8(m_windowsId);
    -        if (openRegistryKey(baseKeyPath, &baseKey)) {
    -            //  Load the localized names
    -            m_displayName = readRegistryString(baseKey, L"Display");
    -            m_standardName = readRegistryString(baseKey, L"Std");
    -            m_daylightName = readRegistryString(baseKey, L"Dlt");
    -            // On Vista and later the optional dynamic key holds historic data
    -            const QString dynamicKeyPath = baseKeyPath + QLatin1String("\\Dynamic DST");
    -            HKEY dynamicKey = NULL;
    -            if (openRegistryKey(dynamicKeyPath, &dynamicKey)) {
    -                // Find out the start and end years stored, then iterate over them
    -                int startYear = readRegistryValue(dynamicKey, L"FirstEntry");
    -                int endYear = readRegistryValue(dynamicKey, L"LastEntry");
    -                for (int year = startYear; year <= endYear; ++year) {
    -                    bool ruleOk;
    -                    QWinTransitionRule rule = readRegistryRule(dynamicKey,
    -                                                               reinterpret_cast(QString::number(year).utf16()),
    -                                                               &ruleOk);
    -                    if (ruleOk
    -                        // Don't repeat a recurrent rule:
    -                        && (m_tranRules.isEmpty()
    -                            || !isSameRule(m_tranRules.last(), rule))) {
    -                        if (!badMonth
    -                            && (rule.standardTimeRule.wMonth == 0)
    -                            != (rule.daylightTimeRule.wMonth == 0)) {
    -                            badMonth = true;
    -                            qWarning("MS registry TZ API violated its wMonth constraint;"
    -                                     "this may cause mistakes for %s from %d",
    -                                     ianaId.constData(), year);
    -                        }
    -                        rule.startYear = m_tranRules.isEmpty() ? MIN_YEAR : year;
    -                        m_tranRules.append(rule);
    -                    }
    -                }
    -                RegCloseKey(dynamicKey);
    -            } else {
    -                // No dynamic data so use the base data
    -                bool ruleOk;
    -                QWinTransitionRule rule = readRegistryRule(baseKey, L"TZI", &ruleOk);
    -                rule.startYear = MIN_YEAR;
    -                if (ruleOk)
    -                    m_tranRules.append(rule);
    -            }
    -            RegCloseKey(baseKey);
    -        }
    -#else // QT_USE_REGISTRY_TIMEZONE
    -        if (gTimeZones->isEmpty())
    -            enumerateTimeZones();
    -        QWinRTTimeZoneHash::const_iterator it = gTimeZones->find(m_windowsId);
    -        if (it != gTimeZones->constEnd()) {
    -            m_displayName = it->timezoneName;
    -            m_standardName = it->standardName;
    -            m_daylightName = it->daylightName;
    -            DWORD firstYear = 0;
    -            DWORD lastYear = 0;
    -            DYNAMIC_TIME_ZONE_INFORMATION dtzi = dynamicInfoForId(m_windowsId);
    -            if (GetDynamicTimeZoneInformationEffectiveYears(&dtzi, &firstYear, &lastYear)
    -                == ERROR_SUCCESS && firstYear < lastYear) {
    -                for (DWORD year = firstYear; year <= lastYear; ++year) {
    -                    bool ok = false;
    -                    QWinTransitionRule rule = readDynamicRule(dtzi, year, &ok);
    -                    if (ok
    -                        // Don't repeat a recurrent rule
    -                        && (m_tranRules.isEmpty()
    -                            || !isSameRule(m_tranRules.last(), rule))) {
    -                        if (!badMonth
    -                            && (rule.standardTimeRule.wMonth == 0)
    -                            != (rule.daylightTimeRule.wMonth == 0)) {
    -                            badMonth = true;
    -                            qWarning("MS dynamic TZ API violated its wMonth constraint;"
    -                                     "this may cause mistakes for %s from %d",
    -                                     ianaId.constData(), year);
    -                        }
    -                        rule.startYear = m_tranRules.isEmpty() ? MIN_YEAR : year;
    -                        m_tranRules.append(rule);
    -                    }
    -                }
    -            } else {
    -                // At least try to get the non-dynamic data:
    -                dtzi.DynamicDaylightTimeDisabled = false;
    -                bool ok = false;
    -                QWinTransitionRule rule = readDynamicRule(dtzi, 1970, &ok);
    -                if (ok) {
    -                    rule.startYear = MIN_YEAR;
    -                    m_tranRules.append(rule);
    -                }
    -            }
    -        }
    -#endif // QT_USE_REGISTRY_TIMEZONE
    -    }
    -
    -    // If there are no rules then we failed to find a windowsId or any tzi info
    -    if (m_tranRules.size() == 0) {
    -        m_id.clear();
    -        m_windowsId.clear();
    -        m_displayName.clear();
    -    }
    -}
    -
    -QString QWinTimeZonePrivate::comment() const
    -{
    -    return m_displayName;
    -}
    -
    -QString QWinTimeZonePrivate::displayName(QTimeZone::TimeType timeType,
    -                                         QTimeZone::NameType nameType,
    -                                         const QLocale &locale) const
    -{
    -    // TODO Registry holds MUI keys, should be able to look up translations?
    -    Q_UNUSED(locale);
    -
    -    if (nameType == QTimeZone::OffsetName) {
    -        const QWinTransitionRule &rule =
    -            m_tranRules.at(ruleIndexForYear(m_tranRules, QDate::currentDate().year()));
    -        int offset = rule.standardTimeBias;
    -        if (timeType == QTimeZone::DaylightTime)
    -            offset += rule.daylightTimeBias;
    -        return isoOffsetFormat(offset * -60);
    -    }
    -
    -    switch (timeType) {
    -    case  QTimeZone::DaylightTime :
    -        return m_daylightName;
    -    case  QTimeZone::GenericTime :
    -        return m_displayName;
    -    case  QTimeZone::StandardTime :
    -        return m_standardName;
    -    }
    -    return m_standardName;
    -}
    -
    -QString QWinTimeZonePrivate::abbreviation(qint64 atMSecsSinceEpoch) const
    -{
    -    return data(atMSecsSinceEpoch).abbreviation;
    -}
    -
    -int QWinTimeZonePrivate::offsetFromUtc(qint64 atMSecsSinceEpoch) const
    -{
    -    return data(atMSecsSinceEpoch).offsetFromUtc;
    -}
    -
    -int QWinTimeZonePrivate::standardTimeOffset(qint64 atMSecsSinceEpoch) const
    -{
    -    return data(atMSecsSinceEpoch).standardTimeOffset;
    -}
    -
    -int QWinTimeZonePrivate::daylightTimeOffset(qint64 atMSecsSinceEpoch) const
    -{
    -    return data(atMSecsSinceEpoch).daylightTimeOffset;
    -}
    -
    -bool QWinTimeZonePrivate::hasDaylightTime() const
    -{
    -    return hasTransitions();
    -}
    -
    -bool QWinTimeZonePrivate::isDaylightTime(qint64 atMSecsSinceEpoch) const
    -{
    -    return (data(atMSecsSinceEpoch).daylightTimeOffset != 0);
    -}
    -
    -QTimeZonePrivate::Data QWinTimeZonePrivate::data(qint64 forMSecsSinceEpoch) const
    -{
    -    int year = msecsToDate(forMSecsSinceEpoch).year();
    -    for (int ruleIndex = ruleIndexForYear(m_tranRules, year);
    -         ruleIndex >= 0; --ruleIndex) {
    -        const QWinTransitionRule &rule = m_tranRules.at(ruleIndex);
    -        // Does this rule's period include any transition at all ?
    -        if (rule.standardTimeRule.wMonth > 0 || rule.daylightTimeRule.wMonth > 0) {
    -            const int endYear = qMax(rule.startYear, year - 1);
    -            while (year >= endYear) {
    -                const int newYearOffset = (year <= rule.startYear && ruleIndex > 0)
    -                    ? yearEndOffset(m_tranRules.at(ruleIndex - 1), year - 1)
    -                    : yearEndOffset(rule, year - 1);
    -                const TransitionTimePair pair(rule, year, newYearOffset);
    -                bool isDst = false;
    -                if (pair.std != invalidMSecs() && pair.std <= forMSecsSinceEpoch) {
    -                    isDst = pair.std < pair.dst && pair.dst <= forMSecsSinceEpoch;
    -                } else if (pair.dst != invalidMSecs() && pair.dst <= forMSecsSinceEpoch) {
    -                    isDst = true;
    -                } else {
    -                    --year; // Try an earlier year for this rule (once).
    -                    continue;
    -                }
    -                return ruleToData(rule, forMSecsSinceEpoch,
    -                                  isDst ? QTimeZone::DaylightTime : QTimeZone::StandardTime,
    -                                  pair.fakesDst());
    -            }
    -            // Fell off start of rule, try previous rule.
    -        } else {
    -            // No transition, no DST, use the year's standard time.
    -            return ruleToData(rule, forMSecsSinceEpoch, QTimeZone::StandardTime);
    -        }
    -        if (year >= rule.startYear)
    -            year = rule.startYear - 1; // Seek last transition in new rule.
    -    }
    -    // We don't have relevant data :-(
    -    return invalidData();
    -}
    -
    -bool QWinTimeZonePrivate::hasTransitions() const
    -{
    -    for (const QWinTransitionRule &rule : m_tranRules) {
    -        if (rule.standardTimeRule.wMonth > 0 && rule.daylightTimeRule.wMonth > 0)
    -            return true;
    -    }
    -    return false;
    -}
    -
    -QTimeZonePrivate::Data QWinTimeZonePrivate::nextTransition(qint64 afterMSecsSinceEpoch) const
    -{
    -    int year = msecsToDate(afterMSecsSinceEpoch).year();
    -    for (int ruleIndex = ruleIndexForYear(m_tranRules, year);
    -         ruleIndex < m_tranRules.count(); ++ruleIndex) {
    -        const QWinTransitionRule &rule = m_tranRules.at(ruleIndex);
    -        // Does this rule's period include any transition at all ?
    -        if (rule.standardTimeRule.wMonth > 0 || rule.daylightTimeRule.wMonth > 0) {
    -            if (year < rule.startYear)
    -                year = rule.startYear; // Seek first transition in this rule.
    -            const int endYear = ruleIndex + 1 < m_tranRules.count()
    -                ? qMin(m_tranRules.at(ruleIndex + 1).startYear, year + 2) : (year + 2);
    -            int newYearOffset = (year <= rule.startYear && ruleIndex > 0)
    -                ? yearEndOffset(m_tranRules.at(ruleIndex - 1), year - 1)
    -                : yearEndOffset(rule, year - 1);
    -            while (year < endYear) {
    -                const TransitionTimePair pair(rule, year, newYearOffset);
    -                bool isDst = false;
    -                Q_ASSERT(invalidMSecs() <= afterMSecsSinceEpoch); // invalid is min qint64
    -                if (pair.std > afterMSecsSinceEpoch) {
    -                    isDst = pair.std > pair.dst && pair.dst > afterMSecsSinceEpoch;
    -                } else if (pair.dst > afterMSecsSinceEpoch) {
    -                    isDst = true;
    -                } else {
    -                    newYearOffset = rule.standardTimeBias;
    -                    if (pair.dst > pair.std)
    -                        newYearOffset += rule.daylightTimeBias;
    -                    ++year; // Try a later year for this rule (once).
    -                    continue;
    -                }
    -
    -                if (isDst)
    -                    return ruleToData(rule, pair.dst, QTimeZone::DaylightTime, pair.fakesDst());
    -                return ruleToData(rule, pair.std, QTimeZone::StandardTime, pair.fakesDst());
    -            }
    -            // Fell off end of rule, try next rule.
    -        } // else: no transition during rule's period
    -    }
    -    // Apparently no transition after the given time:
    -    return invalidData();
    -}
    -
    -QTimeZonePrivate::Data QWinTimeZonePrivate::previousTransition(qint64 beforeMSecsSinceEpoch) const
    -{
    -    const qint64 startOfTime = invalidMSecs() + 1;
    -    if (beforeMSecsSinceEpoch <= startOfTime)
    -        return invalidData();
    -
    -    int year = msecsToDate(beforeMSecsSinceEpoch).year();
    -    for (int ruleIndex = ruleIndexForYear(m_tranRules, year);
    -         ruleIndex >= 0; --ruleIndex) {
    -        const QWinTransitionRule &rule = m_tranRules.at(ruleIndex);
    -        // Does this rule's period include any transition at all ?
    -        if (rule.standardTimeRule.wMonth > 0 || rule.daylightTimeRule.wMonth > 0) {
    -            const int endYear = qMax(rule.startYear, year - 1);
    -            while (year >= endYear) {
    -                const int newYearOffset = (year <= rule.startYear && ruleIndex > 0)
    -                    ? yearEndOffset(m_tranRules.at(ruleIndex - 1), year - 1)
    -                    : yearEndOffset(rule, year - 1);
    -                const TransitionTimePair pair(rule, year, newYearOffset);
    -                bool isDst = false;
    -                if (pair.std != invalidMSecs() && pair.std < beforeMSecsSinceEpoch) {
    -                    isDst = pair.std < pair.dst && pair.dst < beforeMSecsSinceEpoch;
    -                } else if (pair.dst != invalidMSecs() && pair.dst < beforeMSecsSinceEpoch) {
    -                    isDst = true;
    -                } else {
    -                    --year; // Try an earlier year for this rule (once).
    -                    continue;
    -                }
    -                if (isDst)
    -                    return ruleToData(rule, pair.dst, QTimeZone::DaylightTime, pair.fakesDst());
    -                return ruleToData(rule, pair.std, QTimeZone::StandardTime, pair.fakesDst());
    -            }
    -            // Fell off start of rule, try previous rule.
    -        } else if (ruleIndex == 0) {
    -            // Treat a no-transition first rule as a transition at the start of
    -            // time, so that a scan through all rules *does* see it as the first
    -            // rule:
    -            return ruleToData(rule, startOfTime, QTimeZone::StandardTime, false);
    -        } // else: no transition during rule's period
    -        if (year >= rule.startYear)
    -            year = rule.startYear - 1; // Seek last transition in new rule
    -    }
    -    // Apparently no transition before the given time:
    -    return invalidData();
    -}
    -
    -QByteArray QWinTimeZonePrivate::systemTimeZoneId() const
    -{
    -    const QLocale::Country country = userCountry();
    -    const QByteArray windowsId = windowsSystemZoneId();
    -    QByteArray ianaId;
    -    // If we have a real country, then try get a specific match for that country
    -    if (country != QLocale::AnyCountry)
    -        ianaId = windowsIdToDefaultIanaId(windowsId, country);
    -    // If we don't have a real country, or there wasn't a specific match, try the global default
    -    if (ianaId.isEmpty()) {
    -        ianaId = windowsIdToDefaultIanaId(windowsId);
    -        // If no global default then probably an unknown Windows ID so return UTC
    -        if (ianaId.isEmpty())
    -            return utcQByteArray();
    -    }
    -    return ianaId;
    -}
    -
    -QList QWinTimeZonePrivate::availableTimeZoneIds() const
    -{
    -    QList result;
    -    const auto winIds = availableWindowsIds();
    -    for (const QByteArray &winId : winIds)
    -        result += windowsIdToIanaIds(winId);
    -    std::sort(result.begin(), result.end());
    -    result.erase(std::unique(result.begin(), result.end()), result.end());
    -    return result;
    -}
    -
    -QTimeZonePrivate::Data QWinTimeZonePrivate::ruleToData(const QWinTransitionRule &rule,
    -                                                       qint64 atMSecsSinceEpoch,
    -                                                       QTimeZone::TimeType type,
    -                                                       bool fakeDst) const
    -{
    -    Data tran = invalidData();
    -    tran.atMSecsSinceEpoch = atMSecsSinceEpoch;
    -    tran.standardTimeOffset = rule.standardTimeBias * -60;
    -    if (fakeDst) {
    -        tran.daylightTimeOffset = 0;
    -        tran.abbreviation = m_standardName;
    -        // Rule may claim we're in DST when it's actually a standard time change:
    -        if (type == QTimeZone::DaylightTime)
    -            tran.standardTimeOffset += rule.daylightTimeBias * -60;
    -    } else if (type == QTimeZone::DaylightTime) {
    -        tran.daylightTimeOffset = rule.daylightTimeBias * -60;
    -        tran.abbreviation = m_daylightName;
    -    } else {
    -        tran.daylightTimeOffset = 0;
    -        tran.abbreviation = m_standardName;
    -    }
    -    tran.offsetFromUtc = tran.standardTimeOffset + tran.daylightTimeOffset;
    -    return tran;
    -}
    -
    -QT_END_NAMESPACE
    diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri
    index 5dcb6c9ee0..52eddd5d6b 100644
    --- a/src/corelib/tools/tools.pri
    +++ b/src/corelib/tools/tools.pri
    @@ -20,8 +20,6 @@ HEADERS +=  \
             tools/qcontainerfwd.h \
             tools/qcontainertools_impl.h \
             tools/qcryptographichash.h \
    -        tools/qdatetime.h \
    -        tools/qdatetime_p.h \
             tools/qdoublescanprint_p.h \
             tools/qeasingcurve.h \
             tools/qfreelist_p.h \
    @@ -86,7 +84,6 @@ SOURCES += \
             tools/qbytearraymatcher.cpp \
             tools/qcollator.cpp \
             tools/qcryptographichash.cpp \
    -        tools/qdatetime.cpp \
             tools/qeasingcurve.cpp \
             tools/qfreelist.cpp \
             tools/qhash.cpp \
    @@ -154,33 +151,6 @@ qtConfig(icu) {
         SOURCES += tools/qcollator_posix.cpp
     }
     
    -qtConfig(timezone) {
    -    HEADERS += \
    -        tools/qtimezone.h \
    -        tools/qtimezoneprivate_p.h \
    -        tools/qtimezoneprivate_data_p.h
    -    SOURCES += \
    -        tools/qtimezone.cpp \
    -        tools/qtimezoneprivate.cpp
    -    !nacl:darwin: {
    -        SOURCES += tools/qtimezoneprivate_mac.mm
    -    } else: android:!android-embedded: {
    -        SOURCES += tools/qtimezoneprivate_android.cpp
    -    } else: unix: {
    -        SOURCES += tools/qtimezoneprivate_tz.cpp
    -        qtConfig(icu): SOURCES += tools/qtimezoneprivate_icu.cpp
    -    } else: qtConfig(icu): {
    -        SOURCES += tools/qtimezoneprivate_icu.cpp
    -    } else: win32: {
    -        SOURCES += tools/qtimezoneprivate_win.cpp
    -    }
    -}
    -
    -qtConfig(datetimeparser) {
    -    HEADERS += tools/qdatetimeparser_p.h
    -    SOURCES += tools/qdatetimeparser.cpp
    -}
    -
     qtConfig(regularexpression) {
         QMAKE_USE_PRIVATE += pcre2
     
    diff --git a/src/tools/bootstrap/bootstrap.pro b/src/tools/bootstrap/bootstrap.pro
    index 3aeca6e7af..40c0702f0a 100644
    --- a/src/tools/bootstrap/bootstrap.pro
    +++ b/src/tools/bootstrap/bootstrap.pro
    @@ -72,6 +72,7 @@ SOURCES += \
                ../../corelib/serialization/qtextstream.cpp \
                ../../corelib/serialization/qxmlutils.cpp \
                ../../corelib/serialization/qxmlstream.cpp \
    +           ../../corelib/time/qdatetime.cpp \
                ../../corelib/tools/qbitarray.cpp \
                ../../corelib/tools/qbytearray.cpp \
                ../../corelib/tools/qarraydata.cpp \
    @@ -79,7 +80,6 @@ SOURCES += \
                ../../corelib/tools/qcommandlineparser.cpp \
                ../../corelib/tools/qcommandlineoption.cpp \
                ../../corelib/tools/qcryptographichash.cpp \
    -           ../../corelib/tools/qdatetime.cpp \
                ../../corelib/tools/qhash.cpp \
                ../../corelib/tools/qlist.cpp \
                ../../corelib/tools/qlinkedlist.cpp \
    -- 
    cgit v1.2.3
    
    
    From e85aa551ebe5f882c9771dc3ea2b90b02b286a49 Mon Sep 17 00:00:00 2001
    From: Laszlo Agocs 
    Date: Mon, 8 Apr 2019 17:05:28 +0200
    Subject: vulkan: Add debug message filtering
    
    [ChangeLog][QtGui] Added support for filtering Vulkan debug messages in
    QVulkanInstance. This is especially useful for processing or suppressing
    messages from the validation layers.
    
    Change-Id: Idf0d7889085948daf5b1a53d2a9b11081e967609
    Reviewed-by: Paul Olav Tvete 
    ---
     src/gui/vulkan/qplatformvulkaninstance.cpp         |  5 +++
     src/gui/vulkan/qplatformvulkaninstance.h           |  1 +
     src/gui/vulkan/qvulkaninstance.cpp                 | 46 ++++++++++++++++++++++
     src/gui/vulkan/qvulkaninstance.h                   |  5 +++
     .../vkconvenience/qbasicvulkanplatforminstance.cpp | 16 +++++---
     .../vkconvenience/qbasicvulkanplatforminstance_p.h |  4 ++
     6 files changed, 72 insertions(+), 5 deletions(-)
    
    (limited to 'src')
    
    diff --git a/src/gui/vulkan/qplatformvulkaninstance.cpp b/src/gui/vulkan/qplatformvulkaninstance.cpp
    index 6201d3ec11..9d044bfd58 100644
    --- a/src/gui/vulkan/qplatformvulkaninstance.cpp
    +++ b/src/gui/vulkan/qplatformvulkaninstance.cpp
    @@ -85,4 +85,9 @@ void QPlatformVulkanInstance::presentQueued(QWindow *window)
         Q_UNUSED(window);
     }
     
    +void QPlatformVulkanInstance::setDebugFilters(const QVector &filters)
    +{
    +    Q_UNUSED(filters);
    +}
    +
     QT_END_NAMESPACE
    diff --git a/src/gui/vulkan/qplatformvulkaninstance.h b/src/gui/vulkan/qplatformvulkaninstance.h
    index 9f34803f7b..d47c59b5db 100644
    --- a/src/gui/vulkan/qplatformvulkaninstance.h
    +++ b/src/gui/vulkan/qplatformvulkaninstance.h
    @@ -78,6 +78,7 @@ public:
         virtual PFN_vkVoidFunction getInstanceProcAddr(const char *name) = 0;
         virtual bool supportsPresent(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, QWindow *window) = 0;
         virtual void presentQueued(QWindow *window);
    +    virtual void setDebugFilters(const QVector &filters);
     
     private:
         QScopedPointer d_ptr;
    diff --git a/src/gui/vulkan/qvulkaninstance.cpp b/src/gui/vulkan/qvulkaninstance.cpp
    index 2941bfd01f..0605d88cca 100644
    --- a/src/gui/vulkan/qvulkaninstance.cpp
    +++ b/src/gui/vulkan/qvulkaninstance.cpp
    @@ -269,6 +269,7 @@ public:
         VkResult errorCode;
         QScopedPointer funcs;
         QHash deviceFuncs;
    +    QVector debugFilters;
     };
     
     bool QVulkanInstancePrivate::ensureVulkan()
    @@ -570,6 +571,7 @@ bool QVulkanInstance::create()
             d_ptr->extensions = d_ptr->platformInst->enabledExtensions();
             d_ptr->errorCode = VK_SUCCESS;
             d_ptr->funcs.reset(new QVulkanFunctions(this));
    +        d_ptr->platformInst->setDebugFilters(d_ptr->debugFilters);
             return true;
         }
     
    @@ -785,6 +787,50 @@ void QVulkanInstance::presentQueued(QWindow *window)
         d_ptr->platformInst->presentQueued(window);
     }
     
    +/*!
    +    \typedef QVulkanInstance::DebugFilter
    +
    +    Typedef for debug filtering callback functions.
    +
    +    \sa installDebugOutputFilter(), removeDebugOutputFilter()
    + */
    +
    +/*!
    +    Installs a \a filter function that is called for every Vulkan debug
    +    message. When the callback returns \c true, the message is stopped (filtered
    +    out) and will not appear on the debug output.
    +
    +    \note Filtering is only effective when NoDebugOutputRedirect is not
    +    \l{setFlags()}{set}. Installing filters has no effect otherwise.
    +
    +    \note This function can be called before create().
    +
    +    \sa removeDebugOutputFilter()
    + */
    +void QVulkanInstance::installDebugOutputFilter(DebugFilter filter)
    +{
    +    if (!d_ptr->debugFilters.contains(filter)) {
    +        d_ptr->debugFilters.append(filter);
    +        if (d_ptr->platformInst)
    +            d_ptr->platformInst->setDebugFilters(d_ptr->debugFilters);
    +    }
    +}
    +
    +/*!
    +    Removes a \a filter function previously installed by
    +    installDebugOutputFilter().
    +
    +    \note This function can be called before create().
    +
    +    \sa installDebugOutputFilter()
    + */
    +void QVulkanInstance::removeDebugOutputFilter(DebugFilter filter)
    +{
    +    d_ptr->debugFilters.removeOne(filter);
    +    if (d_ptr->platformInst)
    +        d_ptr->platformInst->setDebugFilters(d_ptr->debugFilters);
    +}
    +
     #ifndef QT_NO_DEBUG_STREAM
     QDebug operator<<(QDebug dbg, const QVulkanLayer &layer)
     {
    diff --git a/src/gui/vulkan/qvulkaninstance.h b/src/gui/vulkan/qvulkaninstance.h
    index f28975f911..70f2fd5102 100644
    --- a/src/gui/vulkan/qvulkaninstance.h
    +++ b/src/gui/vulkan/qvulkaninstance.h
    @@ -188,6 +188,11 @@ public:
     
         void presentQueued(QWindow *window);
     
    +    typedef bool (*DebugFilter)(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object,
    +                                size_t location, int32_t messageCode, const char *pLayerPrefix, const char *pMessage);
    +    void installDebugOutputFilter(DebugFilter filter);
    +    void removeDebugOutputFilter(DebugFilter filter);
    +
     private:
         QScopedPointer d_ptr;
         Q_DISABLE_COPY(QVulkanInstance)
    diff --git a/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance.cpp b/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance.cpp
    index b9c5669b3f..68340a3173 100644
    --- a/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance.cpp
    +++ b/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance.cpp
    @@ -330,6 +330,11 @@ bool QBasicPlatformVulkanInstance::supportsPresent(VkPhysicalDevice physicalDevi
         return supported;
     }
     
    +void QBasicPlatformVulkanInstance::setDebugFilters(const QVector &filters)
    +{
    +    m_debugFilters = filters;
    +}
    +
     void QBasicPlatformVulkanInstance::destroySurface(VkSurfaceKHR surface) const
     {
         if (m_destroySurface && surface)
    @@ -345,11 +350,11 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL defaultDebugCallbackFunc(VkDebugReportFlag
                                                                    const char *pMessage,
                                                                    void *pUserData)
     {
    -    Q_UNUSED(flags);
    -    Q_UNUSED(objectType);
    -    Q_UNUSED(object);
    -    Q_UNUSED(location);
    -    Q_UNUSED(pUserData);
    +    QBasicPlatformVulkanInstance *self = static_cast(pUserData);
    +    for (QVulkanInstance::DebugFilter filter : *self->debugFilters()) {
    +        if (filter(flags, objectType, object, location, messageCode, pLayerPrefix, pMessage))
    +            return VK_FALSE;
    +    }
     
         // not categorized, just route to plain old qDebug
         qDebug("vkDebug: %s: %d: %s", pLayerPrefix, messageCode, pMessage);
    @@ -374,6 +379,7 @@ void QBasicPlatformVulkanInstance::setupDebugOutput()
                 | VK_DEBUG_REPORT_WARNING_BIT_EXT
                 | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
         dbgCallbackInfo.pfnCallback = defaultDebugCallbackFunc;
    +    dbgCallbackInfo.pUserData = this;
     
         VkResult err = createDebugReportCallback(m_vkInst, &dbgCallbackInfo, nullptr, &m_debugCallback);
         if (err != VK_SUCCESS)
    diff --git a/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance_p.h b/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance_p.h
    index 566140b032..e59d9219fb 100644
    --- a/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance_p.h
    +++ b/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance_p.h
    @@ -73,7 +73,10 @@ public:
         QByteArrayList enabledExtensions() const override;
         PFN_vkVoidFunction getInstanceProcAddr(const char *name) override;
         bool supportsPresent(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, QWindow *window) override;
    +    void setDebugFilters(const QVector &filters) override;
    +
         void destroySurface(VkSurfaceKHR surface) const;
    +    const QVector *debugFilters() const { return &m_debugFilters; }
     
     protected:
         void loadVulkanLibrary(const QString &defaultLibraryName);
    @@ -105,6 +108,7 @@ private:
     
         VkDebugReportCallbackEXT m_debugCallback;
         PFN_vkDestroyDebugReportCallbackEXT m_vkDestroyDebugReportCallbackEXT;
    +    QVector m_debugFilters;
     };
     
     QT_END_NAMESPACE
    -- 
    cgit v1.2.3
    
    
    From 27e723496351bf4077b3f5e548fddb252e032579 Mon Sep 17 00:00:00 2001
    From: Friedemann Kleint 
    Date: Fri, 24 May 2019 16:34:40 +0200
    Subject: Windows QPA: Fix clang warnings about using typedef
    
    Replace by using (except for function pointers).
    
    Change-Id: I0dfe03c22f9f87155003d13a6376381623df7217
    Reviewed-by: Oliver Wolff 
    ---
     src/plugins/platforms/windows/qwindowscursor.h           |  2 +-
     src/plugins/platforms/windows/qwindowsdialoghelpers.cpp  | 10 +++++-----
     src/plugins/platforms/windows/qwindowsdialoghelpers.h    |  2 +-
     src/plugins/platforms/windows/qwindowsmenu.h             |  4 ++--
     src/plugins/platforms/windows/qwindowsmousehandler.cpp   |  4 ++--
     src/plugins/platforms/windows/qwindowsscreen.cpp         |  2 +-
     src/plugins/platforms/windows/qwindowsscreen.h           |  4 ++--
     src/plugins/platforms/windows/qwindowssystemtrayicon.cpp |  2 +-
     src/plugins/platforms/windows/qwindowswindow.cpp         |  4 ++--
     9 files changed, 17 insertions(+), 17 deletions(-)
    
    (limited to 'src')
    
    diff --git a/src/plugins/platforms/windows/qwindowscursor.h b/src/plugins/platforms/windows/qwindowscursor.h
    index d5c189b5ca..b896f4c7a9 100644
    --- a/src/plugins/platforms/windows/qwindowscursor.h
    +++ b/src/plugins/platforms/windows/qwindowscursor.h
    @@ -84,7 +84,7 @@ private:
         const HCURSOR m_hcursor;
     };
     
    -typedef QSharedPointer CursorHandlePtr;
    +using CursorHandlePtr = QSharedPointer;
     
     class QWindowsCursor : public QPlatformCursor
     {
    diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
    index e55b8fd7b8..57f19b5ff2 100644
    --- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
    +++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
    @@ -271,7 +271,7 @@ QWindowsNativeDialogBase *QWindowsDialogHelperBase::ensureNativeDialo
     class QWindowsDialogThread : public QThread
     {
     public:
    -    typedef QSharedPointer QWindowsNativeDialogBasePtr;
    +    using QWindowsNativeDialogBasePtr = QSharedPointer;
     
         explicit QWindowsDialogThread(const QWindowsNativeDialogBasePtr &d, HWND owner)
             : m_dialog(d), m_owner(owner) {}
    @@ -551,7 +551,7 @@ IFileDialogEvents *QWindowsNativeFileDialogEventHandler::create(QWindowsNativeFi
     class QWindowsShellItem
     {
     public:
    -    typedef std::vector IShellItems;
    +    using IShellItems = std::vector;
     
         explicit QWindowsShellItem(IShellItem *item);
     
    @@ -1688,7 +1688,7 @@ class QWindowsXpNativeFileDialog : public QWindowsNativeDialogBase
     {
         Q_OBJECT
     public:
    -    typedef QSharedPointer OptionsPtr;
    +    using OptionsPtr = QSharedPointer;
     
         static QWindowsXpNativeFileDialog *create(const OptionsPtr &options, const QWindowsFileDialogSharedData &data);
     
    @@ -1779,7 +1779,7 @@ static int QT_WIN_CALLBACK xpFileDialogGetExistingDirCallbackProc(HWND hwnd, UIN
     #if defined(Q_CC_MINGW) && (!defined(__MINGW64_VERSION_MAJOR) || __MINGW64_VERSION_MAJOR < 3)
     typedef ITEMIDLIST *qt_LpItemIdList;
     #else
    -typedef PIDLIST_ABSOLUTE qt_LpItemIdList;
    +using qt_LpItemIdList = PIDLIST_ABSOLUTE;
     #endif
     
     int QWindowsXpNativeFileDialog::existingDirCallback(HWND hwnd, UINT uMsg, LPARAM lParam)
    @@ -2007,7 +2007,7 @@ QString QWindowsXpFileDialogHelper::selectedNameFilter() const
         \ingroup qt-lighthouse-win
     */
     
    -typedef QSharedPointer SharedPointerColor;
    +using SharedPointerColor = QSharedPointer;
     
     #ifdef USE_NATIVE_COLOR_DIALOG
     class QWindowsNativeColorDialog : public QWindowsNativeDialogBase
    diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.h b/src/plugins/platforms/windows/qwindowsdialoghelpers.h
    index f0a7ef5e90..8686749011 100644
    --- a/src/plugins/platforms/windows/qwindowsdialoghelpers.h
    +++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.h
    @@ -66,7 +66,7 @@ class QWindowsDialogHelperBase : public BaseClass
     {
         Q_DISABLE_COPY_MOVE(QWindowsDialogHelperBase)
     public:
    -    typedef QSharedPointer QWindowsNativeDialogBasePtr;
    +    using QWindowsNativeDialogBasePtr = QSharedPointer;
         ~QWindowsDialogHelperBase() { cleanupThread(); }
     
         void exec() override;
    diff --git a/src/plugins/platforms/windows/qwindowsmenu.h b/src/plugins/platforms/windows/qwindowsmenu.h
    index 6de1553f35..aa36846ec0 100644
    --- a/src/plugins/platforms/windows/qwindowsmenu.h
    +++ b/src/plugins/platforms/windows/qwindowsmenu.h
    @@ -120,7 +120,7 @@ class QWindowsMenu : public QPlatformMenu
     {
         Q_OBJECT
     public:
    -    typedef QVector MenuItems;
    +    using MenuItems = QVector;
     
         QWindowsMenu();
         ~QWindowsMenu();
    @@ -196,7 +196,7 @@ class QWindowsMenuBar : public QPlatformMenuBar
     {
         Q_OBJECT
     public:
    -    typedef QVector Menus;
    +    using Menus = QVector;
     
         QWindowsMenuBar();
         ~QWindowsMenuBar() override;
    diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp
    index 97e1319e8d..c15819a65f 100644
    --- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp
    +++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp
    @@ -609,8 +609,8 @@ bool QWindowsMouseHandler::translateTouchEvent(QWindow *window, HWND,
                                                    QtWindows::WindowsEventType,
                                                    MSG msg, LRESULT *)
     {
    -    typedef QWindowSystemInterface::TouchPoint QTouchPoint;
    -    typedef QList QTouchPointList;
    +    using QTouchPoint = QWindowSystemInterface::TouchPoint;
    +    using QTouchPointList = QList;
     
         if (!QWindowsContext::instance()->initTouch()) {
             qWarning("Unable to initialize touch handling.");
    diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp
    index 2f8850cbe0..e3931b3bb1 100644
    --- a/src/plugins/platforms/windows/qwindowsscreen.cpp
    +++ b/src/plugins/platforms/windows/qwindowsscreen.cpp
    @@ -72,7 +72,7 @@ static inline QDpi monitorDPI(HMONITOR hMonitor)
         return {0, 0};
     }
     
    -typedef QList WindowsScreenDataList;
    +using WindowsScreenDataList = QList;
     
     static bool monitorData(HMONITOR hMonitor, QWindowsScreenData *data)
     {
    diff --git a/src/plugins/platforms/windows/qwindowsscreen.h b/src/plugins/platforms/windows/qwindowsscreen.h
    index 3eb2d35b27..0ccebf6d71 100644
    --- a/src/plugins/platforms/windows/qwindowsscreen.h
    +++ b/src/plugins/platforms/windows/qwindowsscreen.h
    @@ -76,7 +76,7 @@ class QWindowsScreen : public QPlatformScreen
     {
     public:
     #ifndef QT_NO_CURSOR
    -    typedef QScopedPointer CursorPtr;
    +    using CursorPtr = QScopedPointer;
     #endif
     
         explicit QWindowsScreen(const QWindowsScreenData &data);
    @@ -127,7 +127,7 @@ private:
     class QWindowsScreenManager
     {
     public:
    -    typedef QList WindowsScreenList;
    +    using WindowsScreenList = QList;
     
         QWindowsScreenManager();
     
    diff --git a/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp b/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp
    index c0f4e4d014..f2dba4d06b 100644
    --- a/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp
    +++ b/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp
    @@ -117,7 +117,7 @@ struct QWindowsHwndSystemTrayIconEntry
         QWindowsSystemTrayIcon *trayIcon;
     };
     
    -typedef QVector HwndTrayIconEntries;
    +using HwndTrayIconEntries = QVector;
     
     Q_GLOBAL_STATIC(HwndTrayIconEntries, hwndTrayIconEntries)
     
    diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
    index 174c63bbbd..3669407765 100644
    --- a/src/plugins/platforms/windows/qwindowswindow.cpp
    +++ b/src/plugins/platforms/windows/qwindowswindow.cpp
    @@ -86,7 +86,7 @@
     
     QT_BEGIN_NAMESPACE
     
    -typedef QSharedPointer QWindowCreationContextPtr;
    +using QWindowCreationContextPtr = QSharedPointer;
     
     enum {
         defaultWindowWidth = 160,
    @@ -494,7 +494,7 @@ static QMargins invisibleMargins(QPoint screenPoint)
     
     struct WindowCreationData
     {
    -    typedef QWindowsWindowData WindowData;
    +    using WindowData = QWindowsWindowData;
         enum Flags { ForceChild = 0x1, ForceTopLevel = 0x2 };
     
         void fromWindow(const QWindow *w, const Qt::WindowFlags flags, unsigned creationFlags = 0);
    -- 
    cgit v1.2.3
    
    
    From a3b931e7c4a5702da5fd99df0746f9ff511b7fdc Mon Sep 17 00:00:00 2001
    From: Edward Welbourne 
    Date: Tue, 28 May 2019 11:53:05 +0200
    Subject: Construct from an array instead of assigning just past a string's end
    MIME-Version: 1.0
    Content-Type: text/plain; charset=UTF-8
    Content-Transfer-Encoding: 8bit
    
    Assigning past the end used to be supported, but isn't a good way to
    do the job.  Exposed by a qtxmlpatterns test that exercised this code,
    which gets a warning thanks to Giuseppe's recent changes to QCharRef.
    
    Task-number: QTBUG-76070
    Change-Id: Ic254c7ffce60e3b2aafce76ab03ea5db8c68fafc
    Reviewed-by: Giuseppe D'Angelo 
    Reviewed-by: Mårten Nordheim 
    ---
     src/network/access/qftp.cpp | 8 +++-----
     1 file changed, 3 insertions(+), 5 deletions(-)
    
    (limited to 'src')
    
    diff --git a/src/network/access/qftp.cpp b/src/network/access/qftp.cpp
    index b6b721030b..cc230a5411 100644
    --- a/src/network/access/qftp.cpp
    +++ b/src/network/access/qftp.cpp
    @@ -955,11 +955,9 @@ void QFtpPI::readyRead()
                     }
                 }
             }
    -        QString endOfMultiLine;
    -        endOfMultiLine[0] = '0' + replyCode[0];
    -        endOfMultiLine[1] = '0' + replyCode[1];
    -        endOfMultiLine[2] = '0' + replyCode[2];
    -        endOfMultiLine[3] = QLatin1Char(' ');
    +        const char count[4] = { char('0' + replyCode[0]), char('0' + replyCode[1]),
    +                                char('0' + replyCode[2]), char(' ') };
    +        QString endOfMultiLine(QLatin1String(count, 4));
             QString lineCont(endOfMultiLine);
             lineCont[3] = QLatin1Char('-');
             QStringRef lineLeft4 = line.leftRef(4);
    -- 
    cgit v1.2.3
    
    
    From c7e6407f84eb51db64871a001dc44010d822061c Mon Sep 17 00:00:00 2001
    From: Edward Welbourne 
    Date: Wed, 29 May 2019 12:22:09 +0200
    Subject: Move container block-size calculations to qarraydata.cpp
    
    These were in qbytearray.cpp, which doesn't use them, is big and I
    intend to move it to a different directory than the header,
    qtools_p.h, that declares them. So move them to a small file that does
    use them.
    
    Change-Id: I5a4684f8c7628e617546019cc3f01d92d829f085
    Reviewed-by: Thiago Macieira 
    ---
     src/corelib/tools/qarraydata.cpp | 105 ++++++++++++++++++++++++++++++++++++++-
     src/corelib/tools/qbytearray.cpp | 102 +------------------------------------
     src/corelib/tools/qtools_p.h     |   4 +-
     3 files changed, 107 insertions(+), 104 deletions(-)
    
    (limited to 'src')
    
    diff --git a/src/corelib/tools/qarraydata.cpp b/src/corelib/tools/qarraydata.cpp
    index bcc0688a91..88d8b8244d 100644
    --- a/src/corelib/tools/qarraydata.cpp
    +++ b/src/corelib/tools/qarraydata.cpp
    @@ -1,6 +1,6 @@
     /****************************************************************************
     **
    -** Copyright (C) 2016 The Qt Company Ltd.
    +** Copyright (C) 2019 The Qt Company Ltd.
     ** Copyright (C) 2016 Intel Corporation.
     ** Contact: https://www.qt.io/licensing/
     **
    @@ -41,11 +41,114 @@
     #include 
     #include 
     #include 
    +#include 
     
     #include 
     
     QT_BEGIN_NAMESPACE
     
    +/*
    + * This pair of functions is declared in qtools_p.h and is used by the Qt
    + * containers to allocate memory and grow the memory block during append
    + * operations.
    + *
    + * They take size_t parameters and return size_t so they will change sizes
    + * according to the pointer width. However, knowing Qt containers store the
    + * container size and element indexes in ints, these functions never return a
    + * size larger than INT_MAX. This is done by casting the element count and
    + * memory block size to int in several comparisons: the check for negative is
    + * very fast on most platforms as the code only needs to check the sign bit.
    + *
    + * These functions return SIZE_MAX on overflow, which can be passed to malloc()
    + * and will surely cause a NULL return (there's no way you can allocate a
    + * memory block the size of your entire VM space).
    + */
    +
    +/*!
    +    \internal
    +    \since 5.7
    +
    +    Returns the memory block size for a container containing \a elementCount
    +    elements, each of \a elementSize bytes, plus a header of \a headerSize
    +    bytes. That is, this function returns \c
    +      {elementCount * elementSize + headerSize}
    +
    +    but unlike the simple calculation, it checks for overflows during the
    +    multiplication and the addition.
    +
    +    Both \a elementCount and \a headerSize can be zero, but \a elementSize
    +    cannot.
    +
    +    This function returns SIZE_MAX (~0) on overflow or if the memory block size
    +    would not fit an int.
    +*/
    +size_t qCalculateBlockSize(size_t elementCount, size_t elementSize, size_t headerSize) noexcept
    +{
    +    unsigned count = unsigned(elementCount);
    +    unsigned size = unsigned(elementSize);
    +    unsigned header = unsigned(headerSize);
    +    Q_ASSERT(elementSize);
    +    Q_ASSERT(size == elementSize);
    +    Q_ASSERT(header == headerSize);
    +
    +    if (Q_UNLIKELY(count != elementCount))
    +        return std::numeric_limits::max();
    +
    +    unsigned bytes;
    +    if (Q_UNLIKELY(mul_overflow(size, count, &bytes)) ||
    +            Q_UNLIKELY(add_overflow(bytes, header, &bytes)))
    +        return std::numeric_limits::max();
    +    if (Q_UNLIKELY(int(bytes) < 0))     // catches bytes >= 2GB
    +        return std::numeric_limits::max();
    +
    +    return bytes;
    +}
    +
    +/*!
    +    \internal
    +    \since 5.7
    +
    +    Returns the memory block size and the number of elements that will fit in
    +    that block for a container containing \a elementCount elements, each of \a
    +    elementSize bytes, plus a header of \a headerSize bytes. This function
    +    assumes the container will grow and pre-allocates a growth factor.
    +
    +    Both \a elementCount and \a headerSize can be zero, but \a elementSize
    +    cannot.
    +
    +    This function returns SIZE_MAX (~0) on overflow or if the memory block size
    +    would not fit an int.
    +
    +    \note The memory block may contain up to \a elementSize - 1 bytes more than
    +    needed.
    +*/
    +CalculateGrowingBlockSizeResult
    +qCalculateGrowingBlockSize(size_t elementCount, size_t elementSize, size_t headerSize) noexcept
    +{
    +    CalculateGrowingBlockSizeResult result = {
    +        std::numeric_limits::max(),std::numeric_limits::max()
    +    };
    +
    +    unsigned bytes = unsigned(qCalculateBlockSize(elementCount, elementSize, headerSize));
    +    if (int(bytes) < 0)     // catches std::numeric_limits::max()
    +        return result;
    +
    +    unsigned morebytes = qNextPowerOfTwo(bytes);
    +    if (Q_UNLIKELY(int(morebytes) < 0)) {
    +        // catches morebytes == 2GB
    +        // grow by half the difference between bytes and morebytes
    +        bytes += (morebytes - bytes) / 2;
    +    } else {
    +        bytes = morebytes;
    +    }
    +
    +    result.elementCount = (bytes - unsigned(headerSize)) / unsigned(elementSize);
    +    result.size = bytes;
    +    return result;
    +}
    +
    +// End of qtools_p.h implementation
    +
     QT_WARNING_PUSH
     QT_WARNING_DISABLE_GCC("-Wmissing-field-initializers")
     
    diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp
    index 9816b5cb32..5c2af7e058 100644
    --- a/src/corelib/tools/qbytearray.cpp
    +++ b/src/corelib/tools/qbytearray.cpp
    @@ -1,6 +1,6 @@
     /****************************************************************************
     **
    -** Copyright (C) 2016 The Qt Company Ltd.
    +** Copyright (C) 2019 The Qt Company Ltd.
     ** Copyright (C) 2016 Intel Corporation.
     ** Contact: https://www.qt.io/licensing/
     **
    @@ -130,106 +130,6 @@ int qFindByteArray(
         const char *haystack0, int haystackLen, int from,
         const char *needle0, int needleLen);
     
    -/*
    - * This pair of functions is declared in qtools_p.h and is used by the Qt
    - * containers to allocate memory and grow the memory block during append
    - * operations.
    - *
    - * They take size_t parameters and return size_t so they will change sizes
    - * according to the pointer width. However, knowing Qt containers store the
    - * container size and element indexes in ints, these functions never return a
    - * size larger than INT_MAX. This is done by casting the element count and
    - * memory block size to int in several comparisons: the check for negative is
    - * very fast on most platforms as the code only needs to check the sign bit.
    - *
    - * These functions return SIZE_MAX on overflow, which can be passed to malloc()
    - * and will surely cause a NULL return (there's no way you can allocate a
    - * memory block the size of your entire VM space).
    - */
    -
    -/*!
    -    \internal
    -    \since 5.7
    -
    -    Returns the memory block size for a container containing \a elementCount
    -    elements, each of \a elementSize bytes, plus a header of \a headerSize
    -    bytes. That is, this function returns \c
    -      {elementCount * elementSize + headerSize}
    -
    -    but unlike the simple calculation, it checks for overflows during the
    -    multiplication and the addition.
    -
    -    Both \a elementCount and \a headerSize can be zero, but \a elementSize
    -    cannot.
    -
    -    This function returns SIZE_MAX (~0) on overflow or if the memory block size
    -    would not fit an int.
    -*/
    -size_t qCalculateBlockSize(size_t elementCount, size_t elementSize, size_t headerSize) noexcept
    -{
    -    unsigned count = unsigned(elementCount);
    -    unsigned size = unsigned(elementSize);
    -    unsigned header = unsigned(headerSize);
    -    Q_ASSERT(elementSize);
    -    Q_ASSERT(size == elementSize);
    -    Q_ASSERT(header == headerSize);
    -
    -    if (Q_UNLIKELY(count != elementCount))
    -        return std::numeric_limits::max();
    -
    -    unsigned bytes;
    -    if (Q_UNLIKELY(mul_overflow(size, count, &bytes)) ||
    -            Q_UNLIKELY(add_overflow(bytes, header, &bytes)))
    -        return std::numeric_limits::max();
    -    if (Q_UNLIKELY(int(bytes) < 0))     // catches bytes >= 2GB
    -        return std::numeric_limits::max();
    -
    -    return bytes;
    -}
    -
    -/*!
    -    \internal
    -    \since 5.7
    -
    -    Returns the memory block size and the number of elements that will fit in
    -    that block for a container containing \a elementCount elements, each of \a
    -    elementSize bytes, plus a header of \a headerSize bytes. This function
    -    assumes the container will grow and pre-allocates a growth factor.
    -
    -    Both \a elementCount and \a headerSize can be zero, but \a elementSize
    -    cannot.
    -
    -    This function returns SIZE_MAX (~0) on overflow or if the memory block size
    -    would not fit an int.
    -
    -    \note The memory block may contain up to \a elementSize - 1 bytes more than
    -    needed.
    -*/
    -CalculateGrowingBlockSizeResult
    -qCalculateGrowingBlockSize(size_t elementCount, size_t elementSize, size_t headerSize) noexcept
    -{
    -    CalculateGrowingBlockSizeResult result = {
    -        std::numeric_limits::max(),std::numeric_limits::max()
    -    };
    -
    -    unsigned bytes = unsigned(qCalculateBlockSize(elementCount, elementSize, headerSize));
    -    if (int(bytes) < 0)     // catches std::numeric_limits::max()
    -        return result;
    -
    -    unsigned morebytes = qNextPowerOfTwo(bytes);
    -    if (Q_UNLIKELY(int(morebytes) < 0)) {
    -        // catches morebytes == 2GB
    -        // grow by half the difference between bytes and morebytes
    -        bytes += (morebytes - bytes) / 2;
    -    } else {
    -        bytes = morebytes;
    -    }
    -
    -    result.elementCount = (bytes - unsigned(headerSize)) / unsigned(elementSize);
    -    result.size = bytes;
    -    return result;
    -}
    -
     /*****************************************************************************
       Safe and portable C string functions; extensions to standard string.h
      *****************************************************************************/
    diff --git a/src/corelib/tools/qtools_p.h b/src/corelib/tools/qtools_p.h
    index b239987871..d48318b474 100644
    --- a/src/corelib/tools/qtools_p.h
    +++ b/src/corelib/tools/qtools_p.h
    @@ -1,6 +1,6 @@
     /****************************************************************************
     **
    -** Copyright (C) 2016 The Qt Company Ltd.
    +** Copyright (C) 2019 The Qt Company Ltd.
     ** Contact: https://www.qt.io/licensing/
     **
     ** This file is part of the QtCore module of the Qt Toolkit.
    @@ -96,7 +96,7 @@ struct CalculateGrowingBlockSizeResult {
         size_t elementCount;
     };
     
    -// implemented in qbytearray.cpp
    +// Implemented in qarraydata.cpp:
     size_t Q_CORE_EXPORT Q_DECL_CONST_FUNCTION
     qCalculateBlockSize(size_t elementCount, size_t elementSize, size_t headerSize = 0) noexcept;
     CalculateGrowingBlockSizeResult Q_CORE_EXPORT Q_DECL_CONST_FUNCTION
    -- 
    cgit v1.2.3
    
    
    From 325d5b58a25a2893261c2c69fc8381abc87cceac Mon Sep 17 00:00:00 2001
    From: Edward Welbourne 
    Date: Tue, 28 May 2019 17:39:14 +0200
    Subject: Regenerate Windows Time Zone ID table
    
    Re-ran util/locale_database/cldr2qtimezone.py to add new zones to the
    table.
    
    Change-Id: I70258a9abbe9815494291deff528f3c18703de40
    Reviewed-by: Thiago Macieira 
    ---
     src/corelib/tools/qtimezoneprivate_data_p.h | 2101 ++++++++++++++-------------
     1 file changed, 1102 insertions(+), 999 deletions(-)
    
    (limited to 'src')
    
    diff --git a/src/corelib/tools/qtimezoneprivate_data_p.h b/src/corelib/tools/qtimezoneprivate_data_p.h
    index 5cedac3b49..40d6c972c2 100644
    --- a/src/corelib/tools/qtimezoneprivate_data_p.h
    +++ b/src/corelib/tools/qtimezoneprivate_data_p.h
    @@ -114,8 +114,8 @@ struct QUtcData {
     // GENERATED PART STARTS HERE
     
     /*
    -    This part of the file was generated on 2017-05-23 from the
    -    Common Locale Data Repository v29 supplemental/windowsZones.xml file $Revision: 12348 $
    +    This part of the file was generated on 2019-05-28 from the
    +    Common Locale Data Repository v35.1 supplemental/windowsZones.xml file $Revision: 14742 $
     
         http://www.unicode.org/cldr/
     
    @@ -125,1027 +125,1130 @@ struct QUtcData {
     
     // Windows ID Key, Country Enum, IANA ID Index
     static const QZoneData zoneDataTable[] = {
    -    {     22,    57,     0 }, // Central Europe Standard Time / CzechRepublic
    -    {     69,   139,    14 }, // Pacific Standard Time / Mexico
    -    {     53,   188,    51 }, // Mauritius Standard Time / Seychelles
    -    {     50,   122,    63 }, // Libya Standard Time / Libya
    -    {     79,    38,    78 }, // SA Western Standard Time / Canada
    -    {     83,    35,    99 }, // South Africa Standard Time / Burundi
    -    {    102,   205,   116 }, // W. Europe Standard Time / Sweden
    -    {     89,   213,   133 }, // Tonga Standard Time / Tokelau
    -    {     77,    76,   149 }, // SA Eastern Standard Time / FrenchGuiana
    -    {     79,   215,   165 }, // SA Western Standard Time / TrinidadAndTobago
    -    {     69,    38,   187 }, // Pacific Standard Time / Canada
    -    {     97,     0,   239 }, // UTC+12 / AnyCountry
    -    {     19,    65,   250 }, // Central America Standard Time / ElSalvador
    -    {     82,   101,   270 }, // Singapore Standard Time / Indonesia
    -    {     37,   248,   284 }, // FLE Standard Time / AlandIslands
    -    {     16,     0,   301 }, // Cape Verde Standard Time / AnyCountry
    -    {     97,   220,   311 }, // UTC+12 / Tuvalu
    -    {     79,   182,   328 }, // SA Western Standard Time / SaintVincentAndTheGrenadines
    -    {     83,   179,   347 }, // South Africa Standard Time / Rwanda
    -    {    102,   125,   361 }, // W. Europe Standard Time / Luxembourg
    -    {     41,    34,   379 }, // Greenwich Standard Time / BurkinaFaso
    -    {     20,   116,   398 }, // Central Asia Standard Time / Kyrgyzstan
    -    {    101,   216,   411 }, // W. Central Africa Standard Time / Tunisia
    -    {    101,    79,   424 }, // W. Central Africa Standard Time / Gabon
    -    {     19,    96,   442 }, // Central America Standard Time / Honduras
    -    {     81,    36,   462 }, // SE Asia Standard Time / Cambodia
    -    {     82,   170,   478 }, // Singapore Standard Time / Philippines
    -    {    101,    41,   490 }, // W. Central Africa Standard Time / CentralAfricanRepublic
    -    {      5,   103,   504 }, // Arabic Standard Time / Iraq
    -    {     72,    21,   517 }, // Romance Standard Time / Belgium
    -    {     74,   178,   533 }, // Russia Time Zone 10 / Russia
    -    {     20,    44,   552 }, // Central Asia Standard Time / China
    -    {      3,    17,   564 }, // Arab Standard Time / Bahrain
    -    {     88,    62,   577 }, // Tokyo Standard Time / EastTimor
    -    {     37,    68,   587 }, // FLE Standard Time / Estonia
    -    {     41,   136,   602 }, // Greenwich Standard Time / Mauritania
    -    {     83,    49,   620 }, // South Africa Standard Time / CongoKinshasa
    -    {     72,    74,   638 }, // Romance Standard Time / France
    -    {     35,   178,   651 }, // Ekaterinburg Standard Time / Russia
    -    {     32,    16,   670 }, // Eastern Standard Time / Bahamas
    -    {     94,    30,   685 }, // UTC-02 / Brazil
    -    {     12,    30,   701 }, // Bahia Standard Time / Brazil
    -    {     82,     0,   715 }, // Singapore Standard Time / AnyCountry
    -    {     29,   201,   725 }, // E. Africa Standard Time / Sudan
    -    {     24,   229,   741 }, // Central Pacific Standard Time / Vanuatu
    -    {     55,   227,   755 }, // Montevideo Standard Time / Uruguay
    -    {     79,   233,   774 }, // SA Western Standard Time / BritishVirginIslands
    -    {     29,   221,   790 }, // E. Africa Standard Time / Uganda
    -    {    101,     6,   805 }, // W. Central Africa Standard Time / Angola
    -    {     68,   141,   819 }, // E. Europe Standard Time / Moldova
    -    {     51,   112,   835 }, // Line Islands Standard Time / Kiribati
    -    {     89,     0,   854 }, // Tonga Standard Time / AnyCountry
    -    {     79,    61,   865 }, // SA Western Standard Time / DominicanRepublic
    -    {     39,    75,   887 }, // GMT Standard Time / Guernsey
    -    {     37,   222,   903 }, // FLE Standard Time / Ukraine
    -    {     83,    28,   949 }, // South Africa Standard Time / Botswana
    -    {     82,   130,   965 }, // Singapore Standard Time / Malaysia
    -    {     95,     4,   996 }, // UTC-11 / AmericanSamoa
    -    {     41,   189,  1014 }, // Greenwich Standard Time / SierraLeone
    -    {     29,   194,  1030 }, // E. Africa Standard Time / Somalia
    -    {     94,   196,  1047 }, // UTC-02 / SouthGeorgiaAndTheSouthSandwichIslands
    -    {     96,     0,  1070 }, // UTC / AnyCountry
    -    {    101,    37,  1078 }, // W. Central Africa Standard Time / Cameroon
    -    {     13,    25,  1092 }, // Bangladesh Standard Time / Bhutan
    -    {    102,   151,  1105 }, // W. Europe Standard Time / Netherlands
    -    {     37,   118,  1122 }, // FLE Standard Time / Latvia
    -    {     29,    48,  1134 }, // E. Africa Standard Time / Comoros
    -    {     60,   178,  1148 }, // N. Central Asia Standard Time / Russia
    -    {     81,   117,  1175 }, // SE Asia Standard Time / Laos
    -    {     22,   242,  1190 }, // Central Europe Standard Time / Montenegro
    -    {     37,    33,  1207 }, // FLE Standard Time / Bulgaria
    -    {     11,   173,  1220 }, // Azores Standard Time / Portugal
    -    {     97,   149,  1236 }, // UTC+12 / Nauru
    -    {     83,   146,  1250 }, // South Africa Standard Time / Mozambique
    -    {    102,    82,  1264 }, // W. Europe Standard Time / Germany
    -    {     79,   255,  1294 }, // SA Western Standard Time / Bonaire
    -    {     24,   153,  1313 }, // Central Pacific Standard Time / NewCaledonia
    -    {     45,   102,  1328 }, // Iran Standard Time / Iran
    -    {     13,    18,  1340 }, // Bangladesh Standard Time / Bangladesh
    -    {     69,   225,  1351 }, // Pacific Standard Time / UnitedStates
    -    {    102,   142,  1371 }, // W. Europe Standard Time / Monaco
    -    {     29,   128,  1385 }, // E. Africa Standard Time / Madagascar
    -    {     65,   178,  1405 }, // North Asia East Standard Time / Russia
    -    {     20,     8,  1418 }, // Central Asia Standard Time / Antarctica
    -    {     22,     2,  1436 }, // Central Europe Standard Time / Albania
    -    {     79,    87,  1450 }, // SA Western Standard Time / Grenada
    -    {     81,     0,  1466 }, // SE Asia Standard Time / AnyCountry
    -    {     39,   173,  1476 }, // GMT Standard Time / Portugal
    -    {    103,   228,  1507 }, // West Asia Standard Time / Uzbekistan
    -    {     58,   139,  1536 }, // Mountain Standard Time / Mexico
    -    {     83,   129,  1552 }, // South Africa Standard Time / Malawi
    -    {     78,   107,  1568 }, // SA Pacific Standard Time / Jamaica
    -    {     41,    91,  1584 }, // Greenwich Standard Time / Guinea
    -    {    101,    49,  1599 }, // W. Central Africa Standard Time / CongoKinshasa
    -    {     43,   226,  1615 }, // Hawaiian Standard Time / UnitedStatesMinorOutlyingIslands
    -    {     77,     8,  1632 }, // SA Eastern Standard Time / Antarctica
    -    {     97,   235,  1651 }, // UTC+12 / WallisAndFutunaIslands
    -    {     81,   232,  1666 }, // SE Asia Standard Time / Vietnam
    -    {     34,    64,  1678 }, // Egypt Standard Time / Egypt
    -    {    102,   106,  1691 }, // W. Europe Standard Time / Italy
    -    {     79,   256,  1703 }, // SA Western Standard Time / SintMaarten
    -    {     59,   147,  1725 }, // Myanmar Standard Time / Myanmar
    -    {     78,   166,  1738 }, // SA Pacific Standard Time / Panama
    -    {     56,   236,  1753 }, // Morocco Standard Time / WesternSahara
    -    {     24,   193,  1769 }, // Central Pacific Standard Time / SolomonIslands
    -    {     48,   178,  1789 }, // Kaliningrad Standard Time / Russia
    -    {     47,   109,  1808 }, // Jordan Standard Time / Jordan
    -    {     42,   177,  1819 }, // GTB Standard Time / Romania
    -    {     41,    92,  1836 }, // Greenwich Standard Time / GuineaBissau
    -    {    102,   184,  1850 }, // W. Europe Standard Time / SanMarino
    -    {    103,   209,  1868 }, // West Asia Standard Time / Tajikistan
    -    {     75,   178,  1882 }, // Russia Time Zone 11 / Russia
    -    {    101,   157,  1909 }, // W. Central Africa Standard Time / Nigeria
    -    {     79,   152,  1922 }, // SA Western Standard Time / CuraSao
    -    {     57,   139,  1938 }, // Mountain Standard Time (Mexico) / Mexico
    -    {      4,   162,  1973 }, // Arabian Standard Time / Oman
    -    {     78,   169,  1985 }, // SA Pacific Standard Time / Peru
    -    {    102,   206,  1998 }, // W. Europe Standard Time / Switzerland
    -    {     41,    99,  2012 }, // Greenwich Standard Time / Iceland
    -    {     33,   139,  2031 }, // Eastern Standard Time (Mexico) / Mexico
    -    {     58,   225,  2046 }, // Mountain Standard Time / UnitedStates
    -    {    100,     8,  2075 }, // W. Australia Standard Time / Antarctica
    -    {     79,    30,  2092 }, // SA Western Standard Time / Brazil
    -    {    101,    23,  2145 }, // W. Central Africa Standard Time / Benin
    -    {     78,    43,  2163 }, // SA Pacific Standard Time / Chile
    -    {    104,     0,  2178 }, // West Pacific Standard Time / AnyCountry
    -    {     79,   181,  2189 }, // SA Western Standard Time / SaintLucia
    -    {     27,   126,  2206 }, // China Standard Time / Macau
    -    {    101,    66,  2217 }, // W. Central Africa Standard Time / EquatorialGuinea
    -    {     43,    51,  2231 }, // Hawaiian Standard Time / CookIslands
    -    {     41,    80,  2249 }, // Greenwich Standard Time / Gambia
    -    {     51,     0,  2263 }, // Line Islands Standard Time / AnyCountry
    -    {     52,   178,  2274 }, // Magadan Standard Time / Russia
    -    {     22,   191,  2287 }, // Central Europe Standard Time / Slovakia
    -    {    102,     5,  2305 }, // W. Europe Standard Time / Andorra
    -    {     81,   211,  2320 }, // SE Asia Standard Time / Thailand
    -    {    103,     0,  2333 }, // West Asia Standard Time / AnyCountry
    -    {     24,   167,  2343 }, // Central Pacific Standard Time / PapuaNewGuinea
    -    {    102,   230,  2364 }, // W. Europe Standard Time / VaticanCityState
    -    {     58,    38,  2379 }, // Mountain Standard Time / Canada
    -    {     77,   202,  2453 }, // SA Eastern Standard Time / Suriname
    -    {      9,    13,  2472 }, // AUS Eastern Standard Time / Australia
    -    {     29,   210,  2509 }, // E. Africa Standard Time / Tanzania
    -    {     58,     0,  2530 }, // Mountain Standard Time / AnyCountry
    -    {     83,   120,  2538 }, // South Africa Standard Time / Lesotho
    -    {     97,   134,  2552 }, // UTC+12 / MarshallIslands
    -    {     29,   111,  2585 }, // E. Africa Standard Time / Kenya
    -    {    103,   218,  2600 }, // West Asia Standard Time / Turkmenistan
    -    {     27,    97,  2614 }, // China Standard Time / HongKong
    -    {     29,     0,  2629 }, // E. Africa Standard Time / AnyCountry
    -    {     19,    22,  2639 }, // Central America Standard Time / Belize
    -    {     31,    30,  2654 }, // E. South America Standard Time / Brazil
    -    {     72,   197,  2672 }, // Romance Standard Time / Spain
    -    {     81,   101,  2699 }, // SE Asia Standard Time / Indonesia
    -    {     88,     0,  2727 }, // Tokyo Standard Time / AnyCountry
    -    {      2,   225,  2737 }, // Alaskan Standard Time / UnitedStates
    -    {     72,    58,  2832 }, // Romance Standard Time / Denmark
    -    {     63,     8,  2850 }, // New Zealand Standard Time / Antarctica
    -    {      3,   175,  2869 }, // Arab Standard Time / Qatar
    -    {     79,   245,  2880 }, // SA Western Standard Time / Saint Martin
    -    {     79,    19,  2896 }, // SA Western Standard Time / Barbados
    -    {     97,   226,  2913 }, // UTC+12 / UnitedStatesMinorOutlyingIslands
    -    {     37,    73,  2926 }, // FLE Standard Time / Finland
    -    {     29,   138,  2942 }, // E. Africa Standard Time / Mayotte
    -    {     39,    71,  2957 }, // GMT Standard Time / FaroeIslands
    -    {     78,    38,  2973 }, // SA Pacific Standard Time / Canada
    -    {     43,     0,  2995 }, // Hawaiian Standard Time / AnyCountry
    -    {     23,    27,  3006 }, // Central European Standard Time / BosniaAndHerzegowina
    -    {     38,    81,  3022 }, // Georgian Standard Time / Georgia
    -    {     95,     0,  3035 }, // UTC-11 / AnyCountry
    -    {     24,    13,  3046 }, // Central Pacific Standard Time / Australia
    -    {    104,   167,  3067 }, // West Pacific Standard Time / PapuaNewGuinea
    -    {     71,   168,  3088 }, // Paraguay Standard Time / Paraguay
    -    {     43,    77,  3105 }, // Hawaiian Standard Time / FrenchPolynesia
    -    {     41,   212,  3120 }, // Greenwich Standard Time / Togo
    -    {     39,   197,  3132 }, // GMT Standard Time / Spain
    -    {     83,   195,  3148 }, // South Africa Standard Time / SouthAfrica
    -    {     18,    13,  3168 }, // Cen. Australia Standard Time / Australia
    -    {    104,   160,  3209 }, // West Pacific Standard Time / NorthernMarianaIslands
    -    {     77,    70,  3224 }, // SA Eastern Standard Time / FalklandIslands
    -    {     42,    56,  3241 }, // GTB Standard Time / Cyprus
    -    {      4,   223,  3254 }, // Arabian Standard Time / UnitedArabEmirates
    -    {    103,    78,  3265 }, // West Asia Standard Time / FrenchSouthernTerritories
    -    {    101,    42,  3282 }, // W. Central Africa Standard Time / Chad
    -    {     23,   127,  3298 }, // Central European Standard Time / Macedonia
    -    {      3,   237,  3312 }, // Arab Standard Time / Yemen
    -    {     80,   183,  3322 }, // Samoa Standard Time / Samoa
    -    {     43,   225,  3335 }, // Hawaiian Standard Time / UnitedStates
    -    {     28,     0,  3352 }, // Dateline Standard Time / AnyCountry
    -    {     93,   139,  3363 }, // US Mountain Standard Time / Mexico
    -    {     64,    38,  3382 }, // Newfoundland Standard Time / Canada
    -    {     63,   154,  3399 }, // New Zealand Standard Time / NewZealand
    -    {     76,   178,  3416 }, // Russian Standard Time / Russia
    -    {     82,   190,  3465 }, // Singapore Standard Time / Singapore
    -    {      1,     1,  3480 }, // Afghanistan Standard Time / Afghanistan
    -    {    102,   133,  3491 }, // W. Europe Standard Time / Malta
    -    {     79,    12,  3504 }, // SA Western Standard Time / Aruba
    -    {     25,   139,  3518 }, // Central Standard Time (Mexico) / Mexico
    -    {     39,   251,  3594 }, // GMT Standard Time / IsleOfMan
    -    {    102,   123,  3613 }, // W. Europe Standard Time / Liechtenstein
    -    {     77,    30,  3626 }, // SA Eastern Standard Time / Brazil
    -    {     49,   114,  3723 }, // Korea Standard Time / SouthKorea
    -    {     79,    88,  3734 }, // SA Western Standard Time / Guadeloupe
    -    {     94,     0,  3753 }, // UTC-02 / AnyCountry
    -    {     59,    46,  3763 }, // Myanmar Standard Time / CocosIslands
    -    {    102,   203,  3776 }, // W. Europe Standard Time / SvalbardAndJanMayenIslands
    -    {     29,    69,  3796 }, // E. Africa Standard Time / Ethiopia
    -    {     73,   178,  3815 }, // Russia Time Zone 3 / Russia
    -    {     83,   240,  3829 }, // South Africa Standard Time / Zimbabwe
    -    {    100,    13,  3843 }, // W. Australia Standard Time / Australia
    -    {    101,     0,  3859 }, // W. Central Africa Standard Time / AnyCountry
    -    {     32,    55,  3869 }, // Eastern Standard Time / Cuba
    -    {     56,   145,  3884 }, // Morocco Standard Time / Morocco
    -    {     17,    11,  3902 }, // Caucasus Standard Time / Armenia
    -    {      7,    24,  3915 }, // Atlantic Standard Time / Bermuda
    -    {     86,   208,  3932 }, // Taipei Standard Time / Taiwan
    -    {     20,     0,  3944 }, // Central Asia Standard Time / AnyCountry
    -    {     40,    86,  3954 }, // Greenland Standard Time / Greenland
    -    {     23,   172,  3970 }, // Central European Standard Time / Poland
    -    {     89,   214,  3984 }, // Tonga Standard Time / Tonga
    -    {     20,   110,  4002 }, // Central Asia Standard Time / Kazakhstan
    -    {     81,     8,  4029 }, // SE Asia Standard Time / Antarctica
    -    {     54,   119,  4046 }, // Middle East Standard Time / Lebanon
    -    {     19,    90,  4058 }, // Central America Standard Time / Guatemala
    -    {     70,   163,  4076 }, // Pakistan Standard Time / Pakistan
    -    {     41,    83,  4089 }, // Greenwich Standard Time / Ghana
    -    {     79,   174,  4102 }, // SA Western Standard Time / PuertoRico
    -    {     79,    26,  4122 }, // SA Western Standard Time / Bolivia
    -    {     32,   225,  4137 }, // Eastern Standard Time / UnitedStates
    -    {     85,   207,  4294 }, // Syria Standard Time / Syria
    -    {     97,   112,  4308 }, // UTC+12 / Kiribati
    -    {     79,     0,  4323 }, // SA Western Standard Time / AnyCountry
    -    {     78,    47,  4333 }, // SA Pacific Standard Time / Colombia
    -    {     16,    39,  4348 }, // Cape Verde Standard Time / CapeVerde
    -    {      8,    13,  4368 }, // AUS Central Standard Time / Australia
    -    {    106,   113,  4385 }, // North Korea Standard Time / NorthKorea
    -    {     10,    15,  4400 }, // Azerbaijan Standard Time / Azerbaijan
    -    {    102,    84,  4410 }, // W. Europe Standard Time / Gibraltar
    -    {     46,   105,  4427 }, // Israel Standard Time / Israel
    -    {     22,   192,  4442 }, // Central Europe Standard Time / Slovenia
    -    {     24,   159,  4459 }, // Central Pacific Standard Time / NorfolkIsland
    -    {     82,    32,  4475 }, // Singapore Standard Time / Brunei
    -    {    101,    50,  4487 }, // W. Central Africa Standard Time / CongoBrazzaville
    -    {     62,   150,  4506 }, // Nepal Standard Time / Nepal
    -    {     44,   100,  4520 }, // India Standard Time / India
    -    {     79,     9,  4534 }, // SA Western Standard Time / AntiguaAndBarbuda
    -    {     39,   252,  4550 }, // GMT Standard Time / Jersey
    -    {     79,   144,  4564 }, // SA Western Standard Time / Montserrat
    -    {     93,     0,  4583 }, // US Mountain Standard Time / AnyCountry
    -    {     79,    93,  4593 }, // SA Western Standard Time / Guyana
    -    {     41,   187,  4608 }, // Greenwich Standard Time / Senegal
    -    {    102,   161,  4621 }, // W. Europe Standard Time / Norway
    -    {     42,    85,  4633 }, // GTB Standard Time / Greece
    -    {      3,   115,  4647 }, // Arab Standard Time / Kuwait
    -    {     24,   140,  4659 }, // Central Pacific Standard Time / Micronesia
    -    {     19,    52,  4689 }, // Central America Standard Time / CostaRica
    -    {     79,    60,  4708 }, // SA Western Standard Time / Dominica
    -    {     83,   204,  4725 }, // South Africa Standard Time / Swaziland
    -    {     79,   135,  4740 }, // SA Western Standard Time / Martinique
    -    {     53,   176,  4759 }, // Mauritius Standard Time / Reunion
    -    {     19,     0,  4774 }, // Central America Standard Time / AnyCountry
    -    {     90,   217,  4784 }, // Turkey Standard Time / Turkey
    -    {     66,   178,  4800 }, // North Asia Standard Time / Russia
    -    {     41,    53,  4835 }, // Greenwich Standard Time / IvoryCoast
    -    {     78,    30,  4850 }, // SA Pacific Standard Time / Brazil
    -    {     26,     0,  4886 }, // Central Standard Time / AnyCountry
    -    {     93,   225,  4894 }, // US Mountain Standard Time / UnitedStates
    -    {     15,    38,  4910 }, // Canada Central Standard Time / Canada
    -    {     78,     0,  4947 }, // SA Pacific Standard Time / AnyCountry
    -    {    103,     8,  4957 }, // West Asia Standard Time / Antarctica
    -    {    103,   131,  4975 }, // West Asia Standard Time / Maldives
    -    {     22,   243,  4991 }, // Central Europe Standard Time / Serbia
    -    {     29,    67,  5007 }, // E. Africa Standard Time / Eritrea
    -    {     93,    38,  5021 }, // US Mountain Standard Time / Canada
    -    {     22,    98,  5078 }, // Central Europe Standard Time / Hungary
    -    {     61,   148,  5094 }, // Namibia Standard Time / Namibia
    -    {     88,   101,  5110 }, // Tokyo Standard Time / Indonesia
    -    {     30,    13,  5124 }, // E. Australia Standard Time / Australia
    -    {      4,     0,  5162 }, // Arabian Standard Time / AnyCountry
    -    {     98,   231,  5172 }, // Venezuela Standard Time / Venezuela
    -    {     29,     8,  5188 }, // E. Africa Standard Time / Antarctica
    -    {     23,    54,  5205 }, // Central European Standard Time / Croatia
    -    {      6,    10,  5219 }, // Argentina Standard Time / Argentina
    -    {     67,     8,  5492 }, // Pacific SA Standard Time / Antarctica
    -    {     32,    38,  5510 }, // Eastern Standard Time / Canada
    -    {     41,   132,  5615 }, // Greenwich Standard Time / Mali
    -    {      3,   186,  5629 }, // Arab Standard Time / SaudiArabia
    -    {    104,   140,  5641 }, // West Pacific Standard Time / Micronesia
    -    {     88,   108,  5654 }, // Tokyo Standard Time / Japan
    -    {     89,   112,  5665 }, // Tonga Standard Time / Kiribati
    -    {     39,   224,  5683 }, // GMT Standard Time / UnitedKingdom
    -    {     92,   225,  5697 }, // US Eastern Standard Time / UnitedStates
    -    {     84,   198,  5764 }, // Sri Lanka Standard Time / SriLanka
    -    {     26,    38,  5777 }, // Central Standard Time / Canada
    -    {     29,    59,  5852 }, // E. Africa Standard Time / Djibouti
    -    {      7,    38,  5868 }, // Atlantic Standard Time / Canada
    -    {     41,   185,  5936 }, // Greenwich Standard Time / SaoTomeAndPrincipe
    -    {     79,   234,  5952 }, // SA Western Standard Time / UnitedStatesVirginIslands
    -    {     83,   239,  5970 }, // South Africa Standard Time / Zambia
    -    {     32,    94,  5984 }, // Eastern Standard Time / Haiti
    -    {    101,   156,  6007 }, // W. Central Africa Standard Time / Niger
    -    {     77,     0,  6021 }, // SA Eastern Standard Time / AnyCountry
    -    {    101,     3,  6031 }, // W. Central Africa Standard Time / Algeria
    -    {     78,    63,  6046 }, // SA Pacific Standard Time / Ecuador
    -    {     20,    31,  6064 }, // Central Asia Standard Time / BritishIndianOceanTerritory
    -    {     27,    44,  6078 }, // China Standard Time / China
    -    {     21,    30,  6092 }, // Central Brazilian Standard Time / Brazil
    -    {     95,   226,  6128 }, // UTC-11 / UnitedStatesMinorOutlyingIslands
    -    {     32,     0,  6143 }, // Eastern Standard Time / AnyCountry
    -    {     81,    45,  6151 }, // SE Asia Standard Time / ChristmasIsland
    -    {     19,    63,  6168 }, // Central America Standard Time / Ecuador
    -    {     79,     7,  6186 }, // SA Western Standard Time / Anguilla
    -    {     78,    40,  6203 }, // SA Pacific Standard Time / CaymanIslands
    -    {     79,   180,  6218 }, // SA Western Standard Time / SaintKittsAndNevis
    -    {     67,    43,  6235 }, // Pacific SA Standard Time / Chile
    -    {     88,   164,  6252 }, // Tokyo Standard Time / Palau
    -    {    105,   178,  6266 }, // Yakutsk Standard Time / Russia
    -    {     37,   124,  6304 }, // FLE Standard Time / Lithuania
    -    {     41,   121,  6319 }, // Greenwich Standard Time / Liberia
    -    {    104,    89,  6335 }, // West Pacific Standard Time / Guam
    -    {     96,    86,  6348 }, // UTC / Greenland
    -    {     36,    72,  6369 }, // Fiji Standard Time / Fiji
    -    {     19,   155,  6382 }, // Central America Standard Time / Nicaragua
    -    {     11,    86,  6398 }, // Azores Standard Time / Greenland
    -    {     79,   244,  6419 }, // SA Western Standard Time / Saint Barthelemy
    -    {     69,     0,  6441 }, // Pacific Standard Time / AnyCountry
    -    {     79,   219,  6449 }, // SA Western Standard Time / TurksAndCaicosIslands
    -    {    103,   110,  6468 }, // West Asia Standard Time / Kazakhstan
    -    {     26,   225,  6501 }, // Central Standard Time / UnitedStates
    -    {     26,   139,  6669 }, // Central Standard Time / Mexico
    -    {      7,    86,  6687 }, // Atlantic Standard Time / Greenland
    -    {     24,     0,  6701 }, // Central Pacific Standard Time / AnyCountry
    -    {     41,   199,  6712 }, // Greenwich Standard Time / SaintHelena
    -    {     95,   158,  6731 }, // UTC-11 / Niue
    -    {     53,   137,  6744 }, // Mauritius Standard Time / Mauritius
    -    {     91,   143,  6761 }, // Ulaanbaatar Standard Time / Mongolia
    -    {     83,     0,  6794 }, // South Africa Standard Time / AnyCountry
    -    {     14,    20,  6804 }, // Belarus Standard Time / Belarus
    -    {     29,   254,  6817 }, // E. Africa Standard Time / SouthSudan
    -    {     87,    13,  6829 }, // Tasmania Standard Time / Australia
    -    {     99,   178,  6863 }, // Vladivostok Standard Time / Russia
    -    {    104,     8,  6908 }, // West Pacific Standard Time / Antarctica
    -    {     39,   104,  6934 }, // GMT Standard Time / Ireland
    -    {    102,    14,  6948 }, // W. Europe Standard Time / Austria
    +    {    131,   143,     0 }, // W. Mongolia Standard Time / Mongolia
    +    {    124,   112,    10 }, // UTC+12 / Kiribati
    +    {     52,    94,    25 }, // Haiti Standard Time / Haiti
    +    {     32,    44,    48 }, // China Standard Time / China
    +    {     95,   244,    62 }, // SA Western Standard Time / Saint Barthelemy
    +    {     25,   116,    84 }, // Central Asia Standard Time / Kyrgyzstan
    +    {     36,     8,    97 }, // E. Africa Standard Time / Antarctica
    +    {     33,   154,   114 }, // Chatham Islands Standard Time / New Zealand
    +    {     95,   144,   130 }, // SA Western Standard Time / Montserrat
    +    {     37,    13,   149 }, // E. Australia Standard Time / Australia
    +    {     61,     0,   187 }, // Line Islands Standard Time / AnyCountry
    +    {    132,   218,   198 }, // West Asia Standard Time / Turkmenistan
    +    {    122,    30,   212 }, // UTC-02 / Brazil
    +    {     24,    52,   228 }, // Central America Standard Time / Costa Rica
    +    {     36,    67,   247 }, // E. Africa Standard Time / Eritrea
    +    {    128,     8,   261 }, // W. Australia Standard Time / Antarctica
    +    {    101,   101,   278 }, // SE Asia Standard Time / Indonesia
    +    {     93,     8,   306 }, // SA Eastern Standard Time / Antarctica
    +    {      4,   178,   325 }, // Altai Standard Time / Russia
    +    {     95,   256,   338 }, // SA Western Standard Time / Sint Maarten
    +    {     95,    60,   360 }, // SA Western Standard Time / Dominica
    +    {    134,   167,   377 }, // West Pacific Standard Time / Papua New Guinea
    +    {     13,    13,   398 }, // AUS Eastern Standard Time / Australia
    +    {     69,   236,   435 }, // Morocco Standard Time / Western Sahara
    +    {     39,    30,   451 }, // E. South America Standard Time / Brazil
    +    {    124,   134,   469 }, // UTC+12 / Marshall Islands
    +    {    125,   112,   502 }, // UTC+13 / Kiribati
    +    {    103,   146,   520 }, // South Africa Standard Time / Mozambique
    +    {     94,    30,   534 }, // SA Pacific Standard Time / Brazil
    +    {     88,    74,   570 }, // Romance Standard Time / France
    +    {     71,    38,   583 }, // Mountain Standard Time / Canada
    +    {     72,   147,   657 }, // Myanmar Standard Time / Myanmar
    +    {     26,    30,   670 }, // Central Brazilian Standard Time / Brazil
    +    {    130,   123,   706 }, // W. Europe Standard Time / Liechtenstein
    +    {     46,    73,   719 }, // FLE Standard Time / Finland
    +    {     93,    70,   735 }, // SA Eastern Standard Time / Falkland Islands
    +    {     78,   159,   752 }, // Norfolk Standard Time / Norfolk Island
    +    {     53,     0,   768 }, // Hawaiian Standard Time / AnyCountry
    +    {     28,    54,   779 }, // Central European Standard Time / Croatia
    +    {     75,   150,   793 }, // Nepal Standard Time / Nepal
    +    {     46,    33,   807 }, // FLE Standard Time / Bulgaria
    +    {      6,   162,   820 }, // Arabian Standard Time / Oman
    +    {    132,   131,   832 }, // West Asia Standard Time / Maldives
    +    {     88,   197,   848 }, // Romance Standard Time / Spain
    +    {     50,    91,   875 }, // Greenwich Standard Time / Guinea
    +    {      5,   237,   890 }, // Arab Standard Time / Yemen
    +    {     92,   222,   900 }, // Russian Standard Time / Ukraine
    +    {    103,   204,   918 }, // South Africa Standard Time / Swaziland
    +    {    130,   203,   933 }, // W. Europe Standard Time / Svalbard And Jan Mayen Islands
    +    {      7,   103,   953 }, // Arabic Standard Time / Iraq
    +    {    119,   226,   966 }, // UTC-11 / United States Minor Outlying Islands
    +    {      5,   115,   981 }, // Arab Standard Time / Kuwait
    +    {     50,   189,   993 }, // Greenwich Standard Time / Sierra Leone
    +    {     31,     0,  1009 }, // Central Standard Time / AnyCountry
    +    {     53,    51,  1017 }, // Hawaiian Standard Time / Cook Islands
    +    {    129,    50,  1035 }, // W. Central Africa Standard Time / Congo Brazzaville
    +    {     64,    43,  1054 }, // Magallanes Standard Time / Chile
    +    {    119,     0,  1075 }, // UTC-11 / AnyCountry
    +    {     84,    38,  1086 }, // Pacific Standard Time / Canada
    +    {     22,    11,  1138 }, // Caucasus Standard Time / Armenia
    +    {    130,   142,  1151 }, // W. Europe Standard Time / Monaco
    +    {    103,   239,  1165 }, // South Africa Standard Time / Zambia
    +    {     46,   222,  1179 }, // FLE Standard Time / Ukraine
    +    {     87,   168,  1225 }, // Paraguay Standard Time / Paraguay
    +    {     57,   109,  1242 }, // Jordan Standard Time / Jordan
    +    {    109,    30,  1253 }, // Tocantins Standard Time / Brazil
    +    {     55,   102,  1271 }, // Iran Standard Time / Iran
    +    {    101,     8,  1283 }, // SE Asia Standard Time / Antarctica
    +    {     27,    57,  1300 }, // Central Europe Standard Time / Czech Republic
    +    {     95,   215,  1314 }, // SA Western Standard Time / Trinidad And Tobago
    +    {    103,    28,  1336 }, // South Africa Standard Time / Botswana
    +    {    132,     0,  1352 }, // West Asia Standard Time / AnyCountry
    +    {     94,    63,  1362 }, // SA Pacific Standard Time / Ecuador
    +    {     51,    85,  1380 }, // GTB Standard Time / Greece
    +    {     36,   128,  1394 }, // E. Africa Standard Time / Madagascar
    +    {     53,   226,  1414 }, // Hawaiian Standard Time / United States Minor Outlying Islands
    +    {     94,   107,  1431 }, // SA Pacific Standard Time / Jamaica
    +    {    104,   198,  1447 }, // Sri Lanka Standard Time / Sri Lanka
    +    {     27,   243,  1460 }, // Central Europe Standard Time / Serbia
    +    {     25,   110,  1476 }, // Central Asia Standard Time / Kazakhstan
    +    {    125,     0,  1502 }, // UTC+13 / AnyCountry
    +    {     94,    38,  1513 }, // SA Pacific Standard Time / Canada
    +    {     25,    31,  1535 }, // Central Asia Standard Time / British Indian Ocean Territory
    +    {    108,    13,  1549 }, // Tasmania Standard Time / Australia
    +    {     95,   174,  1583 }, // SA Western Standard Time / Puerto Rico
    +    {     95,   180,  1603 }, // SA Western Standard Time / Saint Kitts And Nevis
    +    {    130,   206,  1620 }, // W. Europe Standard Time / Switzerland
    +    {    117,   225,  1634 }, // US Eastern Standard Time / United States
    +    {     29,   140,  1701 }, // Central Pacific Standard Time / Micronesia
    +    {    120,    77,  1731 }, // UTC-09 / French Polynesia
    +    {    129,   156,  1747 }, // W. Central Africa Standard Time / Niger
    +    {    118,   139,  1761 }, // US Mountain Standard Time / Mexico
    +    {     36,   194,  1780 }, // E. Africa Standard Time / Somalia
    +    {    118,     0,  1797 }, // US Mountain Standard Time / AnyCountry
    +    {     10,    24,  1807 }, // Atlantic Standard Time / Bermuda
    +    {    103,   240,  1824 }, // South Africa Standard Time / Zimbabwe
    +    {     32,   126,  1838 }, // China Standard Time / Macau
    +    {    129,    66,  1849 }, // W. Central Africa Standard Time / Equatorial Guinea
    +    {     66,   137,  1863 }, // Mauritius Standard Time / Mauritius
    +    {     46,    68,  1880 }, // FLE Standard Time / Estonia
    +    {     50,   187,  1895 }, // Greenwich Standard Time / Senegal
    +    {    132,   110,  1908 }, // West Asia Standard Time / Kazakhstan
    +    {     25,    44,  1968 }, // Central Asia Standard Time / China
    +    {    130,   106,  1980 }, // W. Europe Standard Time / Italy
    +    {     48,   251,  1992 }, // GMT Standard Time / Isle Of Man
    +    {     36,   210,  2011 }, // E. Africa Standard Time / Tanzania
    +    {     10,    86,  2032 }, // Atlantic Standard Time / Greenland
    +    {    123,    86,  2046 }, // UTC / Greenland
    +    {     20,    38,  2067 }, // Canada Central Standard Time / Canada
    +    {     15,    86,  2104 }, // Azores Standard Time / Greenland
    +    {     69,   145,  2125 }, // Morocco Standard Time / Morocco
    +    {    115,   219,  2143 }, // Turks And Caicos Standard Time / Turks And Caicos Islands
    +    {     50,    80,  2162 }, // Greenwich Standard Time / Gambia
    +    {    129,    42,  2176 }, // W. Central Africa Standard Time / Chad
    +    {     56,   105,  2192 }, // Israel Standard Time / Israel
    +    {     64,     8,  2207 }, // Magallanes Standard Time / Antarctica
    +    {     12,    13,  2225 }, // Aus Central W. Standard Time / Australia
    +    {     24,   155,  2241 }, // Central America Standard Time / Nicaragua
    +    {    102,   170,  2257 }, // Singapore Standard Time / Philippines
    +    {    134,   160,  2269 }, // West Pacific Standard Time / Northern Mariana Islands
    +    {     43,    64,  2284 }, // Egypt Standard Time / Egypt
    +    {     88,    21,  2297 }, // Romance Standard Time / Belgium
    +    {     76,     8,  2313 }, // New Zealand Standard Time / Antarctica
    +    {     51,   177,  2332 }, // GTB Standard Time / Romania
    +    {    103,     0,  2349 }, // South Africa Standard Time / AnyCountry
    +    {     41,   225,  2359 }, // Eastern Standard Time / United States
    +    {    129,    23,  2516 }, // W. Central Africa Standard Time / Benin
    +    {     79,   178,  2534 }, // North Asia East Standard Time / Russia
    +    {    116,   143,  2547 }, // Ulaanbaatar Standard Time / Mongolia
    +    {    130,    14,  2580 }, // W. Europe Standard Time / Austria
    +    {     41,    38,  2594 }, // Eastern Standard Time / Canada
    +    {     95,   255,  2699 }, // SA Western Standard Time / Bonaire
    +    {    124,   149,  2718 }, // UTC+12 / Nauru
    +    {    134,     8,  2732 }, // West Pacific Standard Time / Antarctica
    +    {     63,   178,  2758 }, // Magadan Standard Time / Russia
    +    {    130,   161,  2771 }, // W. Europe Standard Time / Norway
    +    {    110,     0,  2783 }, // Tokyo Standard Time / AnyCountry
    +    {     24,    63,  2793 }, // Central America Standard Time / Ecuador
    +    {    103,    35,  2811 }, // South Africa Standard Time / Burundi
    +    {     10,    38,  2828 }, // Atlantic Standard Time / Canada
    +    {     29,     0,  2896 }, // Central Pacific Standard Time / AnyCountry
    +    {     95,    87,  2907 }, // SA Western Standard Time / Grenada
    +    {     29,   153,  2923 }, // Central Pacific Standard Time / New Caledonia
    +    {     42,   139,  2938 }, // Eastern Standard Time (Mexico) / Mexico
    +    {      2,   225,  2953 }, // Alaskan Standard Time / United States
    +    {     49,    86,  3029 }, // Greenland Standard Time / Greenland
    +    {     50,    92,  3045 }, // Greenwich Standard Time / Guinea Bissau
    +    {    130,   184,  3059 }, // W. Europe Standard Time / San Marino
    +    {     27,    98,  3077 }, // Central Europe Standard Time / Hungary
    +    {     24,    96,  3093 }, // Central America Standard Time / Honduras
    +    {     62,    13,  3113 }, // Lord Howe Standard Time / Australia
    +    {     36,     0,  3133 }, // E. Africa Standard Time / AnyCountry
    +    {    129,    79,  3143 }, // W. Central Africa Standard Time / Gabon
    +    {     95,   182,  3161 }, // SA Western Standard Time / Saint Vincent And The Grenadines
    +    {     48,   224,  3180 }, // GMT Standard Time / United Kingdom
    +    {     68,   227,  3194 }, // Montevideo Standard Time / Uruguay
    +    {    124,     0,  3213 }, // UTC+12 / AnyCountry
    +    {    130,   230,  3224 }, // W. Europe Standard Time / Vatican City State
    +    {     50,    99,  3239 }, // Greenwich Standard Time / Iceland
    +    {     34,    55,  3258 }, // Cuba Standard Time / Cuba
    +    {     41,    16,  3273 }, // Eastern Standard Time / Bahamas
    +    {    122,   196,  3288 }, // UTC-02 / South Georgia And The South Sandwich Islands
    +    {     24,    65,  3311 }, // Central America Standard Time / El Salvador
    +    {     31,   225,  3331 }, // Central Standard Time / United States
    +    {     95,     0,  3499 }, // SA Western Standard Time / AnyCountry
    +    {     94,   166,  3509 }, // SA Pacific Standard Time / Panama
    +    {     94,    47,  3524 }, // SA Pacific Standard Time / Colombia
    +    {     70,   139,  3539 }, // Mountain Standard Time (Mexico) / Mexico
    +    {    124,   220,  3574 }, // UTC+12 / Tuvalu
    +    {    130,    84,  3591 }, // W. Europe Standard Time / Gibraltar
    +    {     82,   178,  3608 }, // Omsk Standard Time / Russia
    +    {     60,   122,  3618 }, // Libya Standard Time / Libya
    +    {     25,     8,  3633 }, // Central Asia Standard Time / Antarctica
    +    {     95,    12,  3651 }, // SA Western Standard Time / Aruba
    +    {     67,   119,  3665 }, // Middle East Standard Time / Lebanon
    +    {    102,     0,  3677 }, // Singapore Standard Time / AnyCountry
    +    {     74,   148,  3687 }, // Namibia Standard Time / Namibia
    +    {    126,   231,  3703 }, // Venezuela Standard Time / Venezuela
    +    {     95,   234,  3719 }, // SA Western Standard Time / United States Virgin Islands
    +    {     21,     0,  3737 }, // Cape Verde Standard Time / AnyCountry
    +    {     95,     9,  3747 }, // SA Western Standard Time / Antigua And Barbuda
    +    {     94,   169,  3763 }, // SA Pacific Standard Time / Peru
    +    {     46,   248,  3776 }, // FLE Standard Time / Aland Islands
    +    {     50,   199,  3793 }, // Greenwich Standard Time / Saint Helena
    +    {    134,   140,  3812 }, // West Pacific Standard Time / Micronesia
    +    {    102,   190,  3825 }, // Singapore Standard Time / Singapore
    +    {     95,    61,  3840 }, // SA Western Standard Time / Dominican Republic
    +    {    103,   129,  3862 }, // South Africa Standard Time / Malawi
    +    {     30,   139,  3878 }, // Central Standard Time (Mexico) / Mexico
    +    {    102,   130,  3954 }, // Singapore Standard Time / Malaysia
    +    {     45,    72,  3985 }, // Fiji Standard Time / Fiji
    +    {    118,   225,  3998 }, // US Mountain Standard Time / United States
    +    {     17,    25,  4014 }, // Bangladesh Standard Time / Bhutan
    +    {    130,   133,  4027 }, // W. Europe Standard Time / Malta
    +    {     92,   178,  4040 }, // Russian Standard Time / Russia
    +    {     95,   135,  4084 }, // SA Western Standard Time / Martinique
    +    {     35,     0,  4103 }, // Dateline Standard Time / AnyCountry
    +    {    135,   178,  4114 }, // Yakutsk Standard Time / Russia
    +    {      1,     1,  4141 }, // Afghanistan Standard Time / Afghanistan
    +    {    123,     0,  4152 }, // UTC / AnyCountry
    +    {     31,   139,  4168 }, // Central Standard Time / Mexico
    +    {      6,     0,  4186 }, // Arabian Standard Time / AnyCountry
    +    {    101,    45,  4196 }, // SE Asia Standard Time / Christmas Island
    +    {     15,   173,  4213 }, // Azores Standard Time / Portugal
    +    {    129,     0,  4229 }, // W. Central Africa Standard Time / AnyCountry
    +    {     17,    18,  4239 }, // Bangladesh Standard Time / Bangladesh
    +    {     31,    38,  4250 }, // Central Standard Time / Canada
    +    {     94,     0,  4325 }, // SA Pacific Standard Time / AnyCountry
    +    {    125,   213,  4335 }, // UTC+13 / Tokelau
    +    {     73,   178,  4351 }, // N. Central Asia Standard Time / Russia
    +    {    133,   165,  4368 }, // West Bank Standard Time / Palestinian Territories
    +    {    114,   217,  4390 }, // Turkey Standard Time / Turkey
    +    {      3,   225,  4406 }, // Aleutian Standard Time / United States
    +    {    101,     0,  4419 }, // SE Asia Standard Time / AnyCountry
    +    {     71,   225,  4429 }, // Mountain Standard Time / United States
    +    {     36,    69,  4458 }, // E. Africa Standard Time / Ethiopia
    +    {    130,   151,  4477 }, // W. Europe Standard Time / Netherlands
    +    {     95,   245,  4494 }, // SA Western Standard Time / Saint Martin
    +    {     48,   173,  4510 }, // GMT Standard Time / Portugal
    +    {     46,   124,  4541 }, // FLE Standard Time / Lithuania
    +    {    130,    82,  4556 }, // W. Europe Standard Time / Germany
    +    {     65,    77,  4586 }, // Marquesas Standard Time / French Polynesia
    +    {     80,   178,  4604 }, // North Asia Standard Time / Russia
    +    {     61,   112,  4639 }, // Line Islands Standard Time / Kiribati
    +    {     96,   200,  4658 }, // Saint Pierre Standard Time / Saint Pierre And Miquelon
    +    {     48,   104,  4675 }, // GMT Standard Time / Ireland
    +    {      5,   186,  4689 }, // Arab Standard Time / Saudi Arabia
    +    {     83,    43,  4701 }, // Pacific SA Standard Time / Chile
    +    {     91,   178,  4718 }, // Russia Time Zone 11 / Russia
    +    {     36,    48,  4745 }, // E. Africa Standard Time / Comoros
    +    {     95,   152,  4759 }, // SA Western Standard Time / Cura Sao
    +    {     38,   141,  4775 }, // E. Europe Standard Time / Moldova
    +    {     24,    22,  4791 }, // Central America Standard Time / Belize
    +    {    103,   195,  4806 }, // South Africa Standard Time / South Africa
    +    {    127,   178,  4826 }, // Vladivostok Standard Time / Russia
    +    {    122,     0,  4857 }, // UTC-02 / AnyCountry
    +    {    106,   207,  4867 }, // Syria Standard Time / Syria
    +    {     93,    76,  4881 }, // SA Eastern Standard Time / French Guiana
    +    {     50,   136,  4897 }, // Greenwich Standard Time / Mauritania
    +    {     41,     0,  4915 }, // Eastern Standard Time / AnyCountry
    +    {     16,    30,  4923 }, // Bahia Standard Time / Brazil
    +    {     40,    43,  4937 }, // Easter Island Standard Time / Chile
    +    {     93,     0,  4952 }, // SA Eastern Standard Time / AnyCountry
    +    {      9,   178,  4962 }, // Astrakhan Standard Time / Russia
    +    {     95,    30,  4996 }, // SA Western Standard Time / Brazil
    +    {     18,    20,  5049 }, // Belarus Standard Time / Belarus
    +    {     95,   181,  5062 }, // SA Western Standard Time / Saint Lucia
    +    {    129,     6,  5079 }, // W. Central Africa Standard Time / Angola
    +    {    129,   157,  5093 }, // W. Central Africa Standard Time / Nigeria
    +    {    130,     5,  5106 }, // W. Europe Standard Time / Andorra
    +    {     58,   178,  5121 }, // Kaliningrad Standard Time / Russia
    +    {     71,     0,  5140 }, // Mountain Standard Time / AnyCountry
    +    {     95,     7,  5148 }, // SA Western Standard Time / Anguilla
    +    {    124,   235,  5165 }, // UTC+12 / Wallis And Futuna Islands
    +    {      6,   223,  5180 }, // Arabian Standard Time / United Arab Emirates
    +    {     94,    40,  5191 }, // SA Pacific Standard Time / Cayman Islands
    +    {    101,   211,  5206 }, // SE Asia Standard Time / Thailand
    +    {     29,   193,  5219 }, // Central Pacific Standard Time / Solomon Islands
    +    {     47,    81,  5239 }, // Georgian Standard Time / Georgia
    +    {    101,    36,  5252 }, // SE Asia Standard Time / Cambodia
    +    {    132,   228,  5268 }, // West Asia Standard Time / Uzbekistan
    +    {     51,    56,  5297 }, // GTB Standard Time / Cyprus
    +    {     95,    88,  5325 }, // SA Western Standard Time / Guadeloupe
    +    {    101,   232,  5344 }, // SE Asia Standard Time / Vietnam
    +    {    113,   178,  5356 }, // Transbaikal Standard Time / Russia
    +    {     50,   121,  5367 }, // Greenwich Standard Time / Liberia
    +    {     95,   233,  5383 }, // SA Western Standard Time / British Virgin Islands
    +    {    129,    49,  5399 }, // W. Central Africa Standard Time / Congo Kinshasa
    +    {     97,   178,  5415 }, // Sakhalin Standard Time / Russia
    +    {    124,   226,  5429 }, // UTC+12 / United States Minor Outlying Islands
    +    {     50,    83,  5442 }, // Greenwich Standard Time / Ghana
    +    {     76,   154,  5455 }, // New Zealand Standard Time / New Zealand
    +    {     23,    13,  5472 }, // Cen. Australia Standard Time / Australia
    +    {     53,    77,  5513 }, // Hawaiian Standard Time / French Polynesia
    +    {     50,    34,  5528 }, // Greenwich Standard Time / Burkina Faso
    +    {    132,    78,  5547 }, // West Asia Standard Time / French Southern Territories
    +    {    121,     0,  5564 }, // UTC-08 / AnyCountry
    +    {     27,     2,  5574 }, // Central Europe Standard Time / Albania
    +    {    107,   208,  5588 }, // Taipei Standard Time / Taiwan
    +    {     88,    58,  5600 }, // Romance Standard Time / Denmark
    +    {     36,   221,  5618 }, // E. Africa Standard Time / Uganda
    +    {     95,    19,  5633 }, // SA Western Standard Time / Barbados
    +    {     14,    15,  5650 }, // Azerbaijan Standard Time / Azerbaijan
    +    {     32,    97,  5660 }, // China Standard Time / Hong Kong
    +    {    110,   101,  5675 }, // Tokyo Standard Time / Indonesia
    +    {     53,   225,  5689 }, // Hawaiian Standard Time / United States
    +    {     36,   111,  5706 }, // E. Africa Standard Time / Kenya
    +    {    134,    89,  5721 }, // West Pacific Standard Time / Guam
    +    {     36,   254,  5734 }, // E. Africa Standard Time / South Sudan
    +    {     48,    71,  5746 }, // GMT Standard Time / Faroe Islands
    +    {     90,   178,  5762 }, // Russia Time Zone 10 / Russia
    +    {    119,   158,  5781 }, // UTC-11 / Niue
    +    {    129,     3,  5794 }, // W. Central Africa Standard Time / Algeria
    +    {    110,    62,  5809 }, // Tokyo Standard Time / East Timor
    +    {     93,    30,  5819 }, // SA Eastern Standard Time / Brazil
    +    {     27,   242,  5898 }, // Central Europe Standard Time / Montenegro
    +    {    129,    37,  5915 }, // W. Central Africa Standard Time / Cameroon
    +    {    101,   117,  5929 }, // SE Asia Standard Time / Laos
    +    {     85,   139,  5944 }, // Pacific Standard Time (Mexico) / Mexico
    +    {     50,   212,  5981 }, // Greenwich Standard Time / Togo
    +    {     46,   118,  5993 }, // FLE Standard Time / Latvia
    +    {     95,    38,  6005 }, // SA Western Standard Time / Canada
    +    {    132,   209,  6026 }, // West Asia Standard Time / Tajikistan
    +    {     77,    38,  6040 }, // Newfoundland Standard Time / Canada
    +    {    110,   108,  6057 }, // Tokyo Standard Time / Japan
    +    {     25,     0,  6068 }, // Central Asia Standard Time / AnyCountry
    +    {     28,    27,  6078 }, // Central European Standard Time / Bosnia And Herzegowina
    +    {     27,   191,  6094 }, // Central Europe Standard Time / Slovakia
    +    {     95,    93,  6112 }, // SA Western Standard Time / Guyana
    +    {     48,   197,  6127 }, // GMT Standard Time / Spain
    +    {     19,   167,  6143 }, // Bougainville Standard Time / Papua New Guinea
    +    {      5,    17,  6164 }, // Arab Standard Time / Bahrain
    +    {     24,    90,  6177 }, // Central America Standard Time / Guatemala
    +    {     95,    26,  6195 }, // SA Western Standard Time / Bolivia
    +    {     81,   113,  6210 }, // North Korea Standard Time / North Korea
    +    {    119,     4,  6225 }, // UTC-11 / American Samoa
    +    {     66,   176,  6243 }, // Mauritius Standard Time / Reunion
    +    {    103,   120,  6258 }, // South Africa Standard Time / Lesotho
    +    {     84,     0,  6272 }, // Pacific Standard Time / AnyCountry
    +    {    120,     0,  6280 }, // UTC-09 / AnyCountry
    +    {    129,   216,  6290 }, // W. Central Africa Standard Time / Tunisia
    +    {     99,   185,  6303 }, // Sao Tome Standard Time / Sao Tome And Principe
    +    {    100,   178,  6319 }, // Saratov Standard Time / Russia
    +    {    105,   201,  6334 }, // Sudan Standard Time / Sudan
    +    {     48,   252,  6350 }, // GMT Standard Time / Jersey
    +    {     29,    13,  6364 }, // Central Pacific Standard Time / Australia
    +    {     71,   139,  6385 }, // Mountain Standard Time / Mexico
    +    {     21,    39,  6401 }, // Cape Verde Standard Time / Cape Verde
    +    {    102,   101,  6421 }, // Singapore Standard Time / Indonesia
    +    {     27,   192,  6435 }, // Central Europe Standard Time / Slovenia
    +    {     48,    75,  6452 }, // GMT Standard Time / Guernsey
    +    {    132,     8,  6468 }, // West Asia Standard Time / Antarctica
    +    {      8,    10,  6486 }, // Argentina Standard Time / Argentina
    +    {     98,   183,  6759 }, // Samoa Standard Time / Samoa
    +    {    129,    41,  6772 }, // W. Central Africa Standard Time / Central African Republic
    +    {    111,   178,  6786 }, // Tomsk Standard Time / Russia
    +    {    110,   164,  6797 }, // Tokyo Standard Time / Palau
    +    {     11,    13,  6811 }, // AUS Central Standard Time / Australia
    +    {    121,   171,  6828 }, // UTC-08 / Pitcairn
    +    {    102,    32,  6845 }, // Singapore Standard Time / Brunei
    +    {    112,   214,  6857 }, // Tonga Standard Time / Tonga
    +    {     89,   178,  6875 }, // Russia Time Zone 3 / Russia
    +    {    128,    13,  6889 }, // W. Australia Standard Time / Australia
    +    {     28,   172,  6905 }, // Central European Standard Time / Poland
    +    {     72,    46,  6919 }, // Myanmar Standard Time / Cocos Islands
    +    {     66,   188,  6932 }, // Mauritius Standard Time / Seychelles
    +    {     84,   225,  6944 }, // Pacific Standard Time / United States
    +    {     54,   100,  6983 }, // India Standard Time / India
    +    {     50,    53,  6997 }, // Greenwich Standard Time / Ivory Coast
    +    {     24,     0,  7012 }, // Central America Standard Time / AnyCountry
    +    {     29,   229,  7022 }, // Central Pacific Standard Time / Vanuatu
    +    {    130,   125,  7036 }, // W. Europe Standard Time / Luxembourg
    +    {     50,   132,  7054 }, // Greenwich Standard Time / Mali
    +    {    103,   179,  7068 }, // South Africa Standard Time / Rwanda
    +    {      5,   175,  7082 }, // Arab Standard Time / Qatar
    +    {     86,   163,  7093 }, // Pakistan Standard Time / Pakistan
    +    {    134,     0,  7106 }, // West Pacific Standard Time / AnyCountry
    +    {     36,    59,  7117 }, // E. Africa Standard Time / Djibouti
    +    {     44,   178,  7133 }, // Ekaterinburg Standard Time / Russia
    +    {    118,    38,  7152 }, // US Mountain Standard Time / Canada
    +    {     36,   138,  7209 }, // E. Africa Standard Time / Mayotte
    +    {     28,   127,  7224 }, // Central European Standard Time / Macedonia
    +    {     59,   114,  7238 }, // Korea Standard Time / South Korea
    +    {     93,   202,  7249 }, // SA Eastern Standard Time / Suriname
    +    {    130,   205,  7268 }, // W. Europe Standard Time / Sweden
    +    {    103,    49,  7285 }, // South Africa Standard Time / Congo Kinshasa
         {      0,     0,     0 } // Trailing zeroes
     };
     
     // Windows ID Key, Windows ID Index, IANA ID Index, UTC Offset
     static const QWindowsData windowsDataTable[] = {
    -    {      1,     0,  3480, 16200 }, // Afghanistan Standard Time
    -    {      2,    26,  6962,-32400 }, // Alaskan Standard Time
    -    {      3,    48,  5629, 10800 }, // Arab Standard Time
    -    {      4,    67,  3254, 14400 }, // Arabian Standard Time
    -    {      5,    89,   504, 10800 }, // Arabic Standard Time
    -    {      6,   110,  6980,-10800 }, // Argentina Standard Time
    -    {      7,   134,  7001,-14400 }, // Atlantic Standard Time
    -    {      8,   157,  4368, 34200 }, // AUS Central Standard Time
    -    {      9,   183,  7017, 36000 }, // AUS Eastern Standard Time
    -    {     10,   209,  4400, 14400 }, // Azerbaijan Standard Time
    -    {     11,   234,  1220, -3600 }, // Azores Standard Time
    -    {     12,   255,   701,-10800 }, // Bahia Standard Time
    -    {     13,   275,  1340, 21600 }, // Bangladesh Standard Time
    -    {     14,   300,  6804, 10800 }, // Belarus Standard Time
    -    {     15,   322,  7034,-21600 }, // Canada Central Standard Time
    -    {     16,   351,  4348, -3600 }, // Cape Verde Standard Time
    -    {     17,   376,  3902, 14400 }, // Caucasus Standard Time
    -    {     18,   399,  7049, 34200 }, // Cen. Australia Standard Time
    -    {     19,   428,  4058,-21600 }, // Central America Standard Time
    -    {     20,   458,  7068, 21600 }, // Central Asia Standard Time
    -    {     21,   485,  7080,-14400 }, // Central Brazilian Standard Time
    -    {     22,   517,  5078,  3600 }, // Central Europe Standard Time
    -    {     23,   546,  3970,  3600 }, // Central European Standard Time
    -    {     24,   577,  1769, 39600 }, // Central Pacific Standard Time
    -    {     25,   607,  7095,-21600 }, // Central Standard Time (Mexico)
    -    {     26,   638,  7115,-21600 }, // Central Standard Time
    -    {     27,   660,  6078, 28800 }, // China Standard Time
    -    {     28,   680,  3352,-43200 }, // Dateline Standard Time
    -    {     29,   703,  2585, 10800 }, // E. Africa Standard Time
    -    {     30,   727,  7131, 36000 }, // E. Australia Standard Time
    -    {     31,   754,  2654,-10800 }, // E. South America Standard Time
    -    {     32,   785,  7150,-18000 }, // Eastern Standard Time
    -    {     33,   807,  2031,-18000 }, // Eastern Standard Time (Mexico)
    -    {     34,   838,  1678,  7200 }, // Egypt Standard Time
    -    {     35,   858,   651, 18000 }, // Ekaterinburg Standard Time
    -    {     36,   885,  6369, 43200 }, // Fiji Standard Time
    -    {     37,   904,  7167,  7200 }, // FLE Standard Time
    -    {     38,   922,  3022, 14400 }, // Georgian Standard Time
    -    {     39,   945,  5683,     0 }, // GMT Standard Time
    -    {     40,   963,  3954,-10800 }, // Greenland Standard Time
    -    {     41,   987,  2012,     0 }, // Greenwich Standard Time
    -    {     42,  1011,  1819,  7200 }, // GTB Standard Time
    -    {     43,  1029,  3335,-36000 }, // Hawaiian Standard Time
    -    {     44,  1052,  4520, 19800 }, // India Standard Time
    -    {     45,  1072,  1328, 12600 }, // Iran Standard Time
    -    {     46,  1091,  4427,  7200 }, // Israel Standard Time
    -    {     47,  1112,  1808,  7200 }, // Jordan Standard Time
    -    {     48,  1133,  1789,  7200 }, // Kaliningrad Standard Time
    -    {     49,  1159,  3723, 32400 }, // Korea Standard Time
    -    {     50,  1179,    63,  7200 }, // Libya Standard Time
    -    {     51,  1199,   835, 50400 }, // Line Islands Standard Time
    -    {     52,  1226,  2274, 36000 }, // Magadan Standard Time
    -    {     53,  1248,  6744, 14400 }, // Mauritius Standard Time
    -    {     54,  1272,  4046,  7200 }, // Middle East Standard Time
    -    {     55,  1298,   755,-10800 }, // Montevideo Standard Time
    -    {     56,  1323,  3884,     0 }, // Morocco Standard Time
    -    {     57,  1345,  7179,-25200 }, // Mountain Standard Time (Mexico)
    -    {     58,  1377,  7197,-25200 }, // Mountain Standard Time
    -    {     59,  1400,  1725, 23400 }, // Myanmar Standard Time
    -    {     60,  1422,  7212, 21600 }, // N. Central Asia Standard Time
    -    {     61,  1452,  5094,  3600 }, // Namibia Standard Time
    -    {     62,  1474,  4506, 20700 }, // Nepal Standard Time
    -    {     63,  1494,  3399, 43200 }, // New Zealand Standard Time
    -    {     64,  1520,  3382,-12600 }, // Newfoundland Standard Time
    -    {     65,  1547,  1405, 28800 }, // North Asia East Standard Time
    -    {     66,  1577,  7229, 25200 }, // North Asia Standard Time
    -    {     67,  1602,  6235,-10800 }, // Pacific SA Standard Time
    -    {     68,  1627,   819,  7200 }, // E. Europe Standard Time
    -    {     69,  1651,  1351,-28800 }, // Pacific Standard Time
    -    {     70,  1673,  4076, 18000 }, // Pakistan Standard Time
    -    {     71,  1696,  3088,-14400 }, // Paraguay Standard Time
    -    {     72,  1719,   638,  3600 }, // Romance Standard Time
    -    {     73,  1741,  3815, 14400 }, // Russia Time Zone 3
    -    {     74,  1760,   533, 39600 }, // Russia Time Zone 10
    -    {     75,  1780,  7246, 43200 }, // Russia Time Zone 11
    -    {     76,  1800,  7261, 10800 }, // Russian Standard Time
    -    {     77,  1822,   149,-10800 }, // SA Eastern Standard Time
    -    {     78,  1847,  4333,-18000 }, // SA Pacific Standard Time
    -    {     79,  1872,  4122,-14400 }, // SA Western Standard Time
    -    {     80,  1897,  3322, 46800 }, // Samoa Standard Time
    -    {     81,  1917,  2320, 25200 }, // SE Asia Standard Time
    -    {     82,  1939,  3465, 28800 }, // Singapore Standard Time
    -    {     83,  1963,  3148,  7200 }, // South Africa Standard Time
    -    {     84,  1990,  5764, 19800 }, // Sri Lanka Standard Time
    -    {     85,  2014,  4294,  7200 }, // Syria Standard Time
    -    {     86,  2034,  3932, 28800 }, // Taipei Standard Time
    -    {     87,  2055,  7275, 36000 }, // Tasmania Standard Time
    -    {     88,  2078,  5654, 32400 }, // Tokyo Standard Time
    -    {     89,  2098,  3984, 46800 }, // Tonga Standard Time
    -    {     90,  2118,  4784,  7200 }, // Turkey Standard Time
    -    {     91,  2139,  7292, 28800 }, // Ulaanbaatar Standard Time
    -    {     92,  2165,  7309,-18000 }, // US Eastern Standard Time
    -    {     93,  2190,  4894,-25200 }, // US Mountain Standard Time
    -    {     94,  2216,  3753, -7200 }, // UTC-02
    -    {     95,  2223,  3035,-39600 }, // UTC-11
    -    {     96,  2230,  1070,     0 }, // UTC
    -    {     97,  2234,   239, 43200 }, // UTC+12
    -    {     98,  2241,  5172,-16200 }, // Venezuela Standard Time
    -    {     99,  2265,  7330, 36000 }, // Vladivostok Standard Time
    -    {    100,  2291,  3843, 28800 }, // W. Australia Standard Time
    -    {    101,  2318,  1909,  3600 }, // W. Central Africa Standard Time
    -    {    102,  2350,  7347,  3600 }, // W. Europe Standard Time
    -    {    103,  2374,  7361, 18000 }, // West Asia Standard Time
    -    {    104,  2398,  3067, 36000 }, // West Pacific Standard Time
    -    {    105,  2425,  7375, 32400 }, // Yakutsk Standard Time
    -    {    106,  2447,  4385, 30600 }, // North Korea Standard Time
    +    {      1,     0,  4141, 16200 }, // Afghanistan Standard Time
    +    {      2,    26,  7303,-32400 }, // Alaskan Standard Time
    +    {      3,    48,  4406,-36000 }, // Aleutian Standard Time
    +    {      4,    71,   325, 25200 }, // Altai Standard Time
    +    {      5,    91,  4689, 10800 }, // Arab Standard Time
    +    {      6,   110,  5180, 14400 }, // Arabian Standard Time
    +    {      7,   132,   953, 10800 }, // Arabic Standard Time
    +    {      8,   153,  7321,-10800 }, // Argentina Standard Time
    +    {      9,   177,  7342, 14400 }, // Astrakhan Standard Time
    +    {     10,   201,  7359,-14400 }, // Atlantic Standard Time
    +    {     11,   224,  6811, 34200 }, // AUS Central Standard Time
    +    {     12,   250,  2225, 31500 }, // Aus Central W. Standard Time
    +    {     13,   279,  7375, 36000 }, // AUS Eastern Standard Time
    +    {     14,   305,  5650, 14400 }, // Azerbaijan Standard Time
    +    {     15,   330,  4213, -3600 }, // Azores Standard Time
    +    {     16,   351,  4923,-10800 }, // Bahia Standard Time
    +    {     17,   371,  4239, 21600 }, // Bangladesh Standard Time
    +    {     18,   396,  5049, 10800 }, // Belarus Standard Time
    +    {     19,   418,  6143, 39600 }, // Bougainville Standard Time
    +    {     20,   445,  7392,-21600 }, // Canada Central Standard Time
    +    {     21,   474,  6401, -3600 }, // Cape Verde Standard Time
    +    {     22,   499,  1138, 14400 }, // Caucasus Standard Time
    +    {     23,   522,  7407, 34200 }, // Cen. Australia Standard Time
    +    {     24,   551,  6177,-21600 }, // Central America Standard Time
    +    {     25,   581,  7426, 21600 }, // Central Asia Standard Time
    +    {     26,   608,  7438,-14400 }, // Central Brazilian Standard Time
    +    {     27,   640,  3077,  3600 }, // Central Europe Standard Time
    +    {     28,   669,  6905,  3600 }, // Central European Standard Time
    +    {     29,   700,  5219, 39600 }, // Central Pacific Standard Time
    +    {     30,   730,  7453,-21600 }, // Central Standard Time (Mexico)
    +    {     31,   761,  7473,-21600 }, // Central Standard Time
    +    {     32,   783,    48, 28800 }, // China Standard Time
    +    {     33,   803,   114, 45900 }, // Chatham Islands Standard Time
    +    {     34,   833,  3258,-18000 }, // Cuba Standard Time
    +    {     35,   852,  4103,-43200 }, // Dateline Standard Time
    +    {     36,   875,  5706, 10800 }, // E. Africa Standard Time
    +    {     37,   899,  7489, 36000 }, // E. Australia Standard Time
    +    {     38,   926,  4775,  7200 }, // E. Europe Standard Time
    +    {     39,   950,   451,-10800 }, // E. South America Standard Time
    +    {     40,   981,  4937,-21600 }, // Easter Island Standard Time
    +    {     41,  1009,  7508,-18000 }, // Eastern Standard Time
    +    {     42,  1031,  2938,-18000 }, // Eastern Standard Time (Mexico)
    +    {     43,  1062,  2284,  7200 }, // Egypt Standard Time
    +    {     44,  1082,  7133, 18000 }, // Ekaterinburg Standard Time
    +    {     45,  1109,  3985, 43200 }, // Fiji Standard Time
    +    {     46,  1128,  7525,  7200 }, // FLE Standard Time
    +    {     47,  1146,  5239, 14400 }, // Georgian Standard Time
    +    {     48,  1169,  3180,     0 }, // GMT Standard Time
    +    {     49,  1187,  3029,-10800 }, // Greenland Standard Time
    +    {     50,  1211,  3239,     0 }, // Greenwich Standard Time
    +    {     51,  1235,  2332,  7200 }, // GTB Standard Time
    +    {     52,  1253,    25,-18000 }, // Haiti Standard Time
    +    {     53,  1273,  5689,-36000 }, // Hawaiian Standard Time
    +    {     54,  1296,  6983, 19800 }, // India Standard Time
    +    {     55,  1316,  1271, 12600 }, // Iran Standard Time
    +    {     56,  1335,  2192,  7200 }, // Israel Standard Time
    +    {     57,  1356,  1242,  7200 }, // Jordan Standard Time
    +    {     58,  1377,  5121,  7200 }, // Kaliningrad Standard Time
    +    {     59,  1403,  7238, 32400 }, // Korea Standard Time
    +    {     60,  1423,  3618,  7200 }, // Libya Standard Time
    +    {     61,  1443,  4639, 50400 }, // Line Islands Standard Time
    +    {     62,  1470,  3113, 37800 }, // Lord Howe Standard Time
    +    {     63,  1494,  2758, 36000 }, // Magadan Standard Time
    +    {     64,  1516,  1054,-10800 }, // Magallanes Standard Time
    +    {     65,  1541,  4586,-34200 }, // Marquesas Standard Time
    +    {     66,  1565,  1863, 14400 }, // Mauritius Standard Time
    +    {     67,  1589,  3665,  7200 }, // Middle East Standard Time
    +    {     68,  1615,  3194,-10800 }, // Montevideo Standard Time
    +    {     69,  1640,  2125,     0 }, // Morocco Standard Time
    +    {     70,  1662,  7537,-25200 }, // Mountain Standard Time (Mexico)
    +    {     71,  1694,  7555,-25200 }, // Mountain Standard Time
    +    {     72,  1717,   657, 23400 }, // Myanmar Standard Time
    +    {     73,  1739,  4351, 21600 }, // N. Central Asia Standard Time
    +    {     74,  1769,  3687,  3600 }, // Namibia Standard Time
    +    {     75,  1791,   793, 20700 }, // Nepal Standard Time
    +    {     76,  1811,  5455, 43200 }, // New Zealand Standard Time
    +    {     77,  1837,  6040,-12600 }, // Newfoundland Standard Time
    +    {     78,  1864,   752, 39600 }, // Norfolk Standard Time
    +    {     79,  1886,  2534, 28800 }, // North Asia East Standard Time
    +    {     80,  1916,  7570, 25200 }, // North Asia Standard Time
    +    {     81,  1941,  6210, 30600 }, // North Korea Standard Time
    +    {     82,  1967,  3608, 21600 }, // Omsk Standard Time
    +    {     83,  1986,  4701,-10800 }, // Pacific SA Standard Time
    +    {     84,  2011,  7587,-28800 }, // Pacific Standard Time
    +    {     85,  2033,  7607,-28800 }, // Pacific Standard Time (Mexico)
    +    {     86,  2064,  7093, 18000 }, // Pakistan Standard Time
    +    {     87,  2087,  1225,-14400 }, // Paraguay Standard Time
    +    {     88,  2110,   570,  3600 }, // Romance Standard Time
    +    {     89,  2132,  6875, 14400 }, // Russia Time Zone 3
    +    {     90,  2151,  5762, 39600 }, // Russia Time Zone 10
    +    {     91,  2171,  7623, 43200 }, // Russia Time Zone 11
    +    {     92,  2191,  7638, 10800 }, // Russian Standard Time
    +    {     93,  2213,  4881,-10800 }, // SA Eastern Standard Time
    +    {     94,  2238,  3524,-18000 }, // SA Pacific Standard Time
    +    {     95,  2263,  6195,-14400 }, // SA Western Standard Time
    +    {     96,  2288,  4658,-10800 }, // Saint Pierre Standard Time
    +    {     97,  2315,  5415, 39600 }, // Sakhalin Standard Time
    +    {     98,  2338,  6759, 46800 }, // Samoa Standard Time
    +    {     99,  2358,  6303,     0 }, // Sao Tome Standard Time
    +    {    100,  2381,  6319, 14400 }, // Saratov Standard Time
    +    {    101,  2403,  5206, 25200 }, // SE Asia Standard Time
    +    {    102,  2425,  3825, 28800 }, // Singapore Standard Time
    +    {    103,  2449,  4806,  7200 }, // South Africa Standard Time
    +    {    104,  2476,  1447, 19800 }, // Sri Lanka Standard Time
    +    {    105,  2500,  6334,  7200 }, // Sudan Standard Time
    +    {    106,  2520,  4867,  7200 }, // Syria Standard Time
    +    {    107,  2540,  5588, 28800 }, // Taipei Standard Time
    +    {    108,  2561,  7652, 36000 }, // Tasmania Standard Time
    +    {    109,  2584,  1253,-10800 }, // Tocantins Standard Time
    +    {    110,  2608,  6057, 32400 }, // Tokyo Standard Time
    +    {    111,  2628,  6786, 25200 }, // Tomsk Standard Time
    +    {    112,  2648,  6857, 46800 }, // Tonga Standard Time
    +    {    113,  2668,  5356, 32400 }, // Transbaikal Standard Time
    +    {    114,  2694,  4390,  7200 }, // Turkey Standard Time
    +    {    115,  2715,  2143,-14400 }, // Turks And Caicos Standard Time
    +    {    116,  2746,  7669, 28800 }, // Ulaanbaatar Standard Time
    +    {    117,  2772,  7686,-18000 }, // US Eastern Standard Time
    +    {    118,  2797,  3998,-25200 }, // US Mountain Standard Time
    +    {    119,  2823,  1075,-39600 }, // UTC-11
    +    {    120,  2830,  6280,-32400 }, // UTC-09
    +    {    121,  2837,  5564,-28800 }, // UTC-08
    +    {    122,  2844,  4857, -7200 }, // UTC-02
    +    {    123,  2851,  7707,     0 }, // UTC
    +    {    124,  2855,  3213, 43200 }, // UTC+12
    +    {    125,  2862,  1502, 46800 }, // UTC+13
    +    {    126,  2869,  3703,-16200 }, // Venezuela Standard Time
    +    {    127,  2893,  7715, 36000 }, // Vladivostok Standard Time
    +    {    128,  2919,  6889, 28800 }, // W. Australia Standard Time
    +    {    129,  2946,  5093,  3600 }, // W. Central Africa Standard Time
    +    {    130,  2978,  7732,  3600 }, // W. Europe Standard Time
    +    {    131,  3002,     0, 25200 }, // W. Mongolia Standard Time
    +    {    132,  3028,  7746, 18000 }, // West Asia Standard Time
    +    {    133,  3052,  7760,  7200 }, // West Bank Standard Time
    +    {    134,  3076,   377, 36000 }, // West Pacific Standard Time
    +    {    135,  3103,  7772, 32400 }, // Yakutsk Standard Time
         {      0,     0,     0,     0 } // Trailing zeroes
     };
     
     // IANA ID Index, UTC Offset
     static const QUtcData utcDataTable[] = {
    -    {   7388,     0 }, // UTC
    -    {   7392,-50400 }, // UTC-14:00
    -    {   7402,-46800 }, // UTC-13:00
    -    {   7412,-43200 }, // UTC-12:00
    -    {   7422,-39600 }, // UTC-11:00
    -    {   7432,-36000 }, // UTC-10:00
    -    {   7442,-32400 }, // UTC-09:00
    -    {   7452,-28800 }, // UTC-08:00
    -    {   7462,-25200 }, // UTC-07:00
    -    {   7472,-21600 }, // UTC-06:00
    -    {   7482,-18000 }, // UTC-05:00
    -    {   7492,-16200 }, // UTC-04:30
    -    {   7502,-14400 }, // UTC-04:00
    -    {   7512,-12600 }, // UTC-03:30
    -    {   7522,-10800 }, // UTC-03:00
    -    {   7532, -7200 }, // UTC-02:00
    -    {   7542, -3600 }, // UTC-01:00
    -    {   7552,     0 }, // UTC-00:00
    -    {   7562,     0 }, // UTC+00:00
    -    {   7572,  3600 }, // UTC+01:00
    -    {   7582,  7200 }, // UTC+02:00
    -    {   7592, 10800 }, // UTC+03:00
    -    {   7602, 12600 }, // UTC+03:30
    -    {   7612, 14400 }, // UTC+04:00
    -    {   7622, 16200 }, // UTC+04:30
    -    {   7632, 18000 }, // UTC+05:00
    -    {   7642, 19800 }, // UTC+05:30
    -    {   7652, 20700 }, // UTC+05:45
    -    {   7662, 21600 }, // UTC+06:00
    -    {   7672, 23400 }, // UTC+06:30
    -    {   7682, 25200 }, // UTC+07:00
    -    {   7692, 28800 }, // UTC+08:00
    -    {   7702, 32400 }, // UTC+09:00
    -    {   7712, 34200 }, // UTC+09:30
    -    {   7722, 36000 }, // UTC+10:00
    -    {   7732, 39600 }, // UTC+11:00
    -    {   7742, 43200 }, // UTC+12:00
    -    {   7752, 46800 }, // UTC+13:00
    -    {   7762, 50400 }, // UTC+14:00
    -    {   7772, 30600 }, // UTC+08:30
    +    {   7785,     0 }, // UTC
    +    {   7789,-50400 }, // UTC-14:00
    +    {   7799,-46800 }, // UTC-13:00
    +    {   7809,-43200 }, // UTC-12:00
    +    {   7819,-39600 }, // UTC-11:00
    +    {   7829,-36000 }, // UTC-10:00
    +    {   7839,-32400 }, // UTC-09:00
    +    {   7849,-28800 }, // UTC-08:00
    +    {   7859,-25200 }, // UTC-07:00
    +    {   7869,-21600 }, // UTC-06:00
    +    {   7879,-18000 }, // UTC-05:00
    +    {   7889,-16200 }, // UTC-04:30
    +    {   7899,-14400 }, // UTC-04:00
    +    {   7909,-12600 }, // UTC-03:30
    +    {   7919,-10800 }, // UTC-03:00
    +    {   7929, -7200 }, // UTC-02:00
    +    {   7939, -3600 }, // UTC-01:00
    +    {   7949,     0 }, // UTC-00:00
    +    {   7959,     0 }, // UTC+00:00
    +    {   7969,  3600 }, // UTC+01:00
    +    {   7979,  7200 }, // UTC+02:00
    +    {   7989, 10800 }, // UTC+03:00
    +    {   7999, 12600 }, // UTC+03:30
    +    {   8009, 14400 }, // UTC+04:00
    +    {   8019, 16200 }, // UTC+04:30
    +    {   8029, 18000 }, // UTC+05:00
    +    {   8039, 19800 }, // UTC+05:30
    +    {   8049, 20700 }, // UTC+05:45
    +    {   8059, 21600 }, // UTC+06:00
    +    {   8069, 23400 }, // UTC+06:30
    +    {   8079, 25200 }, // UTC+07:00
    +    {   8089, 28800 }, // UTC+08:00
    +    {   8099, 30600 }, // UTC+08:30
    +    {   8109, 32400 }, // UTC+09:00
    +    {   8119, 34200 }, // UTC+09:30
    +    {   8129, 36000 }, // UTC+10:00
    +    {   8139, 39600 }, // UTC+11:00
    +    {   8149, 43200 }, // UTC+12:00
    +    {   8159, 46800 }, // UTC+13:00
    +    {   8169, 50400 }, // UTC+14:00
         {     0,      0 } // Trailing zeroes
     };
     
     static const char windowsIdData[] = {
     0x41, 0x66, 0x67, 0x68, 0x61, 0x6e, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
     0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x6c, 0x61, 0x73, 0x6b, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
    -0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x72, 0x61, 0x62, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72,
    -0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x72, 0x61, 0x62, 0x69, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
    -0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x72, 0x61, 0x62, 0x69, 0x63, 0x20, 0x53, 0x74, 0x61, 0x6e,
    -0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x20,
    -0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74,
    -0x69, 0x63, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x55, 0x53,
    -0x20, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
    -0x6d, 0x65, 0x0, 0x41, 0x55, 0x53, 0x20, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
    -0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x7a, 0x65, 0x72, 0x62, 0x61, 0x69, 0x6a, 0x61, 0x6e, 0x20,
    -0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x7a, 0x6f, 0x72, 0x65, 0x73,
    -0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x42, 0x61, 0x68, 0x69, 0x61,
    -0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x42, 0x61, 0x6e, 0x67, 0x6c,
    -0x61, 0x64, 0x65, 0x73, 0x68, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0,
    -0x42, 0x65, 0x6c, 0x61, 0x72, 0x75, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d,
    -0x65, 0x0, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x20, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x53, 0x74, 0x61,
    -0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x61, 0x70, 0x65, 0x20, 0x56, 0x65, 0x72, 0x64,
    -0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x61, 0x75, 0x63,
    -0x61, 0x73, 0x75, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43,
    -0x65, 0x6e, 0x2e, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
    -0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x6d, 0x65, 0x72,
    -0x69, 0x63, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65,
    -0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
    -0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x42, 0x72, 0x61, 0x7a, 0x69, 0x6c, 0x69,
    -0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e,
    -0x74, 0x72, 0x61, 0x6c, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
    -0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
    -0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e,
    -0x74, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72,
    -0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
    -0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x28, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x29, 0x0, 0x43, 0x65,
    -0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0,
    -0x43, 0x68, 0x69, 0x6e, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0,
    -0x44, 0x61, 0x74, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
    -0x6d, 0x65, 0x0, 0x45, 0x2e, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72,
    -0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x2e, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x20,
    -0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x2e, 0x20, 0x53, 0x6f, 0x75,
    -0x74, 0x68, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
    -0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72,
    -0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
    -0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x28, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x29, 0x0, 0x45, 0x67,
    -0x79, 0x70, 0x74, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x6b,
    -0x61, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x62, 0x75, 0x72, 0x67, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
    -0x54, 0x69, 0x6d, 0x65, 0x0, 0x46, 0x69, 0x6a, 0x69, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54,
    -0x69, 0x6d, 0x65, 0x0, 0x46, 0x4c, 0x45, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d,
    -0x65, 0x0, 0x47, 0x65, 0x6f, 0x72, 0x67, 0x69, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
    -0x54, 0x69, 0x6d, 0x65, 0x0, 0x47, 0x4d, 0x54, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
    -0x6d, 0x65, 0x0, 0x47, 0x72, 0x65, 0x65, 0x6e, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72,
    -0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x47, 0x72, 0x65, 0x65, 0x6e, 0x77, 0x69, 0x63, 0x68, 0x20, 0x53, 0x74, 0x61,
    -0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x47, 0x54, 0x42, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
    -0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x48, 0x61, 0x77, 0x61, 0x69, 0x69, 0x61, 0x6e, 0x20, 0x53, 0x74,
    -0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x20, 0x53, 0x74,
    -0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x49, 0x72, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61,
    -0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x49, 0x73, 0x72, 0x61, 0x65, 0x6c, 0x20, 0x53, 0x74,
    -0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4a, 0x6f, 0x72, 0x64, 0x61, 0x6e, 0x20, 0x53,
    -0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4b, 0x61, 0x6c, 0x69, 0x6e, 0x69, 0x6e,
    -0x67, 0x72, 0x61, 0x64, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4b,
    -0x6f, 0x72, 0x65, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4c,
    -0x69, 0x62, 0x79, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4c,
    -0x69, 0x6e, 0x65, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
    -0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x61, 0x67, 0x61, 0x64, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
    -0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x69, 0x75, 0x73, 0x20, 0x53, 0x74,
    -0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x20, 0x45,
    -0x61, 0x73, 0x74, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x6f,
    -0x6e, 0x74, 0x65, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
    -0x6d, 0x65, 0x0, 0x4d, 0x6f, 0x72, 0x6f, 0x63, 0x63, 0x6f, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
    -0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
    -0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x28, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x29, 0x0, 0x4d, 0x6f, 0x75,
    -0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0,
    -0x4d, 0x79, 0x61, 0x6e, 0x6d, 0x61, 0x72, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d,
    -0x65, 0x0, 0x4e, 0x2e, 0x20, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x53, 0x74,
    -0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x61, 0x6d, 0x69, 0x62, 0x69, 0x61, 0x20,
    -0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x65, 0x70, 0x61, 0x6c, 0x20,
    -0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x65, 0x77, 0x20, 0x5a, 0x65,
    -0x61, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0,
    -0x4e, 0x65, 0x77, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72,
    -0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x45, 0x61,
    -0x73, 0x74, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x6f, 0x72,
    -0x74, 0x68, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d,
    -0x65, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53, 0x41, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72,
    -0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x2e, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x20, 0x53, 0x74, 0x61,
    +0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x6c, 0x65, 0x75, 0x74, 0x69, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61,
    +0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x6c, 0x74, 0x61, 0x69, 0x20, 0x53, 0x74, 0x61,
    +0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x72, 0x61, 0x62, 0x20, 0x53, 0x74, 0x61, 0x6e,
    +0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x72, 0x61, 0x62, 0x69, 0x61, 0x6e, 0x20, 0x53, 0x74,
    +0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x72, 0x61, 0x62, 0x69, 0x63, 0x20, 0x53,
    +0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69,
    +0x6e, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x73, 0x74,
    +0x72, 0x61, 0x6b, 0x68, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65,
    +0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54,
    +0x69, 0x6d, 0x65, 0x0, 0x41, 0x55, 0x53, 0x20, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x53, 0x74, 0x61, 0x6e,
    +0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x75, 0x73, 0x20, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61,
    +0x6c, 0x20, 0x57, 0x2e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41,
    +0x55, 0x53, 0x20, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
    +0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x7a, 0x65, 0x72, 0x62, 0x61, 0x69, 0x6a, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e,
    +0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x7a, 0x6f, 0x72, 0x65, 0x73, 0x20, 0x53, 0x74, 0x61,
    +0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x42, 0x61, 0x68, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61,
    +0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x42, 0x61, 0x6e, 0x67, 0x6c, 0x61, 0x64, 0x65, 0x73,
    +0x68, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x42, 0x65, 0x6c, 0x61,
    +0x72, 0x75, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x42, 0x6f,
    +0x75, 0x67, 0x61, 0x69, 0x6e, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
    +0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x20, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20,
    +0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x61, 0x70, 0x65, 0x20, 0x56,
    +0x65, 0x72, 0x64, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43,
    +0x61, 0x75, 0x63, 0x61, 0x73, 0x75, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d,
    +0x65, 0x0, 0x43, 0x65, 0x6e, 0x2e, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61,
    +0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41,
    +0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65,
    +0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
    +0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x42, 0x72, 0x61, 0x7a,
    +0x69, 0x6c, 0x69, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0,
    +0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
    +0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x45, 0x75, 0x72,
    +0x6f, 0x70, 0x65, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0,
    +0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53, 0x74, 0x61, 0x6e,
    +0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x53, 0x74,
    +0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x28, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x29,
    +0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
    +0x6d, 0x65, 0x0, 0x43, 0x68, 0x69, 0x6e, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
    +0x6d, 0x65, 0x0, 0x43, 0x68, 0x61, 0x74, 0x68, 0x61, 0x6d, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x53,
    +0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x75, 0x62, 0x61, 0x20, 0x53, 0x74,
    +0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x44, 0x61, 0x74, 0x65, 0x6c, 0x69, 0x6e, 0x65,
    +0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x2e, 0x20, 0x41, 0x66,
    +0x72, 0x69, 0x63, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45,
    +0x2e, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
    +0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x2e, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e,
    +0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x2e, 0x20, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x41,
    +0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65,
    +0x0, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
    +0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x53, 0x74, 0x61,
    +0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x53,
    +0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x28, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f,
    +0x29, 0x0, 0x45, 0x67, 0x79, 0x70, 0x74, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d,
    +0x65, 0x0, 0x45, 0x6b, 0x61, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x62, 0x75, 0x72, 0x67, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
    +0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x46, 0x69, 0x6a, 0x69, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
    +0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x46, 0x4c, 0x45, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
    +0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x47, 0x65, 0x6f, 0x72, 0x67, 0x69, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
    +0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x47, 0x4d, 0x54, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72,
    +0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x47, 0x72, 0x65, 0x65, 0x6e, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x74, 0x61,
    +0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x47, 0x72, 0x65, 0x65, 0x6e, 0x77, 0x69, 0x63, 0x68,
    +0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x47, 0x54, 0x42, 0x20, 0x53,
    +0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x48, 0x61, 0x69, 0x74, 0x69, 0x20, 0x53,
    +0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x48, 0x61, 0x77, 0x61, 0x69, 0x69, 0x61,
    +0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x49, 0x6e, 0x64, 0x69,
    +0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x49, 0x72, 0x61, 0x6e,
    +0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x49, 0x73, 0x72, 0x61, 0x65,
    +0x6c, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4a, 0x6f, 0x72, 0x64,
    +0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4b, 0x61, 0x6c,
    +0x69, 0x6e, 0x69, 0x6e, 0x67, 0x72, 0x61, 0x64, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
    +0x6d, 0x65, 0x0, 0x4b, 0x6f, 0x72, 0x65, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
    +0x6d, 0x65, 0x0, 0x4c, 0x69, 0x62, 0x79, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
    +0x6d, 0x65, 0x0, 0x4c, 0x69, 0x6e, 0x65, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e,
    +0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4c, 0x6f, 0x72, 0x64, 0x20, 0x48, 0x6f, 0x77, 0x65, 0x20,
    +0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x61, 0x67, 0x61, 0x64, 0x61,
    +0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x61, 0x67, 0x61,
    +0x6c, 0x6c, 0x61, 0x6e, 0x65, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65,
    +0x0, 0x4d, 0x61, 0x72, 0x71, 0x75, 0x65, 0x73, 0x61, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
    +0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x69, 0x75, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
    +0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x20, 0x45, 0x61, 0x73, 0x74,
    +0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x6f, 0x6e, 0x74, 0x65,
    +0x76, 0x69, 0x64, 0x65, 0x6f, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0,
    +0x4d, 0x6f, 0x72, 0x6f, 0x63, 0x63, 0x6f, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d,
    +0x65, 0x0, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
    +0x54, 0x69, 0x6d, 0x65, 0x20, 0x28, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x29, 0x0, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x61,
    +0x69, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x79, 0x61,
    +0x6e, 0x6d, 0x61, 0x72, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e,
    +0x2e, 0x20, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
    +0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x61, 0x6d, 0x69, 0x62, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61,
    +0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x65, 0x70, 0x61, 0x6c, 0x20, 0x53, 0x74, 0x61,
    +0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x65, 0x77, 0x20, 0x5a, 0x65, 0x61, 0x6c, 0x61,
    +0x6e, 0x64, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x65, 0x77,
    +0x66, 0x6f, 0x75, 0x6e, 0x64, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54,
    +0x69, 0x6d, 0x65, 0x0, 0x4e, 0x6f, 0x72, 0x66, 0x6f, 0x6c, 0x6b, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
    +0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x45, 0x61, 0x73,
    +0x74, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x6f, 0x72, 0x74,
    +0x68, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65,
    +0x0, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x4b, 0x6f, 0x72, 0x65, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72,
    +0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4f, 0x6d, 0x73, 0x6b, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
    +0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53, 0x41, 0x20, 0x53, 0x74, 0x61,
     0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53,
    -0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x50, 0x61, 0x6b, 0x69, 0x73, 0x74, 0x61,
    -0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x50, 0x61, 0x72, 0x61,
    -0x67, 0x75, 0x61, 0x79, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x52,
    -0x6f, 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65,
    -0x0, 0x52, 0x75, 0x73, 0x73, 0x69, 0x61, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x5a, 0x6f, 0x6e, 0x65, 0x20, 0x33, 0x0,
    -0x52, 0x75, 0x73, 0x73, 0x69, 0x61, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x5a, 0x6f, 0x6e, 0x65, 0x20, 0x31, 0x30, 0x0,
    -0x52, 0x75, 0x73, 0x73, 0x69, 0x61, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x5a, 0x6f, 0x6e, 0x65, 0x20, 0x31, 0x31, 0x0,
    -0x52, 0x75, 0x73, 0x73, 0x69, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d,
    -0x65, 0x0, 0x53, 0x41, 0x20, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72,
    -0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x41, 0x20, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53, 0x74,
    -0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x41, 0x20, 0x57, 0x65, 0x73, 0x74, 0x65,
    -0x72, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x61, 0x6d,
    -0x6f, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x45, 0x20,
    -0x41, 0x73, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53,
    -0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
    -0x6d, 0x65, 0x0, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e,
    -0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x72, 0x69, 0x20, 0x4c, 0x61, 0x6e, 0x6b, 0x61, 0x20,
    -0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x79, 0x72, 0x69, 0x61, 0x20,
    -0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x61, 0x69, 0x70, 0x65, 0x69,
    -0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x61, 0x73, 0x6d, 0x61,
    -0x6e, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x6f,
    -0x6b, 0x79, 0x6f, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x6f,
    -0x6e, 0x67, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x75,
    -0x72, 0x6b, 0x65, 0x79, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x55,
    -0x6c, 0x61, 0x61, 0x6e, 0x62, 0x61, 0x61, 0x74, 0x61, 0x72, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
    -0x54, 0x69, 0x6d, 0x65, 0x0, 0x55, 0x53, 0x20, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e,
    -0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x55, 0x53, 0x20, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69,
    -0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x55, 0x54, 0x43, 0x2d,
    -0x30, 0x32, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x31, 0x31, 0x0, 0x55, 0x54, 0x43, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x32,
    -0x0, 0x56, 0x65, 0x6e, 0x65, 0x7a, 0x75, 0x65, 0x6c, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
    -0x54, 0x69, 0x6d, 0x65, 0x0, 0x56, 0x6c, 0x61, 0x64, 0x69, 0x76, 0x6f, 0x73, 0x74, 0x6f, 0x6b, 0x20, 0x53, 0x74, 0x61,
    -0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x2e, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61,
    -0x6c, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x2e,
    -0x20, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e,
    -0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x2e, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x20,
    -0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x65, 0x73, 0x74, 0x20, 0x41,
    -0x73, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x65,
    -0x73, 0x74, 0x20, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
    -0x54, 0x69, 0x6d, 0x65, 0x0, 0x59, 0x61, 0x6b, 0x75, 0x74, 0x73, 0x6b, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72,
    -0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x4b, 0x6f, 0x72, 0x65, 0x61, 0x20, 0x53,
    -0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0
    +0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
    +0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x28, 0x4d, 0x65, 0x78, 0x69,
    +0x63, 0x6f, 0x29, 0x0, 0x50, 0x61, 0x6b, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72,
    +0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x50, 0x61, 0x72, 0x61, 0x67, 0x75, 0x61, 0x79, 0x20, 0x53, 0x74, 0x61, 0x6e,
    +0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x52, 0x6f, 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x53, 0x74,
    +0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x52, 0x75, 0x73, 0x73, 0x69, 0x61, 0x20, 0x54,
    +0x69, 0x6d, 0x65, 0x20, 0x5a, 0x6f, 0x6e, 0x65, 0x20, 0x33, 0x0, 0x52, 0x75, 0x73, 0x73, 0x69, 0x61, 0x20, 0x54, 0x69,
    +0x6d, 0x65, 0x20, 0x5a, 0x6f, 0x6e, 0x65, 0x20, 0x31, 0x30, 0x0, 0x52, 0x75, 0x73, 0x73, 0x69, 0x61, 0x20, 0x54, 0x69,
    +0x6d, 0x65, 0x20, 0x5a, 0x6f, 0x6e, 0x65, 0x20, 0x31, 0x31, 0x0, 0x52, 0x75, 0x73, 0x73, 0x69, 0x61, 0x6e, 0x20, 0x53,
    +0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x41, 0x20, 0x45, 0x61, 0x73, 0x74,
    +0x65, 0x72, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x41,
    +0x20, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
    +0x6d, 0x65, 0x0, 0x53, 0x41, 0x20, 0x57, 0x65, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
    +0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x61, 0x69, 0x6e, 0x74, 0x20, 0x50, 0x69, 0x65, 0x72, 0x72, 0x65,
    +0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x61, 0x6b, 0x68, 0x61,
    +0x6c, 0x69, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x61,
    +0x6d, 0x6f, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x61,
    +0x6f, 0x20, 0x54, 0x6f, 0x6d, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65,
    +0x0, 0x53, 0x61, 0x72, 0x61, 0x74, 0x6f, 0x76, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
    +0x6d, 0x65, 0x0, 0x53, 0x45, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
    +0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
    +0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63,
    +0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x72, 0x69, 0x20,
    +0x4c, 0x61, 0x6e, 0x6b, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0,
    +0x53, 0x75, 0x64, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0,
    +0x53, 0x79, 0x72, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0,
    +0x54, 0x61, 0x69, 0x70, 0x65, 0x69, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65,
    +0x0, 0x54, 0x61, 0x73, 0x6d, 0x61, 0x6e, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54,
    +0x69, 0x6d, 0x65, 0x0, 0x54, 0x6f, 0x63, 0x61, 0x6e, 0x74, 0x69, 0x6e, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
    +0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x6f, 0x6b, 0x79, 0x6f, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
    +0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x6f, 0x6d, 0x73, 0x6b, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
    +0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x6f, 0x6e, 0x67, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
    +0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x62, 0x61, 0x69, 0x6b, 0x61, 0x6c, 0x20,
    +0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x75, 0x72, 0x6b, 0x65, 0x79,
    +0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x75, 0x72, 0x6b, 0x73,
    +0x20, 0x41, 0x6e, 0x64, 0x20, 0x43, 0x61, 0x69, 0x63, 0x6f, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
    +0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x55, 0x6c, 0x61, 0x61, 0x6e, 0x62, 0x61, 0x61, 0x74, 0x61, 0x72, 0x20, 0x53, 0x74,
    +0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x55, 0x53, 0x20, 0x45, 0x61, 0x73, 0x74, 0x65,
    +0x72, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x55, 0x53, 0x20,
    +0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
    +0x6d, 0x65, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x31, 0x31, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x39, 0x0, 0x55, 0x54, 0x43,
    +0x2d, 0x30, 0x38, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x32, 0x0, 0x55, 0x54, 0x43, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31,
    +0x32, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x33, 0x0, 0x56, 0x65, 0x6e, 0x65, 0x7a, 0x75, 0x65, 0x6c, 0x61, 0x20, 0x53,
    +0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x56, 0x6c, 0x61, 0x64, 0x69, 0x76, 0x6f,
    +0x73, 0x74, 0x6f, 0x6b, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57,
    +0x2e, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
    +0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x2e, 0x20, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x66, 0x72,
    +0x69, 0x63, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x2e,
    +0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d,
    +0x65, 0x0, 0x57, 0x2e, 0x20, 0x4d, 0x6f, 0x6e, 0x67, 0x6f, 0x6c, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
    +0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x65, 0x73, 0x74, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x53, 0x74,
    +0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x65, 0x73, 0x74, 0x20, 0x42, 0x61, 0x6e,
    +0x6b, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x65, 0x73, 0x74,
    +0x20, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
    +0x6d, 0x65, 0x0, 0x59, 0x61, 0x6b, 0x75, 0x74, 0x73, 0x6b, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
    +0x54, 0x69, 0x6d, 0x65, 0x0
     };
     
     static const char ianaIdData[] = {
    +0x41, 0x73, 0x69, 0x61, 0x2f, 0x48, 0x6f, 0x76, 0x64, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x54, 0x61,
    +0x72, 0x61, 0x77, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x2d, 0x61, 0x75,
    +0x2d, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x68, 0x61, 0x6e, 0x67, 0x68, 0x61,
    +0x69, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x42, 0x61, 0x72, 0x74, 0x68, 0x65, 0x6c,
    +0x65, 0x6d, 0x79, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x69, 0x73, 0x68, 0x6b, 0x65, 0x6b, 0x0, 0x41, 0x6e, 0x74,
    +0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x79, 0x6f, 0x77, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69,
    +0x63, 0x2f, 0x43, 0x68, 0x61, 0x74, 0x68, 0x61, 0x6d, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f,
    +0x6e, 0x74, 0x73, 0x65, 0x72, 0x72, 0x61, 0x74, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x42,
    +0x72, 0x69, 0x73, 0x62, 0x61, 0x6e, 0x65, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x4c, 0x69,
    +0x6e, 0x64, 0x65, 0x6d, 0x61, 0x6e, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x34, 0x0, 0x41, 0x73,
    +0x69, 0x61, 0x2f, 0x41, 0x73, 0x68, 0x67, 0x61, 0x62, 0x61, 0x74, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
    +0x4e, 0x6f, 0x72, 0x6f, 0x6e, 0x68, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x6f, 0x73, 0x74,
    +0x61, 0x5f, 0x52, 0x69, 0x63, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x73, 0x6d, 0x65, 0x72, 0x61,
    +0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x73, 0x65, 0x79, 0x0, 0x41, 0x73,
    +0x69, 0x61, 0x2f, 0x4a, 0x61, 0x6b, 0x61, 0x72, 0x74, 0x61, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x50, 0x6f, 0x6e, 0x74,
    +0x69, 0x61, 0x6e, 0x61, 0x6b, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x6f, 0x74,
    +0x68, 0x65, 0x72, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x72, 0x6e, 0x61, 0x75, 0x6c, 0x0, 0x41, 0x6d,
    +0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x77, 0x65, 0x72, 0x5f, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x65, 0x73, 0x0,
    +0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x6f, 0x6d, 0x69, 0x6e, 0x69, 0x63, 0x61, 0x0, 0x50, 0x61, 0x63,
    +0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x5f, 0x4d, 0x6f, 0x72, 0x65, 0x73, 0x62, 0x79, 0x0, 0x41, 0x75,
    +0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x53, 0x79, 0x64, 0x6e, 0x65, 0x79, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72,
    +0x61, 0x6c, 0x69, 0x61, 0x2f, 0x4d, 0x65, 0x6c, 0x62, 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63,
    +0x61, 0x2f, 0x45, 0x6c, 0x5f, 0x41, 0x61, 0x69, 0x75, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53,
    +0x61, 0x6f, 0x5f, 0x50, 0x61, 0x75, 0x6c, 0x6f, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4d, 0x61, 0x6a,
    +0x75, 0x72, 0x6f, 0x20, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4b, 0x77, 0x61, 0x6a, 0x61, 0x6c, 0x65, 0x69,
    +0x6e, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x45, 0x6e, 0x64, 0x65, 0x72, 0x62, 0x75, 0x72, 0x79, 0x0,
    +0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x70, 0x75, 0x74, 0x6f, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
    +0x61, 0x2f, 0x52, 0x69, 0x6f, 0x5f, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
    +0x2f, 0x45, 0x69, 0x72, 0x75, 0x6e, 0x65, 0x70, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x50, 0x61, 0x72,
    +0x69, 0x73, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45, 0x64, 0x6d, 0x6f, 0x6e, 0x74, 0x6f, 0x6e, 0x20,
    +0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x5f, 0x42, 0x61,
    +0x79, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x75, 0x76, 0x69, 0x6b, 0x20, 0x41, 0x6d, 0x65,
    +0x72, 0x69, 0x63, 0x61, 0x2f, 0x59, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6b, 0x6e, 0x69, 0x66, 0x65, 0x0, 0x41, 0x73, 0x69,
    +0x61, 0x2f, 0x52, 0x61, 0x6e, 0x67, 0x6f, 0x6f, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x75,
    +0x69, 0x61, 0x62, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x6d, 0x70, 0x6f, 0x5f, 0x47,
    +0x72, 0x61, 0x6e, 0x64, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, 0x61, 0x64, 0x75, 0x7a, 0x0, 0x45,
    +0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x48, 0x65, 0x6c, 0x73, 0x69, 0x6e, 0x6b, 0x69, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e,
    +0x74, 0x69, 0x63, 0x2f, 0x53, 0x74, 0x61, 0x6e, 0x6c, 0x65, 0x79, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f,
    +0x4e, 0x6f, 0x72, 0x66, 0x6f, 0x6c, 0x6b, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x31, 0x30, 0x0, 0x45,
    +0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x5a, 0x61, 0x67, 0x72, 0x65, 0x62, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61,
    +0x74, 0x6d, 0x61, 0x6e, 0x64, 0x75, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x6f, 0x66, 0x69, 0x61, 0x0,
    +0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x75, 0x73, 0x63, 0x61, 0x74, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4d,
    +0x61, 0x6c, 0x64, 0x69, 0x76, 0x65, 0x73, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x61, 0x64, 0x72, 0x69,
    +0x64, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x65, 0x75, 0x74, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63,
    +0x61, 0x2f, 0x43, 0x6f, 0x6e, 0x61, 0x6b, 0x72, 0x79, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x64, 0x65, 0x6e, 0x0,
    +0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x69, 0x6d, 0x66, 0x65, 0x72, 0x6f, 0x70, 0x6f, 0x6c, 0x0, 0x41, 0x66,
    +0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x62, 0x61, 0x62, 0x61, 0x6e, 0x65, 0x0, 0x41, 0x72, 0x63, 0x74, 0x69, 0x63, 0x2f,
    +0x4c, 0x6f, 0x6e, 0x67, 0x79, 0x65, 0x61, 0x72, 0x62, 0x79, 0x65, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61,
    +0x67, 0x68, 0x64, 0x61, 0x64, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4d, 0x69, 0x64, 0x77, 0x61, 0x79,
    +0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x75, 0x77, 0x61, 0x69, 0x74, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f,
    +0x46, 0x72, 0x65, 0x65, 0x74, 0x6f, 0x77, 0x6e, 0x0, 0x43, 0x53, 0x54, 0x36, 0x43, 0x44, 0x54, 0x0, 0x50, 0x61, 0x63,
    +0x69, 0x66, 0x69, 0x63, 0x2f, 0x52, 0x61, 0x72, 0x6f, 0x74, 0x6f, 0x6e, 0x67, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63,
    +0x61, 0x2f, 0x42, 0x72, 0x61, 0x7a, 0x7a, 0x61, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
    +0x61, 0x2f, 0x50, 0x75, 0x6e, 0x74, 0x61, 0x5f, 0x41, 0x72, 0x65, 0x6e, 0x61, 0x73, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47,
    +0x4d, 0x54, 0x2b, 0x31, 0x31, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x56, 0x61, 0x6e, 0x63, 0x6f, 0x75,
    +0x76, 0x65, 0x72, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x77, 0x73, 0x6f, 0x6e, 0x20, 0x41,
    +0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x57, 0x68, 0x69, 0x74, 0x65, 0x68, 0x6f, 0x72, 0x73, 0x65, 0x0, 0x41, 0x73,
    +0x69, 0x61, 0x2f, 0x59, 0x65, 0x72, 0x65, 0x76, 0x61, 0x6e, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x6f,
    +0x6e, 0x61, 0x63, 0x6f, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x75, 0x73, 0x61, 0x6b, 0x61, 0x0, 0x45,
    +0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4b, 0x69, 0x65, 0x76, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x55, 0x7a,
    +0x68, 0x67, 0x6f, 0x72, 0x6f, 0x64, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x5a, 0x61, 0x70, 0x6f, 0x72, 0x6f,
    +0x7a, 0x68, 0x79, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x73, 0x75, 0x6e, 0x63, 0x69, 0x6f,
    +0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x6d, 0x6d, 0x61, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
    +0x2f, 0x41, 0x72, 0x61, 0x67, 0x75, 0x61, 0x69, 0x6e, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x65, 0x68, 0x72,
    +0x61, 0x6e, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x76, 0x69, 0x73, 0x0,
     0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x50, 0x72, 0x61, 0x67, 0x75, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
    -0x61, 0x2f, 0x54, 0x69, 0x6a, 0x75, 0x61, 0x6e, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61,
    -0x6e, 0x74, 0x61, 0x5f, 0x49, 0x73, 0x61, 0x62, 0x65, 0x6c, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4d, 0x61,
    -0x68, 0x65, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x72, 0x69, 0x70, 0x6f, 0x6c, 0x69, 0x0, 0x41, 0x6d,
    -0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6c, 0x61, 0x6e, 0x63, 0x2d, 0x53, 0x61, 0x62, 0x6c, 0x6f, 0x6e, 0x0, 0x41,
    -0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x75, 0x6a, 0x75, 0x6d, 0x62, 0x75, 0x72, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f,
    -0x70, 0x65, 0x2f, 0x53, 0x74, 0x6f, 0x63, 0x6b, 0x68, 0x6f, 0x6c, 0x6d, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
    -0x2f, 0x46, 0x61, 0x6b, 0x61, 0x6f, 0x66, 0x6f, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x79,
    -0x65, 0x6e, 0x6e, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x5f, 0x6f, 0x66,
    -0x5f, 0x53, 0x70, 0x61, 0x69, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x56, 0x61, 0x6e, 0x63, 0x6f,
    -0x75, 0x76, 0x65, 0x72, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x77, 0x73, 0x6f, 0x6e, 0x20,
    -0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x57, 0x68, 0x69, 0x74, 0x65, 0x68, 0x6f, 0x72, 0x73, 0x65, 0x0, 0x45,
    -0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x32, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45, 0x6c,
    -0x5f, 0x53, 0x61, 0x6c, 0x76, 0x61, 0x64, 0x6f, 0x72, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x61, 0x6b, 0x61, 0x73,
    -0x73, 0x61, 0x72, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x61, 0x72, 0x69, 0x65, 0x68, 0x61, 0x6d, 0x6e,
    -0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x31, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x46,
    -0x75, 0x6e, 0x61, 0x66, 0x75, 0x74, 0x69, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x56,
    -0x69, 0x6e, 0x63, 0x65, 0x6e, 0x74, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x69, 0x67, 0x61, 0x6c, 0x69,
    -0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x75, 0x78, 0x65, 0x6d, 0x62, 0x6f, 0x75, 0x72, 0x67, 0x0, 0x41,
    -0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4f, 0x75, 0x61, 0x67, 0x61, 0x64, 0x6f, 0x75, 0x67, 0x6f, 0x75, 0x0, 0x41, 0x73,
    -0x69, 0x61, 0x2f, 0x42, 0x69, 0x73, 0x68, 0x6b, 0x65, 0x6b, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x75,
    -0x6e, 0x69, 0x73, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x69, 0x62, 0x72, 0x65, 0x76, 0x69, 0x6c, 0x6c,
    -0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x65, 0x67, 0x75, 0x63, 0x69, 0x67, 0x61, 0x6c, 0x70,
    -0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x50, 0x68, 0x6e, 0x6f, 0x6d, 0x5f, 0x50, 0x65, 0x6e, 0x68, 0x0, 0x41, 0x73,
    -0x69, 0x61, 0x2f, 0x4d, 0x61, 0x6e, 0x69, 0x6c, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x6e,
    -0x67, 0x75, 0x69, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x67, 0x68, 0x64, 0x61, 0x64, 0x0, 0x45, 0x75, 0x72,
    -0x6f, 0x70, 0x65, 0x2f, 0x42, 0x72, 0x75, 0x73, 0x73, 0x65, 0x6c, 0x73, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x72,
    -0x65, 0x64, 0x6e, 0x65, 0x6b, 0x6f, 0x6c, 0x79, 0x6d, 0x73, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x72, 0x75,
    -0x6d, 0x71, 0x69, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x68, 0x72, 0x61, 0x69, 0x6e, 0x0, 0x41, 0x73, 0x69,
    -0x61, 0x2f, 0x44, 0x69, 0x6c, 0x69, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x54, 0x61, 0x6c, 0x6c, 0x69, 0x6e,
    -0x6e, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x75, 0x61, 0x6b, 0x63, 0x68, 0x6f, 0x74, 0x74, 0x0,
    -0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x75, 0x62, 0x75, 0x6d, 0x62, 0x61, 0x73, 0x68, 0x69, 0x0, 0x45, 0x75,
    -0x72, 0x6f, 0x70, 0x65, 0x2f, 0x50, 0x61, 0x72, 0x69, 0x73, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x59, 0x65, 0x6b, 0x61,
    -0x74, 0x65, 0x72, 0x69, 0x6e, 0x62, 0x75, 0x72, 0x67, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x61,
    -0x73, 0x73, 0x61, 0x75, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x72, 0x6f, 0x6e, 0x68, 0x61,
    -0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x68, 0x69, 0x61, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47,
    -0x4d, 0x54, 0x2d, 0x38, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x68, 0x61, 0x72, 0x74, 0x6f, 0x75, 0x6d,
    -0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x45, 0x66, 0x61, 0x74, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69,
    -0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x65, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
    -0x61, 0x2f, 0x54, 0x6f, 0x72, 0x74, 0x6f, 0x6c, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x61, 0x6d,
    -0x70, 0x61, 0x6c, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x75, 0x61, 0x6e, 0x64, 0x61, 0x0, 0x45,
    -0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x43, 0x68, 0x69, 0x73, 0x69, 0x6e, 0x61, 0x75, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66,
    -0x69, 0x63, 0x2f, 0x4b, 0x69, 0x72, 0x69, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d,
    -0x54, 0x2d, 0x31, 0x33, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x6f, 0x5f, 0x44,
    -0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x6f, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x47, 0x75, 0x65, 0x72, 0x6e, 0x73,
    -0x65, 0x79, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4b, 0x69, 0x65, 0x76, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70,
    -0x65, 0x2f, 0x55, 0x7a, 0x68, 0x67, 0x6f, 0x72, 0x6f, 0x64, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x5a, 0x61,
    -0x70, 0x6f, 0x72, 0x6f, 0x7a, 0x68, 0x79, 0x65, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x61, 0x62, 0x6f,
    -0x72, 0x6f, 0x6e, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x75, 0x61, 0x6c, 0x61, 0x5f, 0x4c, 0x75, 0x6d, 0x70,
    -0x75, 0x72, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x75, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x0, 0x50, 0x61, 0x63, 0x69,
    -0x66, 0x69, 0x63, 0x2f, 0x50, 0x61, 0x67, 0x6f, 0x5f, 0x50, 0x61, 0x67, 0x6f, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61,
    -0x2f, 0x46, 0x72, 0x65, 0x65, 0x74, 0x6f, 0x77, 0x6e, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x67,
    -0x61, 0x64, 0x69, 0x73, 0x68, 0x75, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x53, 0x6f, 0x75, 0x74,
    -0x68, 0x5f, 0x47, 0x65, 0x6f, 0x72, 0x67, 0x69, 0x61, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x0, 0x41, 0x66,
    -0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x6f, 0x75, 0x61, 0x6c, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x68, 0x69,
    -0x6d, 0x70, 0x68, 0x75, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x41, 0x6d, 0x73, 0x74, 0x65, 0x72, 0x64, 0x61,
    -0x6d, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x52, 0x69, 0x67, 0x61, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e,
    -0x2f, 0x43, 0x6f, 0x6d, 0x6f, 0x72, 0x6f, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4e, 0x6f, 0x76, 0x6f, 0x73, 0x69, 0x62,
    -0x69, 0x72, 0x73, 0x6b, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4f, 0x6d, 0x73, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f,
    -0x56, 0x69, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6e, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x50, 0x6f, 0x64,
    -0x67, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x6f, 0x66, 0x69, 0x61, 0x0,
    -0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x41, 0x7a, 0x6f, 0x72, 0x65, 0x73, 0x0, 0x50, 0x61, 0x63, 0x69,
    -0x66, 0x69, 0x63, 0x2f, 0x4e, 0x61, 0x75, 0x72, 0x75, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x70,
    -0x75, 0x74, 0x6f, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x65, 0x72, 0x6c, 0x69, 0x6e, 0x20, 0x45, 0x75,
    -0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x65, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
    -0x61, 0x2f, 0x4b, 0x72, 0x61, 0x6c, 0x65, 0x6e, 0x64, 0x69, 0x6a, 0x6b, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
    -0x2f, 0x4e, 0x6f, 0x75, 0x6d, 0x65, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x65, 0x68, 0x72, 0x61, 0x6e, 0x0,
    -0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x68, 0x61, 0x6b, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c,
    -0x6f, 0x73, 0x5f, 0x41, 0x6e, 0x67, 0x65, 0x6c, 0x65, 0x73, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x6f,
    -0x6e, 0x61, 0x63, 0x6f, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x41, 0x6e, 0x74, 0x61, 0x6e, 0x61, 0x6e, 0x61,
    -0x72, 0x69, 0x76, 0x6f, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x49, 0x72, 0x6b, 0x75, 0x74, 0x73, 0x6b, 0x0, 0x41, 0x6e,
    -0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x56, 0x6f, 0x73, 0x74, 0x6f, 0x6b, 0x0, 0x45, 0x75, 0x72, 0x6f,
    -0x70, 0x65, 0x2f, 0x54, 0x69, 0x72, 0x61, 0x6e, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x72,
    -0x65, 0x6e, 0x61, 0x64, 0x61, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x37, 0x0, 0x45, 0x75, 0x72, 0x6f,
    -0x70, 0x65, 0x2f, 0x4c, 0x69, 0x73, 0x62, 0x6f, 0x6e, 0x20, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x4d,
    -0x61, 0x64, 0x65, 0x69, 0x72, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x73, 0x68, 0x6b, 0x65, 0x6e, 0x74,
    -0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x61, 0x6d, 0x61, 0x72, 0x6b, 0x61, 0x6e, 0x64, 0x0, 0x41, 0x6d, 0x65, 0x72,
    -0x69, 0x63, 0x61, 0x2f, 0x4f, 0x6a, 0x69, 0x6e, 0x61, 0x67, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42,
    -0x6c, 0x61, 0x6e, 0x74, 0x79, 0x72, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a, 0x61, 0x6d, 0x61,
    -0x69, 0x63, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x6f, 0x6e, 0x61, 0x6b, 0x72, 0x79, 0x0, 0x41,
    -0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x69, 0x6e, 0x73, 0x68, 0x61, 0x73, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66,
    -0x69, 0x63, 0x2f, 0x4a, 0x6f, 0x68, 0x6e, 0x73, 0x74, 0x6f, 0x6e, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69,
    -0x63, 0x61, 0x2f, 0x52, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x57,
    -0x61, 0x6c, 0x6c, 0x69, 0x73, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x61, 0x69, 0x67, 0x6f, 0x6e, 0x0, 0x41, 0x66,
    -0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x69, 0x72, 0x6f, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x52, 0x6f,
    -0x6d, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x77, 0x65, 0x72, 0x5f, 0x50, 0x72, 0x69,
    -0x6e, 0x63, 0x65, 0x73, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x52, 0x61, 0x6e, 0x67, 0x6f, 0x6f, 0x6e, 0x0, 0x41, 0x6d,
    -0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x61, 0x6e, 0x61, 0x6d, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f,
    -0x45, 0x6c, 0x5f, 0x41, 0x61, 0x69, 0x75, 0x6e, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x47, 0x75, 0x61,
    -0x64, 0x61, 0x6c, 0x63, 0x61, 0x6e, 0x61, 0x6c, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4b, 0x61, 0x6c, 0x69,
    -0x6e, 0x69, 0x6e, 0x67, 0x72, 0x61, 0x64, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x6d, 0x6d, 0x61, 0x6e, 0x0, 0x45,
    -0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x75, 0x63, 0x68, 0x61, 0x72, 0x65, 0x73, 0x74, 0x0, 0x41, 0x66, 0x72, 0x69,
    -0x63, 0x61, 0x2f, 0x42, 0x69, 0x73, 0x73, 0x61, 0x75, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x6e,
    -0x5f, 0x4d, 0x61, 0x72, 0x69, 0x6e, 0x6f, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x75, 0x73, 0x68, 0x61, 0x6e, 0x62,
    -0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x6d, 0x63, 0x68, 0x61, 0x74, 0x6b, 0x61, 0x20, 0x41, 0x73, 0x69,
    -0x61, 0x2f, 0x41, 0x6e, 0x61, 0x64, 0x79, 0x72, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x61, 0x67, 0x6f,
    -0x73, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x75, 0x72, 0x61, 0x63, 0x61, 0x6f, 0x0, 0x41, 0x6d,
    -0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x68, 0x75, 0x61, 0x68, 0x75, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72,
    -0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x7a, 0x61, 0x74, 0x6c, 0x61, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x75,
    -0x73, 0x63, 0x61, 0x74, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x69, 0x6d, 0x61, 0x0, 0x45, 0x75,
    -0x72, 0x6f, 0x70, 0x65, 0x2f, 0x5a, 0x75, 0x72, 0x69, 0x63, 0x68, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63,
    -0x2f, 0x52, 0x65, 0x79, 0x6b, 0x6a, 0x61, 0x76, 0x69, 0x6b, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43,
    -0x61, 0x6e, 0x63, 0x75, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x65, 0x6e, 0x76, 0x65, 0x72,
    -0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6f, 0x69, 0x73, 0x65, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72,
    -0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x73, 0x65, 0x79, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
    -0x4d, 0x61, 0x6e, 0x61, 0x75, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6f, 0x61, 0x5f, 0x56,
    -0x69, 0x73, 0x74, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x6f, 0x5f, 0x56,
    -0x65, 0x6c, 0x68, 0x6f, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x6f, 0x2d, 0x4e, 0x6f,
    -0x76, 0x6f, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x0, 0x45, 0x74,
    -0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x30, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f,
    -0x4c, 0x75, 0x63, 0x69, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x61, 0x63, 0x61, 0x75, 0x0, 0x41, 0x66, 0x72,
    -0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x6c, 0x61, 0x62, 0x6f, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x52,
    -0x61, 0x72, 0x6f, 0x74, 0x6f, 0x6e, 0x67, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x6e, 0x6a,
    -0x75, 0x6c, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x34, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d,
    -0x61, 0x67, 0x61, 0x64, 0x61, 0x6e, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x72, 0x61, 0x74, 0x69, 0x73,
    -0x6c, 0x61, 0x76, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x41, 0x6e, 0x64, 0x6f, 0x72, 0x72, 0x61, 0x0,
    -0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x6e, 0x67, 0x6b, 0x6f, 0x6b, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54,
    -0x2d, 0x35, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x42, 0x6f, 0x75, 0x67, 0x61, 0x69, 0x6e, 0x76, 0x69,
    -0x6c, 0x6c, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, 0x61, 0x74, 0x69, 0x63, 0x61, 0x6e, 0x0, 0x41,
    -0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45, 0x64, 0x6d, 0x6f, 0x6e, 0x74, 0x6f, 0x6e, 0x20, 0x41, 0x6d, 0x65, 0x72,
    -0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x5f, 0x42, 0x61, 0x79, 0x20, 0x41, 0x6d,
    -0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x75, 0x76, 0x69, 0x6b, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
    -0x2f, 0x59, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6b, 0x6e, 0x69, 0x66, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
    -0x2f, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x61, 0x72, 0x69, 0x62, 0x6f, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69,
    -0x61, 0x2f, 0x53, 0x79, 0x64, 0x6e, 0x65, 0x79, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x4d,
    -0x65, 0x6c, 0x62, 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x72, 0x5f,
    -0x65, 0x73, 0x5f, 0x53, 0x61, 0x6c, 0x61, 0x61, 0x6d, 0x0, 0x4d, 0x53, 0x54, 0x37, 0x4d, 0x44, 0x54, 0x0, 0x41, 0x66,
    -0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x73, 0x65, 0x72, 0x75, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f,
    -0x4d, 0x61, 0x6a, 0x75, 0x72, 0x6f, 0x20, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4b, 0x77, 0x61, 0x6a, 0x61,
    -0x6c, 0x65, 0x69, 0x6e, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x61, 0x69, 0x72, 0x6f, 0x62, 0x69, 0x0,
    -0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x73, 0x68, 0x67, 0x61, 0x62, 0x61, 0x74, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x48,
    -0x6f, 0x6e, 0x67, 0x5f, 0x4b, 0x6f, 0x6e, 0x67, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x33, 0x0, 0x41,
    -0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x65, 0x6c, 0x69, 0x7a, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
    -0x61, 0x2f, 0x53, 0x61, 0x6f, 0x5f, 0x50, 0x61, 0x75, 0x6c, 0x6f, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d,
    -0x61, 0x64, 0x72, 0x69, 0x64, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x65, 0x75, 0x74, 0x61, 0x0, 0x41,
    -0x73, 0x69, 0x61, 0x2f, 0x4a, 0x61, 0x6b, 0x61, 0x72, 0x74, 0x61, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x50, 0x6f, 0x6e,
    -0x74, 0x69, 0x61, 0x6e, 0x61, 0x6b, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x39, 0x0, 0x41, 0x6d, 0x65,
    -0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69,
    -0x63, 0x61, 0x2f, 0x4a, 0x75, 0x6e, 0x65, 0x61, 0x75, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65,
    -0x74, 0x6c, 0x61, 0x6b, 0x61, 0x74, 0x6c, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x6d,
    -0x65, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x69, 0x74, 0x6b, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72,
    -0x69, 0x63, 0x61, 0x2f, 0x59, 0x61, 0x6b, 0x75, 0x74, 0x61, 0x74, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x43,
    -0x6f, 0x70, 0x65, 0x6e, 0x68, 0x61, 0x67, 0x65, 0x6e, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61,
    -0x2f, 0x4d, 0x63, 0x4d, 0x75, 0x72, 0x64, 0x6f, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x51, 0x61, 0x74, 0x61, 0x72, 0x0,
    -0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x72, 0x69, 0x67, 0x6f, 0x74, 0x0, 0x41, 0x6d, 0x65, 0x72,
    -0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x72, 0x62, 0x61, 0x64, 0x6f, 0x73, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
    -0x2f, 0x57, 0x61, 0x6b, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x48, 0x65, 0x6c, 0x73, 0x69, 0x6e, 0x6b,
    -0x69, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4d, 0x61, 0x79, 0x6f, 0x74, 0x74, 0x65, 0x0, 0x41, 0x74, 0x6c,
    -0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x46, 0x61, 0x65, 0x72, 0x6f, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
    -0x2f, 0x43, 0x6f, 0x72, 0x61, 0x6c, 0x5f, 0x48, 0x61, 0x72, 0x62, 0x6f, 0x75, 0x72, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47,
    -0x4d, 0x54, 0x2b, 0x31, 0x30, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x72, 0x61, 0x6a, 0x65, 0x76,
    -0x6f, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x62, 0x69, 0x6c, 0x69, 0x73, 0x69, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47,
    -0x4d, 0x54, 0x2b, 0x31, 0x31, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x63,
    -0x71, 0x75, 0x61, 0x72, 0x69, 0x65, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x5f,
    -0x4d, 0x6f, 0x72, 0x65, 0x73, 0x62, 0x79, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x73, 0x75, 0x6e,
    -0x63, 0x69, 0x6f, 0x6e, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x54, 0x61, 0x68, 0x69, 0x74, 0x69, 0x0,
    -0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x6d, 0x65, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63,
    -0x2f, 0x43, 0x61, 0x6e, 0x61, 0x72, 0x79, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a, 0x6f, 0x68, 0x61, 0x6e,
    -0x6e, 0x65, 0x73, 0x62, 0x75, 0x72, 0x67, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x41, 0x64,
    -0x65, 0x6c, 0x61, 0x69, 0x64, 0x65, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x42, 0x72, 0x6f,
    -0x6b, 0x65, 0x6e, 0x5f, 0x48, 0x69, 0x6c, 0x6c, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x53, 0x61, 0x69,
    -0x70, 0x61, 0x6e, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x53, 0x74, 0x61, 0x6e, 0x6c, 0x65, 0x79,
    -0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4e, 0x69, 0x63, 0x6f, 0x73, 0x69, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44,
    -0x75, 0x62, 0x61, 0x69, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4b, 0x65, 0x72, 0x67, 0x75, 0x65, 0x6c, 0x65,
    -0x6e, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x64, 0x6a, 0x61, 0x6d, 0x65, 0x6e, 0x61, 0x0, 0x45, 0x75,
    -0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x6b, 0x6f, 0x70, 0x6a, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x64, 0x65,
    -0x6e, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x41, 0x70, 0x69, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66,
    -0x69, 0x63, 0x2f, 0x48, 0x6f, 0x6e, 0x6f, 0x6c, 0x75, 0x6c, 0x75, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b,
    -0x31, 0x32, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x65, 0x72, 0x6d, 0x6f, 0x73, 0x69, 0x6c, 0x6c,
    -0x6f, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x4a, 0x6f, 0x68, 0x6e, 0x73, 0x0, 0x50,
    -0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x41, 0x75, 0x63, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x0, 0x45, 0x75, 0x72, 0x6f,
    -0x70, 0x65, 0x2f, 0x4d, 0x6f, 0x73, 0x63, 0x6f, 0x77, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x69, 0x6d,
    -0x66, 0x65, 0x72, 0x6f, 0x70, 0x6f, 0x6c, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, 0x6f, 0x6c, 0x67, 0x6f,
    -0x67, 0x72, 0x61, 0x64, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x0,
    -0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x62, 0x75, 0x6c, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x61,
    -0x6c, 0x74, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x75, 0x62, 0x61, 0x0, 0x41, 0x6d,
    +0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x5f, 0x6f, 0x66, 0x5f, 0x53, 0x70, 0x61, 0x69, 0x6e, 0x0, 0x41, 0x66, 0x72, 0x69,
    +0x63, 0x61, 0x2f, 0x47, 0x61, 0x62, 0x6f, 0x72, 0x6f, 0x6e, 0x65, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d,
    +0x35, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x75, 0x61, 0x79, 0x61, 0x71, 0x75, 0x69, 0x6c, 0x0,
    +0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x41, 0x74, 0x68, 0x65, 0x6e, 0x73, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e,
    +0x2f, 0x41, 0x6e, 0x74, 0x61, 0x6e, 0x61, 0x6e, 0x61, 0x72, 0x69, 0x76, 0x6f, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69,
    +0x63, 0x2f, 0x4a, 0x6f, 0x68, 0x6e, 0x73, 0x74, 0x6f, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a,
    +0x61, 0x6d, 0x61, 0x69, 0x63, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x43, 0x6f, 0x6c, 0x6f, 0x6d, 0x62, 0x6f, 0x0,
    +0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x65, 0x6c, 0x67, 0x72, 0x61, 0x64, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61,
    +0x2f, 0x41, 0x6c, 0x6d, 0x61, 0x74, 0x79, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x51, 0x6f, 0x73, 0x74, 0x61, 0x6e, 0x61,
    +0x79, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x33, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
    +0x2f, 0x43, 0x6f, 0x72, 0x61, 0x6c, 0x5f, 0x48, 0x61, 0x72, 0x62, 0x6f, 0x75, 0x72, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61,
    +0x6e, 0x2f, 0x43, 0x68, 0x61, 0x67, 0x6f, 0x73, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x48,
    +0x6f, 0x62, 0x61, 0x72, 0x74, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x43, 0x75, 0x72, 0x72,
    +0x69, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x75, 0x65, 0x72, 0x74, 0x6f, 0x5f, 0x52, 0x69,
    +0x63, 0x6f, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x4b, 0x69, 0x74, 0x74, 0x73, 0x0,
    +0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x5a, 0x75, 0x72, 0x69, 0x63, 0x68, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
    +0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x70, 0x6f, 0x6c, 0x69, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69,
    +0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x4d, 0x61, 0x72, 0x65, 0x6e, 0x67, 0x6f, 0x20, 0x41,
    +0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x56, 0x65, 0x76, 0x61, 0x79,
    +0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x6f, 0x6e, 0x61, 0x70, 0x65, 0x20, 0x50, 0x61, 0x63, 0x69,
    +0x66, 0x69, 0x63, 0x2f, 0x4b, 0x6f, 0x73, 0x72, 0x61, 0x65, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x47,
    +0x61, 0x6d, 0x62, 0x69, 0x65, 0x72, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x69, 0x61, 0x6d, 0x65, 0x79,
    +0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x65, 0x72, 0x6d, 0x6f, 0x73, 0x69, 0x6c, 0x6c, 0x6f, 0x0,
    +0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x67, 0x61, 0x64, 0x69, 0x73, 0x68, 0x75, 0x0, 0x45, 0x74, 0x63,
    +0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x37, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x42, 0x65, 0x72, 0x6d,
    +0x75, 0x64, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x72, 0x61, 0x72, 0x65, 0x0, 0x41, 0x73,
    +0x69, 0x61, 0x2f, 0x4d, 0x61, 0x63, 0x61, 0x75, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x6c, 0x61,
    +0x62, 0x6f, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x69, 0x75, 0x73, 0x0,
    +0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x54, 0x61, 0x6c, 0x6c, 0x69, 0x6e, 0x6e, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63,
    +0x61, 0x2f, 0x44, 0x61, 0x6b, 0x61, 0x72, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4f, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x73,
    +0x69, 0x61, 0x2f, 0x41, 0x71, 0x74, 0x61, 0x75, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x71, 0x74, 0x6f, 0x62, 0x65,
    +0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x74, 0x79, 0x72, 0x61, 0x75, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x51, 0x79,
    +0x7a, 0x79, 0x6c, 0x6f, 0x72, 0x64, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x72, 0x75, 0x6d, 0x71, 0x69, 0x0,
    +0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x52, 0x6f, 0x6d, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x49,
    +0x73, 0x6c, 0x65, 0x5f, 0x6f, 0x66, 0x5f, 0x4d, 0x61, 0x6e, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61,
    +0x72, 0x5f, 0x65, 0x73, 0x5f, 0x53, 0x61, 0x6c, 0x61, 0x61, 0x6d, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
    +0x54, 0x68, 0x75, 0x6c, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x6e, 0x6d, 0x61, 0x72,
    +0x6b, 0x73, 0x68, 0x61, 0x76, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x65, 0x67, 0x69, 0x6e,
    +0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x77, 0x69, 0x66, 0x74, 0x5f, 0x43, 0x75, 0x72, 0x72,
    +0x65, 0x6e, 0x74, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x62, 0x79,
    +0x73, 0x75, 0x6e, 0x64, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x73, 0x61, 0x62, 0x6c, 0x61, 0x6e,
    +0x63, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x72, 0x61, 0x6e, 0x64, 0x5f, 0x54, 0x75, 0x72,
    +0x6b, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x6e, 0x6a, 0x75, 0x6c, 0x0, 0x41, 0x66, 0x72, 0x69,
    +0x63, 0x61, 0x2f, 0x4e, 0x64, 0x6a, 0x61, 0x6d, 0x65, 0x6e, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4a, 0x65, 0x72,
    +0x75, 0x73, 0x61, 0x6c, 0x65, 0x6d, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x61,
    +0x6c, 0x6d, 0x65, 0x72, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x45, 0x75, 0x63, 0x6c, 0x61,
    +0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x75, 0x61, 0x0, 0x41, 0x73, 0x69,
    +0x61, 0x2f, 0x4d, 0x61, 0x6e, 0x69, 0x6c, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x53, 0x61, 0x69,
    +0x70, 0x61, 0x6e, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x69, 0x72, 0x6f, 0x0, 0x45, 0x75, 0x72,
    +0x6f, 0x70, 0x65, 0x2f, 0x42, 0x72, 0x75, 0x73, 0x73, 0x65, 0x6c, 0x73, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74,
    +0x69, 0x63, 0x61, 0x2f, 0x4d, 0x63, 0x4d, 0x75, 0x72, 0x64, 0x6f, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42,
    +0x75, 0x63, 0x68, 0x61, 0x72, 0x65, 0x73, 0x74, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x32, 0x0, 0x41,
    +0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x65, 0x77, 0x5f, 0x59, 0x6f, 0x72, 0x6b, 0x20, 0x41, 0x6d, 0x65, 0x72,
    +0x69, 0x63, 0x61, 0x2f, 0x44, 0x65, 0x74, 0x72, 0x6f, 0x69, 0x74, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
    +0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x50, 0x65, 0x74, 0x65, 0x72, 0x73, 0x62, 0x75, 0x72, 0x67, 0x20, 0x41,
    +0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x56, 0x69, 0x6e, 0x63, 0x65,
    +0x6e, 0x6e, 0x65, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61,
    +0x2f, 0x57, 0x69, 0x6e, 0x61, 0x6d, 0x61, 0x63, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x65, 0x6e,
    +0x74, 0x75, 0x63, 0x6b, 0x79, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x69, 0x63, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x41, 0x6d, 0x65,
    +0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x75, 0x69, 0x73, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0, 0x41, 0x66, 0x72, 0x69,
    +0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x6f, 0x2d, 0x4e, 0x6f, 0x76, 0x6f, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x49,
    +0x72, 0x6b, 0x75, 0x74, 0x73, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x6c, 0x61, 0x61, 0x6e, 0x62, 0x61, 0x61,
    +0x74, 0x61, 0x72, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x43, 0x68, 0x6f, 0x69, 0x62, 0x61, 0x6c, 0x73, 0x61, 0x6e, 0x0,
    +0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, 0x69, 0x65, 0x6e, 0x6e, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
    +0x61, 0x2f, 0x54, 0x6f, 0x72, 0x6f, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x71,
    +0x61, 0x6c, 0x75, 0x69, 0x74, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x72, 0x65,
    +0x61, 0x6c, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x69, 0x70, 0x69, 0x67, 0x6f, 0x6e, 0x20, 0x41,
    +0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x61, 0x6e, 0x67, 0x6e, 0x69, 0x72, 0x74, 0x75, 0x6e, 0x67, 0x20, 0x41,
    +0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x68, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x42, 0x61, 0x79, 0x0, 0x41,
    +0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x72, 0x61, 0x6c, 0x65, 0x6e, 0x64, 0x69, 0x6a, 0x6b, 0x0, 0x50, 0x61,
    +0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4e, 0x61, 0x75, 0x72, 0x75, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69,
    +0x63, 0x61, 0x2f, 0x44, 0x75, 0x6d, 0x6f, 0x6e, 0x74, 0x44, 0x55, 0x72, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0, 0x41, 0x73,
    +0x69, 0x61, 0x2f, 0x4d, 0x61, 0x67, 0x61, 0x64, 0x61, 0x6e, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4f, 0x73,
    +0x6c, 0x6f, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x39, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
    +0x2f, 0x47, 0x61, 0x6c, 0x61, 0x70, 0x61, 0x67, 0x6f, 0x73, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x75,
    +0x6a, 0x75, 0x6d, 0x62, 0x75, 0x72, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x6c, 0x69,
    +0x66, 0x61, 0x78, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x6c, 0x61, 0x63, 0x65, 0x5f, 0x42, 0x61,
    +0x79, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x6f, 0x6f, 0x73, 0x65, 0x5f, 0x42, 0x61, 0x79, 0x20,
    +0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x63, 0x74, 0x6f, 0x6e, 0x0, 0x45, 0x74, 0x63, 0x2f,
    +0x47, 0x4d, 0x54, 0x2d, 0x31, 0x31, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x72, 0x65, 0x6e, 0x61,
    +0x64, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4e, 0x6f, 0x75, 0x6d, 0x65, 0x61, 0x0, 0x41, 0x6d,
    +0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x6e, 0x63, 0x75, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
    +0x2f, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a,
    +0x75, 0x6e, 0x65, 0x61, 0x75, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x6d, 0x65, 0x20, 0x41,
    +0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x69, 0x74, 0x6b, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
    +0x2f, 0x59, 0x61, 0x6b, 0x75, 0x74, 0x61, 0x74, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x6f, 0x64,
    +0x74, 0x68, 0x61, 0x62, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x69, 0x73, 0x73, 0x61, 0x75, 0x0, 0x45,
    +0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x6e, 0x5f, 0x4d, 0x61, 0x72, 0x69, 0x6e, 0x6f, 0x0, 0x45, 0x75, 0x72,
    +0x6f, 0x70, 0x65, 0x2f, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, 0x73, 0x74, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
    +0x2f, 0x54, 0x65, 0x67, 0x75, 0x63, 0x69, 0x67, 0x61, 0x6c, 0x70, 0x61, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c,
    +0x69, 0x61, 0x2f, 0x4c, 0x6f, 0x72, 0x64, 0x5f, 0x48, 0x6f, 0x77, 0x65, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54,
    +0x2d, 0x33, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x69, 0x62, 0x72, 0x65, 0x76, 0x69, 0x6c, 0x6c, 0x65,
    +0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x56, 0x69, 0x6e, 0x63, 0x65, 0x6e, 0x74, 0x0,
    +0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x6f, 0x6e, 0x64, 0x6f, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
    +0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x65, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54,
    +0x2d, 0x31, 0x32, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, 0x61, 0x74, 0x69, 0x63, 0x61, 0x6e, 0x0, 0x41,
    +0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x52, 0x65, 0x79, 0x6b, 0x6a, 0x61, 0x76, 0x69, 0x6b, 0x0, 0x41, 0x6d,
    +0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x76, 0x61, 0x6e, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
    +0x2f, 0x4e, 0x61, 0x73, 0x73, 0x61, 0x75, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x53, 0x6f, 0x75,
    +0x74, 0x68, 0x5f, 0x47, 0x65, 0x6f, 0x72, 0x67, 0x69, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45,
    +0x6c, 0x5f, 0x53, 0x61, 0x6c, 0x76, 0x61, 0x64, 0x6f, 0x72, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43,
    +0x68, 0x69, 0x63, 0x61, 0x67, 0x6f, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61,
    +0x6e, 0x61, 0x2f, 0x4b, 0x6e, 0x6f, 0x78, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69,
    +0x61, 0x6e, 0x61, 0x2f, 0x54, 0x65, 0x6c, 0x6c, 0x5f, 0x43, 0x69, 0x74, 0x79, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
    +0x61, 0x2f, 0x4d, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x6e, 0x65, 0x65, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
    +0x4e, 0x6f, 0x72, 0x74, 0x68, 0x5f, 0x44, 0x61, 0x6b, 0x6f, 0x74, 0x61, 0x2f, 0x42, 0x65, 0x75, 0x6c, 0x61, 0x68, 0x20,
    +0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x5f, 0x44, 0x61, 0x6b, 0x6f, 0x74, 0x61,
    +0x2f, 0x43, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x72, 0x74,
    +0x68, 0x5f, 0x44, 0x61, 0x6b, 0x6f, 0x74, 0x61, 0x2f, 0x4e, 0x65, 0x77, 0x5f, 0x53, 0x61, 0x6c, 0x65, 0x6d, 0x0, 0x45,
    +0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x34, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x61, 0x6e,
    +0x61, 0x6d, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6f, 0x67, 0x6f, 0x74, 0x61, 0x0, 0x41,
    +0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x68, 0x75, 0x61, 0x68, 0x75, 0x61, 0x20, 0x41, 0x6d, 0x65,
    +0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x7a, 0x61, 0x74, 0x6c, 0x61, 0x6e, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69,
    +0x63, 0x2f, 0x46, 0x75, 0x6e, 0x61, 0x66, 0x75, 0x74, 0x69, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x47, 0x69,
    +0x62, 0x72, 0x61, 0x6c, 0x74, 0x61, 0x72, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4f, 0x6d, 0x73, 0x6b, 0x0, 0x41, 0x66,
    +0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x72, 0x69, 0x70, 0x6f, 0x6c, 0x69, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74,
    +0x69, 0x63, 0x61, 0x2f, 0x56, 0x6f, 0x73, 0x74, 0x6f, 0x6b, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41,
    +0x72, 0x75, 0x62, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x65, 0x69, 0x72, 0x75, 0x74, 0x0, 0x45, 0x74, 0x63,
    +0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x38, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x57, 0x69, 0x6e, 0x64, 0x68, 0x6f,
    +0x65, 0x6b, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x72, 0x61, 0x63, 0x61, 0x73, 0x0, 0x41,
    +0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x54, 0x68, 0x6f, 0x6d, 0x61, 0x73, 0x0, 0x45, 0x74, 0x63,
    +0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x31, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x6e, 0x74, 0x69, 0x67,
    +0x75, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x69, 0x6d, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f,
    +0x70, 0x65, 0x2f, 0x4d, 0x61, 0x72, 0x69, 0x65, 0x68, 0x61, 0x6d, 0x6e, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69,
    +0x63, 0x2f, 0x53, 0x74, 0x5f, 0x48, 0x65, 0x6c, 0x65, 0x6e, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f,
    +0x54, 0x72, 0x75, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x0,
    +0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x6f, 0x5f, 0x44, 0x6f, 0x6d, 0x69, 0x6e, 0x67,
    +0x6f, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6c, 0x61, 0x6e, 0x74, 0x79, 0x72, 0x65, 0x0, 0x41, 0x6d,
     0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x5f, 0x43, 0x69, 0x74, 0x79, 0x20, 0x41, 0x6d,
     0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x68, 0x69, 0x61, 0x5f, 0x42, 0x61, 0x6e, 0x64, 0x65, 0x72, 0x61, 0x73,
     0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x72, 0x69, 0x64, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72,
    -0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x65, 0x79, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
    -0x2f, 0x49, 0x73, 0x6c, 0x65, 0x5f, 0x6f, 0x66, 0x5f, 0x4d, 0x61, 0x6e, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f,
    -0x56, 0x61, 0x64, 0x75, 0x7a, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x46, 0x6f, 0x72, 0x74, 0x61, 0x6c,
    -0x65, 0x7a, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x61, 0x67, 0x75, 0x61, 0x69, 0x6e,
    -0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x65, 0x6c, 0x65, 0x6d, 0x20, 0x41, 0x6d, 0x65, 0x72,
    -0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x63, 0x65, 0x69, 0x6f, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52,
    -0x65, 0x63, 0x69, 0x66, 0x65, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x61, 0x72,
    -0x65, 0x6d, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x65, 0x6f, 0x75, 0x6c, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
    -0x61, 0x2f, 0x47, 0x75, 0x61, 0x64, 0x65, 0x6c, 0x6f, 0x75, 0x70, 0x65, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54,
    -0x2b, 0x32, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x43, 0x6f, 0x63, 0x6f, 0x73, 0x0, 0x41, 0x72, 0x63, 0x74,
    -0x69, 0x63, 0x2f, 0x4c, 0x6f, 0x6e, 0x67, 0x79, 0x65, 0x61, 0x72, 0x62, 0x79, 0x65, 0x6e, 0x0, 0x41, 0x66, 0x72, 0x69,
    -0x63, 0x61, 0x2f, 0x41, 0x64, 0x64, 0x69, 0x73, 0x5f, 0x41, 0x62, 0x61, 0x62, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70,
    -0x65, 0x2f, 0x53, 0x61, 0x6d, 0x61, 0x72, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x72, 0x61,
    -0x72, 0x65, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x50, 0x65, 0x72, 0x74, 0x68, 0x0, 0x45,
    -0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x76,
    -0x61, 0x6e, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x73, 0x61, 0x62, 0x6c, 0x61, 0x6e, 0x63,
    -0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x59, 0x65, 0x72, 0x65, 0x76, 0x61, 0x6e, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e,
    -0x74, 0x69, 0x63, 0x2f, 0x42, 0x65, 0x72, 0x6d, 0x75, 0x64, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x69,
    -0x70, 0x65, 0x69, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x36, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
    -0x61, 0x2f, 0x47, 0x6f, 0x64, 0x74, 0x68, 0x61, 0x62, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x57, 0x61, 0x72,
    -0x73, 0x61, 0x77, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x54, 0x6f, 0x6e, 0x67, 0x61, 0x74, 0x61, 0x70,
    -0x75, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x6c, 0x6d, 0x61, 0x74, 0x79, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x51,
    -0x79, 0x7a, 0x79, 0x6c, 0x6f, 0x72, 0x64, 0x61, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f,
    -0x44, 0x61, 0x76, 0x69, 0x73, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x65, 0x69, 0x72, 0x75, 0x74, 0x0, 0x41, 0x6d,
    -0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x75, 0x61, 0x74, 0x65, 0x6d, 0x61, 0x6c, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61,
    -0x2f, 0x4b, 0x61, 0x72, 0x61, 0x63, 0x68, 0x69, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x63, 0x63, 0x72,
    -0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x75, 0x65, 0x72, 0x74, 0x6f, 0x5f, 0x52, 0x69, 0x63,
    -0x6f, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x61, 0x5f, 0x50, 0x61, 0x7a, 0x0, 0x41, 0x6d, 0x65,
    -0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x65, 0x77, 0x5f, 0x59, 0x6f, 0x72, 0x6b, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
    -0x61, 0x2f, 0x44, 0x65, 0x74, 0x72, 0x6f, 0x69, 0x74, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e,
    -0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x50, 0x65, 0x74, 0x65, 0x72, 0x73, 0x62, 0x75, 0x72, 0x67, 0x20, 0x41, 0x6d, 0x65,
    -0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x56, 0x69, 0x6e, 0x63, 0x65, 0x6e, 0x6e,
    -0x65, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x57,
    -0x69, 0x6e, 0x61, 0x6d, 0x61, 0x63, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x65, 0x6e, 0x74, 0x75,
    -0x63, 0x6b, 0x79, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x69, 0x63, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69,
    -0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x75, 0x69, 0x73, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44,
    -0x61, 0x6d, 0x61, 0x73, 0x63, 0x75, 0x73, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x54, 0x61, 0x72, 0x61,
    -0x77, 0x61, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x34, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
    -0x2f, 0x42, 0x6f, 0x67, 0x6f, 0x74, 0x61, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x43, 0x61, 0x70,
    -0x65, 0x5f, 0x56, 0x65, 0x72, 0x64, 0x65, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x44, 0x61,
    -0x72, 0x77, 0x69, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x50, 0x79, 0x6f, 0x6e, 0x67, 0x79, 0x61, 0x6e, 0x67, 0x0,
    -0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x6b, 0x75, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x47, 0x69, 0x62,
    -0x72, 0x61, 0x6c, 0x74, 0x61, 0x72, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4a, 0x65, 0x72, 0x75, 0x73, 0x61, 0x6c, 0x65,
    -0x6d, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x6a, 0x75, 0x62, 0x6c, 0x6a, 0x61, 0x6e, 0x61, 0x0, 0x50,
    -0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4e, 0x6f, 0x72, 0x66, 0x6f, 0x6c, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f,
    -0x42, 0x72, 0x75, 0x6e, 0x65, 0x69, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x72, 0x61, 0x7a, 0x7a, 0x61,
    -0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x74, 0x6d, 0x61, 0x6e, 0x64, 0x75, 0x0,
    -0x41, 0x73, 0x69, 0x61, 0x2f, 0x43, 0x61, 0x6c, 0x63, 0x75, 0x74, 0x74, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
    -0x61, 0x2f, 0x41, 0x6e, 0x74, 0x69, 0x67, 0x75, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4a, 0x65, 0x72,
    -0x73, 0x65, 0x79, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x73, 0x65, 0x72, 0x72,
    -0x61, 0x74, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x37, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
    -0x2f, 0x47, 0x75, 0x79, 0x61, 0x6e, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x6b, 0x61, 0x72,
    -0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4f, 0x73, 0x6c, 0x6f, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f,
    -0x41, 0x74, 0x68, 0x65, 0x6e, 0x73, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x75, 0x77, 0x61, 0x69, 0x74, 0x0, 0x50,
    -0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x6f, 0x6e, 0x61, 0x70, 0x65, 0x20, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69,
    -0x63, 0x2f, 0x4b, 0x6f, 0x73, 0x72, 0x61, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x6f, 0x73,
    -0x74, 0x61, 0x5f, 0x52, 0x69, 0x63, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x6f, 0x6d, 0x69,
    -0x6e, 0x69, 0x63, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x62, 0x61, 0x62, 0x61, 0x6e, 0x65, 0x0,
    -0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x72, 0x74, 0x69, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x0, 0x49,
    -0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x52, 0x65, 0x75, 0x6e, 0x69, 0x6f, 0x6e, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d,
    -0x54, 0x2b, 0x36, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x49, 0x73, 0x74, 0x61, 0x6e, 0x62, 0x75, 0x6c, 0x0,
    -0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x72, 0x61, 0x73, 0x6e, 0x6f, 0x79, 0x61, 0x72, 0x73, 0x6b, 0x20, 0x41, 0x73, 0x69,
    -0x61, 0x2f, 0x4e, 0x6f, 0x76, 0x6f, 0x6b, 0x75, 0x7a, 0x6e, 0x65, 0x74, 0x73, 0x6b, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63,
    -0x61, 0x2f, 0x41, 0x62, 0x69, 0x64, 0x6a, 0x61, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x69,
    -0x6f, 0x5f, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45, 0x69, 0x72,
    -0x75, 0x6e, 0x65, 0x70, 0x65, 0x0, 0x43, 0x53, 0x54, 0x36, 0x43, 0x44, 0x54, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
    -0x61, 0x2f, 0x50, 0x68, 0x6f, 0x65, 0x6e, 0x69, 0x78, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x65,
    -0x67, 0x69, 0x6e, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x77, 0x69, 0x66, 0x74, 0x5f, 0x43,
    -0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x35, 0x0, 0x41, 0x6e, 0x74,
    -0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x77, 0x73, 0x6f, 0x6e, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61,
    -0x6e, 0x2f, 0x4d, 0x61, 0x6c, 0x64, 0x69, 0x76, 0x65, 0x73, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x65,
    -0x6c, 0x67, 0x72, 0x61, 0x64, 0x65, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x73, 0x6d, 0x65, 0x72, 0x61,
    -0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x77, 0x73, 0x6f, 0x6e, 0x5f, 0x43, 0x72, 0x65, 0x65,
    -0x6b, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x72, 0x65, 0x73, 0x74, 0x6f, 0x6e, 0x20, 0x41, 0x6d,
    -0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x46, 0x6f, 0x72, 0x74, 0x5f, 0x4e, 0x65, 0x6c, 0x73, 0x6f, 0x6e, 0x0, 0x45, 0x75,
    -0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, 0x73, 0x74, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61,
    -0x2f, 0x57, 0x69, 0x6e, 0x64, 0x68, 0x6f, 0x65, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4a, 0x61, 0x79, 0x61, 0x70,
    -0x75, 0x72, 0x61, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x42, 0x72, 0x69, 0x73, 0x62, 0x61,
    -0x6e, 0x65, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x4c, 0x69, 0x6e, 0x64, 0x65, 0x6d, 0x61,
    -0x6e, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x34, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
    -0x43, 0x61, 0x72, 0x61, 0x63, 0x61, 0x73, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x53,
    -0x79, 0x6f, 0x77, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x5a, 0x61, 0x67, 0x72, 0x65, 0x62, 0x0, 0x41,
    -0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x75, 0x65, 0x6e, 0x6f, 0x73, 0x5f, 0x41, 0x69, 0x72, 0x65, 0x73, 0x20,
    -0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x4c, 0x61,
    -0x5f, 0x52, 0x69, 0x6f, 0x6a, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e,
    -0x74, 0x69, 0x6e, 0x61, 0x2f, 0x52, 0x69, 0x6f, 0x5f, 0x47, 0x61, 0x6c, 0x6c, 0x65, 0x67, 0x6f, 0x73, 0x20, 0x41, 0x6d,
    -0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x53, 0x61, 0x6c, 0x74,
    -0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f,
    -0x53, 0x61, 0x6e, 0x5f, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67,
    -0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x5f, 0x4c, 0x75, 0x69, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72,
    -0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x54, 0x75, 0x63, 0x75, 0x6d, 0x61,
    -0x6e, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f,
    -0x55, 0x73, 0x68, 0x75, 0x61, 0x69, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x74, 0x61,
    -0x6d, 0x61, 0x72, 0x63, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x6f, 0x72, 0x64, 0x6f, 0x62,
    -0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a, 0x75, 0x6a, 0x75, 0x79, 0x20, 0x41, 0x6d, 0x65, 0x72,
    -0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x6e, 0x64, 0x6f, 0x7a, 0x61, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69,
    -0x63, 0x61, 0x2f, 0x50, 0x61, 0x6c, 0x6d, 0x65, 0x72, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x6f,
    -0x72, 0x6f, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x71, 0x61, 0x6c, 0x75, 0x69,
    -0x74, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x72, 0x65, 0x61, 0x6c, 0x20, 0x41,
    -0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x69, 0x70, 0x69, 0x67, 0x6f, 0x6e, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69,
    -0x63, 0x61, 0x2f, 0x50, 0x61, 0x6e, 0x67, 0x6e, 0x69, 0x72, 0x74, 0x75, 0x6e, 0x67, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69,
    -0x63, 0x61, 0x2f, 0x54, 0x68, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x42, 0x61, 0x79, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63,
    -0x61, 0x2f, 0x42, 0x61, 0x6d, 0x61, 0x6b, 0x6f, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x52, 0x69, 0x79, 0x61, 0x64, 0x68,
    -0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x54, 0x72, 0x75, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54,
    -0x6f, 0x6b, 0x79, 0x6f, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x45, 0x6e, 0x64, 0x65, 0x72, 0x62, 0x75,
    -0x72, 0x79, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x6f, 0x6e, 0x64, 0x6f, 0x6e, 0x0, 0x41, 0x6d, 0x65,
    -0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x70, 0x6f, 0x6c, 0x69, 0x73, 0x20, 0x41, 0x6d,
    -0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x4d, 0x61, 0x72, 0x65, 0x6e, 0x67,
    -0x6f, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x56, 0x65,
    -0x76, 0x61, 0x79, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x43, 0x6f, 0x6c, 0x6f, 0x6d, 0x62, 0x6f, 0x0, 0x41, 0x6d, 0x65,
    -0x72, 0x69, 0x63, 0x61, 0x2f, 0x57, 0x69, 0x6e, 0x6e, 0x69, 0x70, 0x65, 0x67, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
    -0x61, 0x2f, 0x52, 0x61, 0x69, 0x6e, 0x79, 0x5f, 0x52, 0x69, 0x76, 0x65, 0x72, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
    -0x61, 0x2f, 0x52, 0x61, 0x6e, 0x6b, 0x69, 0x6e, 0x5f, 0x49, 0x6e, 0x6c, 0x65, 0x74, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69,
    -0x63, 0x61, 0x2f, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x65, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44,
    -0x6a, 0x69, 0x62, 0x6f, 0x75, 0x74, 0x69, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x6c, 0x69,
    -0x66, 0x61, 0x78, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x6c, 0x61, 0x63, 0x65, 0x5f, 0x42, 0x61,
    -0x79, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x6f, 0x6f, 0x73, 0x65, 0x5f, 0x42, 0x61, 0x79, 0x20,
    -0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x63, 0x74, 0x6f, 0x6e, 0x0, 0x41, 0x66, 0x72, 0x69,
    -0x63, 0x61, 0x2f, 0x53, 0x61, 0x6f, 0x5f, 0x54, 0x6f, 0x6d, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
    -0x53, 0x74, 0x5f, 0x54, 0x68, 0x6f, 0x6d, 0x61, 0x73, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x75, 0x73,
    -0x61, 0x6b, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x2d, 0x61, 0x75, 0x2d,
    -0x50, 0x72, 0x69, 0x6e, 0x63, 0x65, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x69, 0x61, 0x6d, 0x65, 0x79,
    -0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x33, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x6c,
    -0x67, 0x69, 0x65, 0x72, 0x73, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x75, 0x61, 0x79, 0x61, 0x71,
    -0x75, 0x69, 0x6c, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x43, 0x68, 0x61, 0x67, 0x6f, 0x73, 0x0, 0x41, 0x73,
    -0x69, 0x61, 0x2f, 0x53, 0x68, 0x61, 0x6e, 0x67, 0x68, 0x61, 0x69, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
    -0x43, 0x75, 0x69, 0x61, 0x62, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x6d, 0x70, 0x6f,
    -0x5f, 0x47, 0x72, 0x61, 0x6e, 0x64, 0x65, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4d, 0x69, 0x64, 0x77,
    -0x61, 0x79, 0x0, 0x45, 0x53, 0x54, 0x35, 0x45, 0x44, 0x54, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x43, 0x68,
    -0x72, 0x69, 0x73, 0x74, 0x6d, 0x61, 0x73, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x47, 0x61, 0x6c, 0x61,
    -0x70, 0x61, 0x67, 0x6f, 0x73, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x6e, 0x67, 0x75, 0x69, 0x6c,
    -0x6c, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x79, 0x6d, 0x61, 0x6e, 0x0, 0x41, 0x6d,
    -0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x4b, 0x69, 0x74, 0x74, 0x73, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69,
    -0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x69, 0x61, 0x67, 0x6f, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f,
    -0x50, 0x61, 0x6c, 0x61, 0x75, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x59, 0x61, 0x6b, 0x75, 0x74, 0x73, 0x6b, 0x20, 0x41,
    -0x73, 0x69, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x74, 0x61, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x68, 0x61, 0x6e, 0x64,
    -0x79, 0x67, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, 0x69, 0x6c, 0x6e, 0x69, 0x75, 0x73, 0x0, 0x41,
    -0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x72, 0x6f, 0x76, 0x69, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66,
    -0x69, 0x63, 0x2f, 0x47, 0x75, 0x61, 0x6d, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x6e, 0x6d,
    -0x61, 0x72, 0x6b, 0x73, 0x68, 0x61, 0x76, 0x6e, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x46, 0x69, 0x6a,
    -0x69, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x75, 0x61, 0x0, 0x41, 0x6d,
    -0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x62, 0x79, 0x73, 0x75, 0x6e, 0x64, 0x0, 0x41,
    -0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x42, 0x61, 0x72, 0x74, 0x68, 0x65, 0x6c, 0x65, 0x6d, 0x79,
    -0x0, 0x50, 0x53, 0x54, 0x38, 0x50, 0x44, 0x54, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x72, 0x61,
    -0x6e, 0x64, 0x5f, 0x54, 0x75, 0x72, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4f, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x73,
    -0x69, 0x61, 0x2f, 0x41, 0x71, 0x74, 0x61, 0x75, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x71, 0x74, 0x6f, 0x62, 0x65,
    -0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x63, 0x61, 0x67, 0x6f, 0x20, 0x41, 0x6d, 0x65,
    -0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x4b, 0x6e, 0x6f, 0x78, 0x20, 0x41, 0x6d,
    -0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x54, 0x65, 0x6c, 0x6c, 0x5f, 0x43,
    -0x69, 0x74, 0x79, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x6e, 0x65,
    -0x65, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x5f, 0x44, 0x61, 0x6b, 0x6f,
    -0x74, 0x61, 0x2f, 0x42, 0x65, 0x75, 0x6c, 0x61, 0x68, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f,
    -0x72, 0x74, 0x68, 0x5f, 0x44, 0x61, 0x6b, 0x6f, 0x74, 0x61, 0x2f, 0x43, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x20, 0x41, 0x6d,
    -0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x5f, 0x44, 0x61, 0x6b, 0x6f, 0x74, 0x61, 0x2f, 0x4e,
    -0x65, 0x77, 0x5f, 0x53, 0x61, 0x6c, 0x65, 0x6d, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x74,
    -0x61, 0x6d, 0x6f, 0x72, 0x6f, 0x73, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x68, 0x75, 0x6c, 0x65,
    -0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x31, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63,
    -0x2f, 0x53, 0x74, 0x5f, 0x48, 0x65, 0x6c, 0x65, 0x6e, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4e,
    -0x69, 0x75, 0x65, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x69, 0x75, 0x73,
    -0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x6c, 0x61, 0x61, 0x6e, 0x62, 0x61, 0x61, 0x74, 0x61, 0x72, 0x20, 0x41, 0x73,
    -0x69, 0x61, 0x2f, 0x43, 0x68, 0x6f, 0x69, 0x62, 0x61, 0x6c, 0x73, 0x61, 0x6e, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d,
    -0x54, 0x2d, 0x32, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x69, 0x6e, 0x73, 0x6b, 0x0, 0x41, 0x66, 0x72,
    -0x69, 0x63, 0x61, 0x2f, 0x4a, 0x75, 0x62, 0x61, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x48,
    -0x6f, 0x62, 0x61, 0x72, 0x74, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x43, 0x75, 0x72, 0x72,
    -0x69, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x56, 0x6c, 0x61, 0x64, 0x69, 0x76, 0x6f, 0x73, 0x74, 0x6f, 0x6b, 0x20,
    -0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x61, 0x6b, 0x68, 0x61, 0x6c, 0x69, 0x6e, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55,
    -0x73, 0x74, 0x2d, 0x4e, 0x65, 0x72, 0x61, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x44,
    -0x75, 0x6d, 0x6f, 0x6e, 0x74, 0x44, 0x55, 0x72, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
    -0x2f, 0x44, 0x75, 0x62, 0x6c, 0x69, 0x6e, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, 0x69, 0x65, 0x6e, 0x6e,
    -0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x0,
    -0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x75, 0x65, 0x6e, 0x6f, 0x73, 0x5f, 0x41, 0x69, 0x72, 0x65, 0x73,
    -0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x6c, 0x69, 0x66, 0x61, 0x78, 0x0, 0x41, 0x75, 0x73,
    -0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x53, 0x79, 0x64, 0x6e, 0x65, 0x79, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
    -0x61, 0x2f, 0x52, 0x65, 0x67, 0x69, 0x6e, 0x61, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x41,
    -0x64, 0x65, 0x6c, 0x61, 0x69, 0x64, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x6c, 0x6d, 0x61, 0x74, 0x79, 0x0,
    -0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x75, 0x69, 0x61, 0x62, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69,
    -0x63, 0x61, 0x2f, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x5f, 0x43, 0x69, 0x74, 0x79, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69,
    -0x63, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x63, 0x61, 0x67, 0x6f, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61,
    -0x2f, 0x42, 0x72, 0x69, 0x73, 0x62, 0x61, 0x6e, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x65,
    -0x77, 0x5f, 0x59, 0x6f, 0x72, 0x6b, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4b, 0x69, 0x65, 0x76, 0x0, 0x41,
    -0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x68, 0x75, 0x61, 0x68, 0x75, 0x61, 0x0, 0x41, 0x6d, 0x65,
    -0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x65, 0x6e, 0x76, 0x65, 0x72, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4e, 0x6f, 0x76,
    -0x6f, 0x73, 0x69, 0x62, 0x69, 0x72, 0x73, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x72, 0x61, 0x73, 0x6e, 0x6f,
    -0x79, 0x61, 0x72, 0x73, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x6d, 0x63, 0x68, 0x61, 0x74, 0x6b, 0x61,
    -0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x6f, 0x73, 0x63, 0x6f, 0x77, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72,
    -0x61, 0x6c, 0x69, 0x61, 0x2f, 0x48, 0x6f, 0x62, 0x61, 0x72, 0x74, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x6c, 0x61,
    -0x61, 0x6e, 0x62, 0x61, 0x61, 0x74, 0x61, 0x72, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64,
    -0x69, 0x61, 0x6e, 0x61, 0x70, 0x6f, 0x6c, 0x69, 0x73, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x56, 0x6c, 0x61, 0x64, 0x69,
    -0x76, 0x6f, 0x73, 0x74, 0x6f, 0x6b, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x65, 0x72, 0x6c, 0x69, 0x6e,
    -0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x73, 0x68, 0x6b, 0x65, 0x6e, 0x74, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f,
    -0x59, 0x61, 0x6b, 0x75, 0x74, 0x73, 0x6b, 0x0, 0x55, 0x54, 0x43, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x31, 0x34, 0x3a, 0x30,
    -0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x31, 0x33, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x31, 0x32, 0x3a, 0x30,
    -0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x31, 0x31, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x31, 0x30, 0x3a, 0x30,
    -0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x39, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x38, 0x3a, 0x30,
    -0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x37, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x36, 0x3a, 0x30,
    -0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x35, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x34, 0x3a, 0x33,
    -0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x34, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x33, 0x3a, 0x33,
    -0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x33, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x32, 0x3a, 0x30,
    -0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x31, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x30, 0x3a, 0x30,
    -0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x31, 0x3a, 0x30,
    -0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x33, 0x3a, 0x30,
    -0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x33, 0x3a, 0x33, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x34, 0x3a, 0x30,
    -0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x34, 0x3a, 0x33, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x35, 0x3a, 0x30,
    -0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x35, 0x3a, 0x33, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x35, 0x3a, 0x34,
    -0x35, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x36, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x36, 0x3a, 0x33,
    -0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x37, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x38, 0x3a, 0x30,
    -0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x39, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x39, 0x3a, 0x33,
    -0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x30, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x31, 0x3a, 0x30,
    -0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x32, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x33, 0x3a, 0x30,
    -0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x34, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x38, 0x3a, 0x33,
    -0x30, 0x0
    +0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x65, 0x79, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b,
    +0x75, 0x61, 0x6c, 0x61, 0x5f, 0x4c, 0x75, 0x6d, 0x70, 0x75, 0x72, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x75, 0x63,
    +0x68, 0x69, 0x6e, 0x67, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x46, 0x69, 0x6a, 0x69, 0x0, 0x41, 0x6d,
    +0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x68, 0x6f, 0x65, 0x6e, 0x69, 0x78, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54,
    +0x68, 0x69, 0x6d, 0x70, 0x68, 0x75, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x61, 0x6c, 0x74, 0x61, 0x0,
    +0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x6f, 0x73, 0x63, 0x6f, 0x77, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
    +0x2f, 0x4b, 0x69, 0x72, 0x6f, 0x76, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, 0x6f, 0x6c, 0x67, 0x6f, 0x67,
    +0x72, 0x61, 0x64, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x72, 0x74, 0x69, 0x6e, 0x69, 0x71,
    +0x75, 0x65, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x31, 0x32, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x59,
    +0x61, 0x6b, 0x75, 0x74, 0x73, 0x6b, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x68, 0x61, 0x6e, 0x64, 0x79, 0x67, 0x61,
    +0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x62, 0x75, 0x6c, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x20,
    +0x45, 0x74, 0x63, 0x2f, 0x55, 0x54, 0x43, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x74, 0x61,
    +0x6d, 0x6f, 0x72, 0x6f, 0x73, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x34, 0x0, 0x49, 0x6e, 0x64, 0x69,
    +0x61, 0x6e, 0x2f, 0x43, 0x68, 0x72, 0x69, 0x73, 0x74, 0x6d, 0x61, 0x73, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69,
    +0x63, 0x2f, 0x41, 0x7a, 0x6f, 0x72, 0x65, 0x73, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x0, 0x41,
    +0x73, 0x69, 0x61, 0x2f, 0x44, 0x68, 0x61, 0x6b, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x57, 0x69,
    +0x6e, 0x6e, 0x69, 0x70, 0x65, 0x67, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x61, 0x69, 0x6e, 0x79,
    +0x5f, 0x52, 0x69, 0x76, 0x65, 0x72, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x61, 0x6e, 0x6b, 0x69,
    +0x6e, 0x5f, 0x49, 0x6e, 0x6c, 0x65, 0x74, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x65, 0x73, 0x6f,
    +0x6c, 0x75, 0x74, 0x65, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x35, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66,
    +0x69, 0x63, 0x2f, 0x46, 0x61, 0x6b, 0x61, 0x6f, 0x66, 0x6f, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4e, 0x6f, 0x76, 0x6f,
    +0x73, 0x69, 0x62, 0x69, 0x72, 0x73, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x48, 0x65, 0x62, 0x72, 0x6f, 0x6e, 0x20,
    +0x41, 0x73, 0x69, 0x61, 0x2f, 0x47, 0x61, 0x7a, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x49, 0x73, 0x74,
    +0x61, 0x6e, 0x62, 0x75, 0x6c, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x64, 0x61, 0x6b, 0x0, 0x45,
    +0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x37, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x65, 0x6e,
    +0x76, 0x65, 0x72, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6f, 0x69, 0x73, 0x65, 0x0, 0x41, 0x66,
    +0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x64, 0x64, 0x69, 0x73, 0x5f, 0x41, 0x62, 0x61, 0x62, 0x61, 0x0, 0x45, 0x75, 0x72,
    +0x6f, 0x70, 0x65, 0x2f, 0x41, 0x6d, 0x73, 0x74, 0x65, 0x72, 0x64, 0x61, 0x6d, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
    +0x61, 0x2f, 0x4d, 0x61, 0x72, 0x69, 0x67, 0x6f, 0x74, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x69, 0x73,
    +0x62, 0x6f, 0x6e, 0x20, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x4d, 0x61, 0x64, 0x65, 0x69, 0x72, 0x61,
    +0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, 0x69, 0x6c, 0x6e, 0x69, 0x75, 0x73, 0x0, 0x45, 0x75, 0x72, 0x6f,
    +0x70, 0x65, 0x2f, 0x42, 0x65, 0x72, 0x6c, 0x69, 0x6e, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x75, 0x73,
    +0x69, 0x6e, 0x67, 0x65, 0x6e, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4d, 0x61, 0x72, 0x71, 0x75, 0x65,
    +0x73, 0x61, 0x73, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x72, 0x61, 0x73, 0x6e, 0x6f, 0x79, 0x61, 0x72, 0x73, 0x6b,
    +0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4e, 0x6f, 0x76, 0x6f, 0x6b, 0x75, 0x7a, 0x6e, 0x65, 0x74, 0x73, 0x6b, 0x0, 0x50,
    +0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4b, 0x69, 0x72, 0x69, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x0, 0x41, 0x6d,
    +0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x69, 0x71, 0x75, 0x65, 0x6c, 0x6f, 0x6e, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70,
    +0x65, 0x2f, 0x44, 0x75, 0x62, 0x6c, 0x69, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x52, 0x69, 0x79, 0x61, 0x64, 0x68,
    +0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x69, 0x61, 0x67, 0x6f, 0x0, 0x41, 0x73,
    +0x69, 0x61, 0x2f, 0x4b, 0x61, 0x6d, 0x63, 0x68, 0x61, 0x74, 0x6b, 0x61, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x6e,
    +0x61, 0x64, 0x79, 0x72, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x43, 0x6f, 0x6d, 0x6f, 0x72, 0x6f, 0x0, 0x41,
    +0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x75, 0x72, 0x61, 0x63, 0x61, 0x6f, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70,
    +0x65, 0x2f, 0x43, 0x68, 0x69, 0x73, 0x69, 0x6e, 0x61, 0x75, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42,
    +0x65, 0x6c, 0x69, 0x7a, 0x65, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a, 0x6f, 0x68, 0x61, 0x6e, 0x6e, 0x65,
    +0x73, 0x62, 0x75, 0x72, 0x67, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x56, 0x6c, 0x61, 0x64, 0x69, 0x76, 0x6f, 0x73, 0x74,
    +0x6f, 0x6b, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x73, 0x74, 0x2d, 0x4e, 0x65, 0x72, 0x61, 0x0, 0x45, 0x74, 0x63,
    +0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x32, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x61, 0x6d, 0x61, 0x73, 0x63, 0x75, 0x73,
    +0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x79, 0x65, 0x6e, 0x6e, 0x65, 0x0, 0x41, 0x66, 0x72,
    +0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x75, 0x61, 0x6b, 0x63, 0x68, 0x6f, 0x74, 0x74, 0x0, 0x45, 0x53, 0x54, 0x35, 0x45,
    +0x44, 0x54, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x68, 0x69, 0x61, 0x0, 0x50, 0x61, 0x63,
    +0x69, 0x66, 0x69, 0x63, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b,
    +0x33, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x41, 0x73, 0x74, 0x72, 0x61, 0x6b, 0x68, 0x61, 0x6e, 0x20, 0x45,
    +0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x55, 0x6c, 0x79, 0x61, 0x6e, 0x6f, 0x76, 0x73, 0x6b, 0x0, 0x41, 0x6d, 0x65, 0x72,
    +0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x6e, 0x61, 0x75, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42,
    +0x6f, 0x61, 0x5f, 0x56, 0x69, 0x73, 0x74, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72,
    +0x74, 0x6f, 0x5f, 0x56, 0x65, 0x6c, 0x68, 0x6f, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x69, 0x6e, 0x73,
    +0x6b, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x4c, 0x75, 0x63, 0x69, 0x61, 0x0, 0x41,
    +0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x75, 0x61, 0x6e, 0x64, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f,
    +0x4c, 0x61, 0x67, 0x6f, 0x73, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x41, 0x6e, 0x64, 0x6f, 0x72, 0x72, 0x61,
    +0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4b, 0x61, 0x6c, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x72, 0x61, 0x64, 0x0,
    +0x4d, 0x53, 0x54, 0x37, 0x4d, 0x44, 0x54, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x6e, 0x67, 0x75,
    +0x69, 0x6c, 0x6c, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x57, 0x61, 0x6c, 0x6c, 0x69, 0x73, 0x0,
    +0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x75, 0x62, 0x61, 0x69, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43,
    +0x61, 0x79, 0x6d, 0x61, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x6e, 0x67, 0x6b, 0x6f, 0x6b, 0x0, 0x50,
    +0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x47, 0x75, 0x61, 0x64, 0x61, 0x6c, 0x63, 0x61, 0x6e, 0x61, 0x6c, 0x0, 0x41,
    +0x73, 0x69, 0x61, 0x2f, 0x54, 0x62, 0x69, 0x6c, 0x69, 0x73, 0x69, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x50, 0x68, 0x6e,
    +0x6f, 0x6d, 0x5f, 0x50, 0x65, 0x6e, 0x68, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x73, 0x68, 0x6b, 0x65, 0x6e,
    +0x74, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x61, 0x6d, 0x61, 0x72, 0x6b, 0x61, 0x6e, 0x64, 0x0, 0x41, 0x73, 0x69,
    +0x61, 0x2f, 0x46, 0x61, 0x6d, 0x61, 0x67, 0x75, 0x73, 0x74, 0x61, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4e, 0x69, 0x63,
    +0x6f, 0x73, 0x69, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x75, 0x61, 0x64, 0x65, 0x6c, 0x6f,
    +0x75, 0x70, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x61, 0x69, 0x67, 0x6f, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61,
    +0x2f, 0x43, 0x68, 0x69, 0x74, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x72, 0x6f, 0x76,
    +0x69, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x6f, 0x72, 0x74, 0x6f, 0x6c, 0x61, 0x0, 0x41,
    +0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x69, 0x6e, 0x73, 0x68, 0x61, 0x73, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f,
    +0x53, 0x61, 0x6b, 0x68, 0x61, 0x6c, 0x69, 0x6e, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x57, 0x61, 0x6b,
    +0x65, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x63, 0x63, 0x72, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66,
    +0x69, 0x63, 0x2f, 0x41, 0x75, 0x63, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69,
    +0x61, 0x2f, 0x41, 0x64, 0x65, 0x6c, 0x61, 0x69, 0x64, 0x65, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61,
    +0x2f, 0x42, 0x72, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x48, 0x69, 0x6c, 0x6c, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
    +0x2f, 0x54, 0x61, 0x68, 0x69, 0x74, 0x69, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4f, 0x75, 0x61, 0x67, 0x61,
    +0x64, 0x6f, 0x75, 0x67, 0x6f, 0x75, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4b, 0x65, 0x72, 0x67, 0x75, 0x65,
    +0x6c, 0x65, 0x6e, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x38, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
    +0x2f, 0x54, 0x69, 0x72, 0x61, 0x6e, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x69, 0x70, 0x65, 0x69, 0x0,
    +0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x43, 0x6f, 0x70, 0x65, 0x6e, 0x68, 0x61, 0x67, 0x65, 0x6e, 0x0, 0x41, 0x66,
    +0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x61, 0x6d, 0x70, 0x61, 0x6c, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
    +0x2f, 0x42, 0x61, 0x72, 0x62, 0x61, 0x64, 0x6f, 0x73, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x6b, 0x75, 0x0,
    +0x41, 0x73, 0x69, 0x61, 0x2f, 0x48, 0x6f, 0x6e, 0x67, 0x5f, 0x4b, 0x6f, 0x6e, 0x67, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f,
    +0x4a, 0x61, 0x79, 0x61, 0x70, 0x75, 0x72, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x48, 0x6f, 0x6e,
    +0x6f, 0x6c, 0x75, 0x6c, 0x75, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x61, 0x69, 0x72, 0x6f, 0x62, 0x69,
    +0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x47, 0x75, 0x61, 0x6d, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61,
    +0x2f, 0x4a, 0x75, 0x62, 0x61, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x46, 0x61, 0x65, 0x72, 0x6f,
    +0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x72, 0x65, 0x64, 0x6e, 0x65, 0x6b, 0x6f, 0x6c, 0x79, 0x6d, 0x73, 0x6b,
    +0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4e, 0x69, 0x75, 0x65, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61,
    +0x2f, 0x41, 0x6c, 0x67, 0x69, 0x65, 0x72, 0x73, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x69, 0x6c, 0x69, 0x0, 0x41,
    +0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x46, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x65, 0x7a, 0x61, 0x20, 0x41, 0x6d, 0x65,
    +0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x65, 0x6c, 0x65, 0x6d, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d,
    +0x61, 0x63, 0x65, 0x69, 0x6f, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x65, 0x63, 0x69, 0x66, 0x65,
    +0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x61, 0x72, 0x65, 0x6d, 0x0, 0x45, 0x75,
    +0x72, 0x6f, 0x70, 0x65, 0x2f, 0x50, 0x6f, 0x64, 0x67, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63,
    +0x61, 0x2f, 0x44, 0x6f, 0x75, 0x61, 0x6c, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x56, 0x69, 0x65, 0x6e, 0x74, 0x69,
    +0x61, 0x6e, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x69, 0x6a, 0x75, 0x61, 0x6e, 0x61, 0x20,
    +0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x61, 0x5f, 0x49, 0x73, 0x61, 0x62, 0x65, 0x6c,
    +0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x6d, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f,
    +0x52, 0x69, 0x67, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6c, 0x61, 0x6e, 0x63, 0x2d, 0x53,
    +0x61, 0x62, 0x6c, 0x6f, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x75, 0x73, 0x68, 0x61, 0x6e, 0x62, 0x65, 0x0,
    +0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x4a, 0x6f, 0x68, 0x6e, 0x73, 0x0, 0x41, 0x73, 0x69,
    +0x61, 0x2f, 0x54, 0x6f, 0x6b, 0x79, 0x6f, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x36, 0x0, 0x45, 0x75,
    +0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x72, 0x61, 0x6a, 0x65, 0x76, 0x6f, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
    +0x2f, 0x42, 0x72, 0x61, 0x74, 0x69, 0x73, 0x6c, 0x61, 0x76, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
    +0x47, 0x75, 0x79, 0x61, 0x6e, 0x61, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x43, 0x61, 0x6e, 0x61,
    +0x72, 0x79, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x42, 0x6f, 0x75, 0x67, 0x61, 0x69, 0x6e, 0x76, 0x69,
    +0x6c, 0x6c, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x68, 0x72, 0x61, 0x69, 0x6e, 0x0, 0x41, 0x6d, 0x65,
    +0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x75, 0x61, 0x74, 0x65, 0x6d, 0x61, 0x6c, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69,
    +0x63, 0x61, 0x2f, 0x4c, 0x61, 0x5f, 0x50, 0x61, 0x7a, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x50, 0x79, 0x6f, 0x6e, 0x67,
    +0x79, 0x61, 0x6e, 0x67, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x61, 0x67, 0x6f, 0x5f, 0x50, 0x61,
    +0x67, 0x6f, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x52, 0x65, 0x75, 0x6e, 0x69, 0x6f, 0x6e, 0x0, 0x41, 0x66,
    +0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x73, 0x65, 0x72, 0x75, 0x0, 0x50, 0x53, 0x54, 0x38, 0x50, 0x44, 0x54, 0x0,
    +0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x39, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x75, 0x6e,
    +0x69, 0x73, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6f, 0x5f, 0x54, 0x6f, 0x6d, 0x65, 0x0, 0x45,
    +0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x72, 0x61, 0x74, 0x6f, 0x76, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61,
    +0x2f, 0x4b, 0x68, 0x61, 0x72, 0x74, 0x6f, 0x75, 0x6d, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4a, 0x65, 0x72,
    +0x73, 0x65, 0x79, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x63, 0x71, 0x75,
    +0x61, 0x72, 0x69, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4f, 0x6a, 0x69, 0x6e, 0x61, 0x67, 0x61,
    +0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x43, 0x61, 0x70, 0x65, 0x5f, 0x56, 0x65, 0x72, 0x64, 0x65,
    +0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x61, 0x6b, 0x61, 0x73, 0x73, 0x61, 0x72, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70,
    +0x65, 0x2f, 0x4c, 0x6a, 0x75, 0x62, 0x6c, 0x6a, 0x61, 0x6e, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x47,
    +0x75, 0x65, 0x72, 0x6e, 0x73, 0x65, 0x79, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x4d,
    +0x61, 0x77, 0x73, 0x6f, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x75, 0x65, 0x6e, 0x6f, 0x73,
    +0x5f, 0x41, 0x69, 0x72, 0x65, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e,
    +0x74, 0x69, 0x6e, 0x61, 0x2f, 0x4c, 0x61, 0x5f, 0x52, 0x69, 0x6f, 0x6a, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
    +0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x52, 0x69, 0x6f, 0x5f, 0x47, 0x61, 0x6c, 0x6c,
    +0x65, 0x67, 0x6f, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69,
    +0x6e, 0x61, 0x2f, 0x53, 0x61, 0x6c, 0x74, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67,
    +0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x5f, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x41, 0x6d, 0x65, 0x72,
    +0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x5f, 0x4c, 0x75,
    +0x69, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61,
    +0x2f, 0x54, 0x75, 0x63, 0x75, 0x6d, 0x61, 0x6e, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67,
    +0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x55, 0x73, 0x68, 0x75, 0x61, 0x69, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69,
    +0x63, 0x61, 0x2f, 0x43, 0x61, 0x74, 0x61, 0x6d, 0x61, 0x72, 0x63, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
    +0x2f, 0x43, 0x6f, 0x72, 0x64, 0x6f, 0x62, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a, 0x75, 0x6a,
    +0x75, 0x79, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x6e, 0x64, 0x6f, 0x7a, 0x61, 0x0, 0x50,
    +0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x41, 0x70, 0x69, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42,
    +0x61, 0x6e, 0x67, 0x75, 0x69, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x6f, 0x6d, 0x73, 0x6b, 0x0, 0x50, 0x61, 0x63,
    +0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x61, 0x6c, 0x61, 0x75, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61,
    +0x2f, 0x44, 0x61, 0x72, 0x77, 0x69, 0x6e, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x69, 0x74, 0x63,
    +0x61, 0x69, 0x72, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x72, 0x75, 0x6e, 0x65, 0x69, 0x0, 0x50, 0x61, 0x63,
    +0x69, 0x66, 0x69, 0x63, 0x2f, 0x54, 0x6f, 0x6e, 0x67, 0x61, 0x74, 0x61, 0x70, 0x75, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70,
    +0x65, 0x2f, 0x53, 0x61, 0x6d, 0x61, 0x72, 0x61, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x50,
    +0x65, 0x72, 0x74, 0x68, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x57, 0x61, 0x72, 0x73, 0x61, 0x77, 0x0, 0x49,
    +0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x43, 0x6f, 0x63, 0x6f, 0x73, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4d,
    +0x61, 0x68, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x73, 0x5f, 0x41, 0x6e, 0x67, 0x65,
    +0x6c, 0x65, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x74, 0x6c, 0x61, 0x6b, 0x61, 0x74,
    +0x6c, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x43, 0x61, 0x6c, 0x63, 0x75, 0x74, 0x74, 0x61, 0x0, 0x41, 0x66, 0x72,
    +0x69, 0x63, 0x61, 0x2f, 0x41, 0x62, 0x69, 0x64, 0x6a, 0x61, 0x6e, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b,
    +0x36, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x45, 0x66, 0x61, 0x74, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f,
    +0x70, 0x65, 0x2f, 0x4c, 0x75, 0x78, 0x65, 0x6d, 0x62, 0x6f, 0x75, 0x72, 0x67, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61,
    +0x2f, 0x42, 0x61, 0x6d, 0x61, 0x6b, 0x6f, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x69, 0x67, 0x61, 0x6c,
    +0x69, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x51, 0x61, 0x74, 0x61, 0x72, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61,
    +0x72, 0x61, 0x63, 0x68, 0x69, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x30, 0x0, 0x41, 0x66, 0x72,
    +0x69, 0x63, 0x61, 0x2f, 0x44, 0x6a, 0x69, 0x62, 0x6f, 0x75, 0x74, 0x69, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x59, 0x65,
    +0x6b, 0x61, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x62, 0x75, 0x72, 0x67, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
    +0x44, 0x61, 0x77, 0x73, 0x6f, 0x6e, 0x5f, 0x43, 0x72, 0x65, 0x65, 0x6b, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
    +0x2f, 0x43, 0x72, 0x65, 0x73, 0x74, 0x6f, 0x6e, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x46, 0x6f, 0x72,
    +0x74, 0x5f, 0x4e, 0x65, 0x6c, 0x73, 0x6f, 0x6e, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4d, 0x61, 0x79, 0x6f,
    +0x74, 0x74, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x6b, 0x6f, 0x70, 0x6a, 0x65, 0x0, 0x41, 0x73,
    +0x69, 0x61, 0x2f, 0x53, 0x65, 0x6f, 0x75, 0x6c, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x61, 0x72,
    +0x61, 0x6d, 0x61, 0x72, 0x69, 0x62, 0x6f, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x74, 0x6f, 0x63, 0x6b,
    +0x68, 0x6f, 0x6c, 0x6d, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x75, 0x62, 0x75, 0x6d, 0x62, 0x61, 0x73,
    +0x68, 0x69, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x61, 0x67, 0x65,
    +0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x75, 0x65, 0x6e, 0x6f, 0x73, 0x5f, 0x41, 0x69, 0x72, 0x65,
    +0x73, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x41, 0x73, 0x74, 0x72, 0x61, 0x6b, 0x68, 0x61, 0x6e, 0x0, 0x41,
    +0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x6c, 0x69, 0x66, 0x61, 0x78, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72,
    +0x61, 0x6c, 0x69, 0x61, 0x2f, 0x53, 0x79, 0x64, 0x6e, 0x65, 0x79, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
    +0x52, 0x65, 0x67, 0x69, 0x6e, 0x61, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x41, 0x64, 0x65,
    +0x6c, 0x61, 0x69, 0x64, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x6c, 0x6d, 0x61, 0x74, 0x79, 0x0, 0x41, 0x6d,
    +0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x75, 0x69, 0x61, 0x62, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
    +0x2f, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x5f, 0x43, 0x69, 0x74, 0x79, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
    +0x2f, 0x43, 0x68, 0x69, 0x63, 0x61, 0x67, 0x6f, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x42,
    +0x72, 0x69, 0x73, 0x62, 0x61, 0x6e, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x65, 0x77, 0x5f,
    +0x59, 0x6f, 0x72, 0x6b, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4b, 0x69, 0x65, 0x76, 0x0, 0x41, 0x6d, 0x65,
    +0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x68, 0x75, 0x61, 0x68, 0x75, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69,
    +0x63, 0x61, 0x2f, 0x44, 0x65, 0x6e, 0x76, 0x65, 0x72, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x72, 0x61, 0x73, 0x6e,
    +0x6f, 0x79, 0x61, 0x72, 0x73, 0x6b, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x73, 0x5f, 0x41,
    +0x6e, 0x67, 0x65, 0x6c, 0x65, 0x73, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x69, 0x6a, 0x75, 0x61,
    +0x6e, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x6d, 0x63, 0x68, 0x61, 0x74, 0x6b, 0x61, 0x0, 0x45, 0x75,
    +0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x6f, 0x73, 0x63, 0x6f, 0x77, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69,
    +0x61, 0x2f, 0x48, 0x6f, 0x62, 0x61, 0x72, 0x74, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x6c, 0x61, 0x61, 0x6e, 0x62,
    +0x61, 0x61, 0x74, 0x61, 0x72, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e,
    +0x61, 0x70, 0x6f, 0x6c, 0x69, 0x73, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f,
    +0x56, 0x6c, 0x61, 0x64, 0x69, 0x76, 0x6f, 0x73, 0x74, 0x6f, 0x6b, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42,
    +0x65, 0x72, 0x6c, 0x69, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x73, 0x68, 0x6b, 0x65, 0x6e, 0x74, 0x0,
    +0x41, 0x73, 0x69, 0x61, 0x2f, 0x48, 0x65, 0x62, 0x72, 0x6f, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x59, 0x61, 0x6b,
    +0x75, 0x74, 0x73, 0x6b, 0x0, 0x55, 0x54, 0x43, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x31, 0x34, 0x3a, 0x30, 0x30, 0x0, 0x55,
    +0x54, 0x43, 0x2d, 0x31, 0x33, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x31, 0x32, 0x3a, 0x30, 0x30, 0x0, 0x55,
    +0x54, 0x43, 0x2d, 0x31, 0x31, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x31, 0x30, 0x3a, 0x30, 0x30, 0x0, 0x55,
    +0x54, 0x43, 0x2d, 0x30, 0x39, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x38, 0x3a, 0x30, 0x30, 0x0, 0x55,
    +0x54, 0x43, 0x2d, 0x30, 0x37, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x36, 0x3a, 0x30, 0x30, 0x0, 0x55,
    +0x54, 0x43, 0x2d, 0x30, 0x35, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x34, 0x3a, 0x33, 0x30, 0x0, 0x55,
    +0x54, 0x43, 0x2d, 0x30, 0x34, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x33, 0x3a, 0x33, 0x30, 0x0, 0x55,
    +0x54, 0x43, 0x2d, 0x30, 0x33, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x32, 0x3a, 0x30, 0x30, 0x0, 0x55,
    +0x54, 0x43, 0x2d, 0x30, 0x31, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x0, 0x55,
    +0x54, 0x43, 0x2b, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x31, 0x3a, 0x30, 0x30, 0x0, 0x55,
    +0x54, 0x43, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x33, 0x3a, 0x30, 0x30, 0x0, 0x55,
    +0x54, 0x43, 0x2b, 0x30, 0x33, 0x3a, 0x33, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x34, 0x3a, 0x30, 0x30, 0x0, 0x55,
    +0x54, 0x43, 0x2b, 0x30, 0x34, 0x3a, 0x33, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x35, 0x3a, 0x30, 0x30, 0x0, 0x55,
    +0x54, 0x43, 0x2b, 0x30, 0x35, 0x3a, 0x33, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x35, 0x3a, 0x34, 0x35, 0x0, 0x55,
    +0x54, 0x43, 0x2b, 0x30, 0x36, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x36, 0x3a, 0x33, 0x30, 0x0, 0x55,
    +0x54, 0x43, 0x2b, 0x30, 0x37, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x38, 0x3a, 0x30, 0x30, 0x0, 0x55,
    +0x54, 0x43, 0x2b, 0x30, 0x38, 0x3a, 0x33, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x39, 0x3a, 0x30, 0x30, 0x0, 0x55,
    +0x54, 0x43, 0x2b, 0x30, 0x39, 0x3a, 0x33, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x30, 0x3a, 0x30, 0x30, 0x0, 0x55,
    +0x54, 0x43, 0x2b, 0x31, 0x31, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x32, 0x3a, 0x30, 0x30, 0x0, 0x55,
    +0x54, 0x43, 0x2b, 0x31, 0x33, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x34, 0x3a, 0x30, 0x30, 0x0
     };
     // GENERATED PART ENDS HERE
     
    -- 
    cgit v1.2.3
    
    
    From 9ff6df892925b4b56b842ff206dd672e75e36138 Mon Sep 17 00:00:00 2001
    From: Edward Welbourne 
    Date: Fri, 24 May 2019 14:40:54 +0200
    Subject: Convert the one extant use of QTime as a timer to use a local class
    
    Use QDateTime::currentMSecsSinceEpoch() instead of a QTime with funky
    wrapping at midnight and potential DST glitches.
    
    Change-Id: I2455db5778635fc00b4ffdef6edee6d6793e50eb
    Reviewed-by: Thiago Macieira 
    ---
     src/tools/androiddeployqt/main.cpp | 19 +++++++++++++++++--
     1 file changed, 17 insertions(+), 2 deletions(-)
    
    (limited to 'src')
    
    diff --git a/src/tools/androiddeployqt/main.cpp b/src/tools/androiddeployqt/main.cpp
    index 01c392f8f9..65d95362f7 100644
    --- a/src/tools/androiddeployqt/main.cpp
    +++ b/src/tools/androiddeployqt/main.cpp
    @@ -1,6 +1,6 @@
     /****************************************************************************
     **
    -** Copyright (C) 2016 The Qt Company Ltd.
    +** Copyright (C) 2019 The Qt Company Ltd.
     ** Contact: https://www.qt.io/licensing/
     **
     ** This file is part of the tools applications of the Qt Toolkit.
    @@ -52,6 +52,21 @@
     #define QT_POPEN_READ "r"
     #endif
     
    +class ActionTimer
    +{
    +    qint64 started;
    +public:
    +    ActionTimer() = default;
    +    void start()
    +    {
    +        started = QDateTime::currentMSecsSinceEpoch();
    +    }
    +    int elapsed()
    +    {
    +        return int(QDateTime::currentMSecsSinceEpoch() - started);
    +    }
    +};
    +
     static const bool mustReadOutputAnyway = true; // pclose seems to return the wrong error code unless we read the output
     
     void deleteRecursively(const QString &dirName)
    @@ -138,7 +153,7 @@ struct Options
         bool gradle;
         bool auxMode;
         bool stripLibraries = true;
    -    QTime timer;
    +    ActionTimer timer;
     
         // External tools
         QString sdkPath;
    -- 
    cgit v1.2.3
    
    
    From d2090b764aa23f9b50215aa5d276583117c328d3 Mon Sep 17 00:00:00 2001
    From: Edward Welbourne 
    Date: Fri, 24 May 2019 14:29:54 +0200
    Subject: Convert some deprecations to QT_DEPRECATED_X
    
    To make their replacements easier to find.
    They're in the documentation, but weren't in the source.
    
    Change-Id: Iea936062feaead636e3dd8e93f0b4c82ed8876cb
    Reviewed-by: Thiago Macieira 
    ---
     src/corelib/tools/qdatetime.h | 8 ++++----
     1 file changed, 4 insertions(+), 4 deletions(-)
    
    (limited to 'src')
    
    diff --git a/src/corelib/tools/qdatetime.h b/src/corelib/tools/qdatetime.h
    index 79fd25d762..1ff187a9bd 100644
    --- a/src/corelib/tools/qdatetime.h
    +++ b/src/corelib/tools/qdatetime.h
    @@ -107,8 +107,8 @@ public:
         QString toString(QStringView format) const;
     #endif
     #if QT_DEPRECATED_SINCE(5,0)
    -QT_DEPRECATED inline bool setYMD(int y, int m, int d)
    -{ if (uint(y) <= 99) y += 1900; return setDate(y, m, d); }
    +    QT_DEPRECATED_X("Use setDate() instead") inline bool setYMD(int y, int m, int d)
    +    { if (uint(y) <= 99) y += 1900; return setDate(y, m, d); }
     #endif
     
         bool setDate(int year, int month, int day);
    @@ -342,8 +342,8 @@ public:
         inline bool operator>=(const QDateTime &other) const { return !(*this < other); }
     
     #if QT_DEPRECATED_SINCE(5, 2) // ### Qt 6: remove
    -    QT_DEPRECATED void setUtcOffset(int seconds);
    -    QT_DEPRECATED int utcOffset() const;
    +    QT_DEPRECATED_X("Use setOffsetFromUtc() instead") void setUtcOffset(int seconds);
    +    QT_DEPRECATED_X("Use offsetFromUtc() instead") int utcOffset() const;
     #endif // QT_DEPRECATED_SINCE
     
         static QDateTime currentDateTime();
    -- 
    cgit v1.2.3
    
    
    From ed99a591a83a399458f12341d0a1c0b3152f247a Mon Sep 17 00:00:00 2001
    From: Edward Welbourne 
    Date: Mon, 6 May 2019 18:19:06 +0200
    Subject: Deprecate use of QTime as a timer
    MIME-Version: 1.0
    Content-Type: text/plain; charset=UTF-8
    Content-Transfer-Encoding: 8bit
    
    QElapsedTimer does the job better and without the DST kludges.
    
    Change-Id: Ic4a566f695648cbe069a21ea8d3e84562b665a3c
    Reviewed-by: André Hartmann 
    Reviewed-by: Thiago Macieira 
    ---
     src/corelib/tools/qdatetime.cpp | 16 ++++++----------
     src/corelib/tools/qdatetime.h   |  8 +++++---
     2 files changed, 11 insertions(+), 13 deletions(-)
    
    (limited to 'src')
    
    diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp
    index 0f8c8629a8..9220d210f1 100644
    --- a/src/corelib/tools/qdatetime.cpp
    +++ b/src/corelib/tools/qdatetime.cpp
    @@ -1686,12 +1686,10 @@ bool QDate::isLeapYear(int y)
         \brief The QTime class provides clock time functions.
     
     
    -    A QTime object contains a clock time, which it can express as the
    -    numbers of hours, minutes, seconds, and milliseconds since
    -    midnight. It can read the current time from the system clock and
    -    measure a span of elapsed time. It provides functions for
    -    comparing times and for manipulating a time by adding a number of
    -    milliseconds.
    +    A QTime object contains a clock time, which it can express as the numbers of
    +    hours, minutes, seconds, and milliseconds since midnight. It provides
    +    functions for comparing times and for manipulating a time by adding a number
    +    of milliseconds.
     
         QTime uses the 24-hour clock format; it has no concept of AM/PM.
         Unlike QDateTime, QTime knows nothing about time zones or
    @@ -1718,9 +1716,6 @@ bool QDate::isLeapYear(int y)
         objects; an earlier time is considered smaller than a later one;
         if A.msecsTo(B) is positive, then A < B.
     
    -    QTime can be used to measure a span of elapsed time using the
    -    start(), restart(), and elapsed() functions.
    -
         \sa QDate, QDateTime
     */
     
    @@ -2364,7 +2359,7 @@ bool QTime::isValid(int h, int m, int s, int ms)
         return (uint)h < 24 && (uint)m < 60 && (uint)s < 60 && (uint)ms < 1000;
     }
     
    -
    +#if QT_DEPRECATED_SINCE(5, 14) // ### Qt 6: remove
     /*!
         Sets this time to the current time. This is practical for timing:
     
    @@ -2433,6 +2428,7 @@ int QTime::elapsed() const
             n += 86400 * 1000;
         return n;
     }
    +#endif // Use QElapsedTimer instead !
     
     /*****************************************************************************
       QDateTime static helper functions
    diff --git a/src/corelib/tools/qdatetime.h b/src/corelib/tools/qdatetime.h
    index 1ff187a9bd..3e3b953b52 100644
    --- a/src/corelib/tools/qdatetime.h
    +++ b/src/corelib/tools/qdatetime.h
    @@ -206,9 +206,11 @@ public:
     #endif
         static bool isValid(int h, int m, int s, int ms = 0);
     
    -    void start();
    -    int restart();
    -    int elapsed() const;
    +#if QT_DEPRECATED_SINCE(5, 14) // ### Qt 6: remove
    +    QT_DEPRECATED_X("Use QElapsedTimer instead") void start();
    +    QT_DEPRECATED_X("Use QElapsedTimer instead") int restart();
    +    QT_DEPRECATED_X("Use QElapsedTimer instead") int elapsed() const;
    +#endif
     private:
         enum TimeFlag { NullTime = -1 };
         Q_DECL_CONSTEXPR inline int ds() const { return mds == -1 ? 0 : mds; }
    -- 
    cgit v1.2.3
    
    
    From 5505d25be972948db1621e1511b89b4144aa8bfc Mon Sep 17 00:00:00 2001
    From: Kai Koehne 
    Date: Fri, 17 May 2019 14:30:10 +0200
    Subject: uic: Remove deprecated options
    
    The --no-stringliteral option got introduced by commit d12d2949d1e4ac0
    for 5.10.0, but already deprecated in commit  ff18b02f21a04f7 for 5.12.0.
    
    [ChangeLog][uic] uic does not accept the --no-stringliteral/-s option
    anymore.
    
    Change-Id: I7a0f647ad91b3760bc826884702bf8581f5565f2
    Reviewed-by: Jarek Kobus 
    ---
     src/tools/uic/main.cpp | 7 -------
     1 file changed, 7 deletions(-)
    
    (limited to 'src')
    
    diff --git a/src/tools/uic/main.cpp b/src/tools/uic/main.cpp
    index 166fe78ff7..e689d477bd 100644
    --- a/src/tools/uic/main.cpp
    +++ b/src/tools/uic/main.cpp
    @@ -76,10 +76,6 @@ int runUic(int argc, char *argv[])
         noImplicitIncludesOption.setDescription(QStringLiteral("Disable generation of #include-directives."));
         parser.addOption(noImplicitIncludesOption);
     
    -    QCommandLineOption noStringLiteralOption(QStringList() << QStringLiteral("s") << QStringLiteral("no-stringliteral"));
    -    noStringLiteralOption.setDescription(QStringLiteral("Deprecated. The use of this option won't take any effect."));
    -    parser.addOption(noStringLiteralOption);
    -
         QCommandLineOption postfixOption(QStringLiteral("postfix"));
         postfixOption.setDescription(QStringLiteral("Postfix to add to all generated classnames."));
         postfixOption.setValueName(QStringLiteral("postfix"));
    @@ -124,9 +120,6 @@ int runUic(int argc, char *argv[])
         }
         language::setLanguage(language);
     
    -    if (parser.isSet(noStringLiteralOption))
    -        fprintf(stderr, "The -s, --no-stringliteral option is deprecated and it won't take any effect.\n");
    -
         QString inputFile;
         if (!parser.positionalArguments().isEmpty())
             inputFile = parser.positionalArguments().at(0);
    -- 
    cgit v1.2.3
    
    
    From de752e8994220639b2934b769e83bab0e56a00c9 Mon Sep 17 00:00:00 2001
    From: Marc Mutz 
    Date: Mon, 3 Jun 2019 23:03:30 +0200
    Subject: QLatin1Char: add comparison operators with char
    
    When QT_NO_CAST_FROM_ASCII is in effect, `char == QLatinChar` no longer
    compiles, because the QChar(char) ctor has become private.
    
    Fix by supplying the missing mixed-type operators.
    
    [ChangeLog][QtCore][QLatin1Char] Comparison against char now works
    even in QT_NO_CAST_FROM_ASCII builds.
    
    Change-Id: I86f5ec8e2ddfcda72f5928086cb298bd00b42544
    Reviewed-by: Thiago Macieira 
    ---
     src/corelib/tools/qchar.h | 13 +++++++++++++
     1 file changed, 13 insertions(+)
    
    (limited to 'src')
    
    diff --git a/src/corelib/tools/qchar.h b/src/corelib/tools/qchar.h
    index be344838ed..73344ecf52 100644
    --- a/src/corelib/tools/qchar.h
    +++ b/src/corelib/tools/qchar.h
    @@ -58,6 +58,19 @@ private:
         char ch;
     };
     
    +Q_DECL_CONSTEXPR inline bool operator==(char lhs, QLatin1Char rhs) noexcept { return lhs == rhs.toLatin1(); }
    +Q_DECL_CONSTEXPR inline bool operator!=(char lhs, QLatin1Char rhs) noexcept { return lhs != rhs.toLatin1(); }
    +Q_DECL_CONSTEXPR inline bool operator<=(char lhs, QLatin1Char rhs) noexcept { return lhs <= rhs.toLatin1(); }
    +Q_DECL_CONSTEXPR inline bool operator>=(char lhs, QLatin1Char rhs) noexcept { return lhs >= rhs.toLatin1(); }
    +Q_DECL_CONSTEXPR inline bool operator< (char lhs, QLatin1Char rhs) noexcept { return lhs <  rhs.toLatin1(); }
    +Q_DECL_CONSTEXPR inline bool operator> (char lhs, QLatin1Char rhs) noexcept { return lhs >  rhs.toLatin1(); }
    +
    +Q_DECL_CONSTEXPR inline bool operator==(QLatin1Char lhs, char rhs) noexcept { return lhs.toLatin1() == rhs; }
    +Q_DECL_CONSTEXPR inline bool operator!=(QLatin1Char lhs, char rhs) noexcept { return lhs.toLatin1() != rhs; }
    +Q_DECL_CONSTEXPR inline bool operator<=(QLatin1Char lhs, char rhs) noexcept { return lhs.toLatin1() <= rhs; }
    +Q_DECL_CONSTEXPR inline bool operator>=(QLatin1Char lhs, char rhs) noexcept { return lhs.toLatin1() >= rhs; }
    +Q_DECL_CONSTEXPR inline bool operator< (QLatin1Char lhs, char rhs) noexcept { return lhs.toLatin1() <  rhs; }
    +Q_DECL_CONSTEXPR inline bool operator> (QLatin1Char lhs, char rhs) noexcept { return lhs.toLatin1() >  rhs; }
     
     class Q_CORE_EXPORT QChar {
     public:
    -- 
    cgit v1.2.3
    
    
    From a76ae0a631c8387bc96ec7d358e14f6c86b73f35 Mon Sep 17 00:00:00 2001
    From: Mikhail Svetkin 
    Date: Tue, 20 Mar 2018 14:20:23 +0100
    Subject: rtems: Fix build sha3 (undef ALIGN)
    
    ALIGN macro exists in RTEMS system headers and in sha3 library.
    
    Change-Id: I00cbb5be5598a6a6ca1f011f199da62d658ef9d5
    Reviewed-by: Ryan Chu 
    ---
     src/corelib/tools/qcryptographichash.cpp | 4 ++++
     1 file changed, 4 insertions(+)
    
    (limited to 'src')
    
    diff --git a/src/corelib/tools/qcryptographichash.cpp b/src/corelib/tools/qcryptographichash.cpp
    index 3c79bb797d..ee7657789c 100644
    --- a/src/corelib/tools/qcryptographichash.cpp
    +++ b/src/corelib/tools/qcryptographichash.cpp
    @@ -58,6 +58,10 @@ typedef unsigned char BitSequence;
     typedef unsigned long long DataLength;
     typedef enum { SUCCESS = 0, FAIL = 1, BAD_HASHLEN = 2 } HashReturn;
     
    +#ifdef Q_OS_RTEMS
    +#  undef ALIGN
    +#endif
    +
     #include "../../3rdparty/sha3/KeccakSponge.c"
     typedef spongeState hashState;
     
    -- 
    cgit v1.2.3
    
    
    From 2c51a91e03de48e6a0fa215e265fe4a6a85c02f6 Mon Sep 17 00:00:00 2001
    From: Mikhail Svetkin 
    Date: Thu, 6 Jun 2019 10:18:20 +0200
    Subject: rtems: Disable sys/sem.h include
    
    RTEMS does not have sys/sem.h
    
    Change-Id: I9fe5c5244a4205521493885b39fa0051abcc4539
    Reviewed-by: Volker Hilsheimer 
    
    
    
    Reviewed-by: Thiago Macieira 
    ---
     src/corelib/kernel/qsharedmemory_p.h | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    (limited to 'src')
    
    diff --git a/src/corelib/kernel/qsharedmemory_p.h b/src/corelib/kernel/qsharedmemory_p.h
    index 59802eb6ce..bf7c42dc62 100644
    --- a/src/corelib/kernel/qsharedmemory_p.h
    +++ b/src/corelib/kernel/qsharedmemory_p.h
    @@ -69,7 +69,7 @@ namespace QSharedMemoryPrivate
     #include "qsystemsemaphore.h"
     #include "private/qobject_p.h"
     
    -#if !defined(Q_OS_WIN) && !defined(Q_OS_ANDROID) && !defined(Q_OS_INTEGRITY)
    +#if !defined(Q_OS_WIN) && !defined(Q_OS_ANDROID) && !defined(Q_OS_INTEGRITY) && !defined(Q_OS_RTEMS)
     #  include 
     #endif
     
    -- 
    cgit v1.2.3
    
    
    From 0624c99ea3d52f07c93378fcf75c3121df1b3928 Mon Sep 17 00:00:00 2001
    From: Marc Mutz 
    Date: Thu, 6 Jun 2019 22:03:58 +0200
    Subject: QDistanceField: add missing copy assignment operator
    
    As found by GCC, while compiling qt5/qttools/src/distancefieldgenerator/mainwindow.cpp.
    
    Change-Id: I155c0b8b09bd12c12af0bd69e19747485be960e1
    Reviewed-by: Thiago Macieira 
    ---
     src/gui/text/qdistancefield.cpp | 3 +++
     src/gui/text/qdistancefield_p.h | 1 +
     2 files changed, 4 insertions(+)
    
    (limited to 'src')
    
    diff --git a/src/gui/text/qdistancefield.cpp b/src/gui/text/qdistancefield.cpp
    index 82bb617733..5967c8d3de 100644
    --- a/src/gui/text/qdistancefield.cpp
    +++ b/src/gui/text/qdistancefield.cpp
    @@ -904,6 +904,9 @@ QDistanceField::QDistanceField(const QDistanceField &other)
         d = other.d;
     }
     
    +QDistanceField &QDistanceField::operator=(const QDistanceField &)
    +    = default;
    +
     QDistanceField::QDistanceField(const QRawFont &font, glyph_t glyph, bool doubleResolution)
     {
         setGlyph(font, glyph, doubleResolution);
    diff --git a/src/gui/text/qdistancefield_p.h b/src/gui/text/qdistancefield_p.h
    index 1a1b6866a2..dc5d5a9a02 100644
    --- a/src/gui/text/qdistancefield_p.h
    +++ b/src/gui/text/qdistancefield_p.h
    @@ -95,6 +95,7 @@ public:
         QDistanceField(QFontEngine *fontEngine, glyph_t glyph, bool doubleResolution = false);
         QDistanceField(const QPainterPath &path, glyph_t glyph, bool doubleResolution = false);
         QDistanceField(const QDistanceField &other);
    +    QDistanceField &operator=(const QDistanceField &other);
     
         bool isNull() const;
     
    -- 
    cgit v1.2.3
    
    
    From 3619e87ba1c0b11b8406fee3e1fe5c1e96abb7ef Mon Sep 17 00:00:00 2001
    From: Edward Welbourne 
    Date: Tue, 4 Jun 2019 19:49:12 +0200
    Subject: Fix a minor grammar glitch in new string / byte-array doc note
    
    Amends 8845caa057cfcf54f7d46621adb3393c13747ffb.
    
    Change-Id: I4bf09b9c1fff52815de58070fbe4ff0c08eff53f
    Reviewed-by: Marc Mutz 
    
    
    Reviewed-by: Thiago Macieira 
    ---
     src/corelib/tools/qbytearray.cpp | 2 +-
     src/corelib/tools/qstring.cpp    | 2 +-
     2 files changed, 2 insertions(+), 2 deletions(-)
    
    (limited to 'src')
    
    diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp
    index 5c2af7e058..9526350126 100644
    --- a/src/corelib/tools/qbytearray.cpp
    +++ b/src/corelib/tools/qbytearray.cpp
    @@ -1439,7 +1439,7 @@ QByteArray &QByteArray::operator=(const char *str)
     
         \note Before Qt 5.14 it was possible to use this operator to access
         a character at an out-of-bounds position in the byte array, and
    -    then assign to such position, causing the byte array to be
    +    then assign to such a position, causing the byte array to be
         automatically resized. Furthermore, assigning a value to the
         returned QByteRef would cause a detach of the byte array, even if the
         byte array has been copied in the meanwhile (and the QByteRef kept
    diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
    index 06636098af..963c2a4d34 100644
    --- a/src/corelib/tools/qstring.cpp
    +++ b/src/corelib/tools/qstring.cpp
    @@ -5800,7 +5800,7 @@ QString QString::trimmed_helper(QString &str)
     
         \note Before Qt 5.14 it was possible to use this operator to access
         a character at an out-of-bounds position in the string, and
    -    then assign to such position, causing the string to be
    +    then assign to such a position, causing the string to be
         automatically resized. Furthermore, assigning a value to the
         returned QCharRef would cause a detach of the string, even if the
         string has been copied in the meanwhile (and the QCharRef kept
    -- 
    cgit v1.2.3
    
    
    From cbc9d8947842b97f28e3acb2d87d80b4861d00b9 Mon Sep 17 00:00:00 2001
    From: Marc Mutz 
    Date: Wed, 5 Jun 2019 21:59:46 +0200
    Subject: QInputDeviceManager: replace a QMap with a
     std::array
    MIME-Version: 1.0
    Content-Type: text/plain; charset=UTF-8
    Content-Transfer-Encoding: 8bit
    
    QInputDeviceManager::DeviceType is a (non-flag) enum with all of five
    values. Using a self-rebalancing rb-tree to map these to an int is
    overkill. An array can do the job just as well and better, given the
    enum values are consecutive, and even if some don't make sense (like
    Unknown), the waste caused by unused array slots is more than
    compensated by the lack of any memory allocations. Even more so as the
    array API is 1:1 identical with the map's for the use-case at hand.
    
    Saves 1.2KiB in text size on optimized Linux AMD64 GCC 9.1 builds.
    
    Change-Id: I1bfa115ac75e2f7d9a4bd9a0e3f3241bf68c9989
    Reviewed-by: Tor Arne Vestbø 
    ---
     src/gui/kernel/qinputdevicemanager.cpp   | 4 ++--
     src/gui/kernel/qinputdevicemanager_p.h   | 4 +++-
     src/gui/kernel/qinputdevicemanager_p_p.h | 5 +++--
     3 files changed, 8 insertions(+), 5 deletions(-)
    
    (limited to 'src')
    
    diff --git a/src/gui/kernel/qinputdevicemanager.cpp b/src/gui/kernel/qinputdevicemanager.cpp
    index 6e4e5a9c93..11442407e1 100644
    --- a/src/gui/kernel/qinputdevicemanager.cpp
    +++ b/src/gui/kernel/qinputdevicemanager.cpp
    @@ -75,13 +75,13 @@ int QInputDeviceManager::deviceCount(DeviceType type) const
     
     int QInputDeviceManagerPrivate::deviceCount(QInputDeviceManager::DeviceType type) const
     {
    -    return m_deviceCount.value(type);
    +    return m_deviceCount[type];
     }
     
     void QInputDeviceManagerPrivate::setDeviceCount(QInputDeviceManager::DeviceType type, int count)
     {
         Q_Q(QInputDeviceManager);
    -    if (m_deviceCount.value(type) != count) {
    +    if (m_deviceCount[type] != count) {
             m_deviceCount[type] = count;
             emit q->deviceListChanged(type);
         }
    diff --git a/src/gui/kernel/qinputdevicemanager_p.h b/src/gui/kernel/qinputdevicemanager_p.h
    index 74494d712b..1d20b102e3 100644
    --- a/src/gui/kernel/qinputdevicemanager_p.h
    +++ b/src/gui/kernel/qinputdevicemanager_p.h
    @@ -69,7 +69,9 @@ public:
             DeviceTypePointer,
             DeviceTypeKeyboard,
             DeviceTypeTouch,
    -        DeviceTypeTablet
    +        DeviceTypeTablet,
    +
    +        NumDeviceTypes
         };
     
         QInputDeviceManager(QObject *parent = nullptr);
    diff --git a/src/gui/kernel/qinputdevicemanager_p_p.h b/src/gui/kernel/qinputdevicemanager_p_p.h
    index 0a91252fbc..871f9315c3 100644
    --- a/src/gui/kernel/qinputdevicemanager_p_p.h
    +++ b/src/gui/kernel/qinputdevicemanager_p_p.h
    @@ -52,10 +52,11 @@
     //
     
     #include 
    -#include 
     #include 
     #include "qinputdevicemanager_p.h"
     
    +#include 
    +
     QT_BEGIN_NAMESPACE
     
     class Q_GUI_EXPORT QInputDeviceManagerPrivate : public QObjectPrivate
    @@ -68,7 +69,7 @@ public:
         int deviceCount(QInputDeviceManager::DeviceType type) const;
         void setDeviceCount(QInputDeviceManager::DeviceType type, int count);
     
    -    QMap m_deviceCount;
    +    std::array m_deviceCount;
     
         Qt::KeyboardModifiers keyboardModifiers;
     };
    -- 
    cgit v1.2.3
    
    
    From 638f2749a052a22622de5ab01dfe3913644c2c25 Mon Sep 17 00:00:00 2001
    From: Anton Kudryavtsev 
    Date: Thu, 11 Apr 2019 15:57:59 +0300
    Subject: QLatin1String, QStringView: add contains
    
    [ChangeLog][QtCore][QLatin1String] Added contains().
    
    [ChangeLog][QtCore][QStringView] Added contains().
    
    Change-Id: I19fd2e155180edd8620c520f4e60a1f86f0603ac
    Reviewed-by: Marc Mutz 
    ---
     src/corelib/tools/qstring.cpp     | 51 +++++++++++++++++++++++++++++++++++++--
     src/corelib/tools/qstring.h       | 29 +++++++++++++++++++---
     src/corelib/tools/qstringview.cpp | 15 ++++++++++++
     src/corelib/tools/qstringview.h   |  6 +++++
     4 files changed, 96 insertions(+), 5 deletions(-)
    
    (limited to 'src')
    
    diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
    index aa602559fe..06636098af 100644
    --- a/src/corelib/tools/qstring.cpp
    +++ b/src/corelib/tools/qstring.cpp
    @@ -4273,7 +4273,7 @@ int QString::count(const QStringRef &str, Qt::CaseSensitivity cs) const
         return int(qt_string_count(QStringView(unicode(), size()), QStringView(str.unicode(), str.size()), cs));
     }
     
    -
    +#if QT_STRINGVIEW_LEVEL < 2
     /*! \fn bool QString::contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
     
         Returns \c true if this string contains an occurrence of the string
    @@ -4287,6 +4287,7 @@ int QString::count(const QStringRef &str, Qt::CaseSensitivity cs) const
     
         \sa indexOf(), count()
     */
    +#endif // QT_STRINGVIEW_LEVEL < 2
     
     /*! \fn bool QString::contains(QLatin1String str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
         \since 5.3
    @@ -4305,6 +4306,7 @@ int QString::count(const QStringRef &str, Qt::CaseSensitivity cs) const
         character \a ch; otherwise returns \c false.
     */
     
    +#if QT_STRINGVIEW_LEVEL < 2
     /*! \fn bool QString::contains(const QStringRef &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
         \since 4.8
     
    @@ -4316,6 +4318,20 @@ int QString::count(const QStringRef &str, Qt::CaseSensitivity cs) const
     
         \sa indexOf(), count()
     */
    +#endif // QT_STRINGVIEW_LEVEL < 2
    +
    +/*! \fn bool QString::contains(QStringView str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
    +    \since 5.14
    +    \overload contains()
    +
    +    Returns \c true if this string contains an occurrence of the string view
    +    \a str; otherwise returns \c false.
    +
    +    If \a cs is Qt::CaseSensitive (default), the search is
    +    case sensitive; otherwise the search is case insensitive.
    +
    +    \sa indexOf(), count()
    +*/
     
     /*! \fn bool QString::contains(const QRegExp &rx) const
     
    @@ -9530,6 +9546,21 @@ QString &QString::setRawData(const QChar *unicode, int size)
         \sa QString::indexOf()
     */
     
    +/*!
    +    \fn bool QLatin1String::contains(QStringView str, Qt::CaseSensitivity cs) const
    +    \fn bool QLatin1String::contains(QLatin1String l1, Qt::CaseSensitivity cs) const
    +    \fn bool QLatin1String::contains(QChar c, Qt::CaseSensitivity cs) const
    +    \since 5.14
    +
    +    Returns \c true if this Latin-1 string contains an occurrence of the string-view
    +    \a str, Latin-1 string \a l1, or character \a ch; otherwise returns \c false.
    +
    +    If \a cs is Qt::CaseSensitive (the default), the search is
    +    case-sensitive; otherwise the search is case-insensitive.
    +
    +    \sa indexOf(), QStringView::contains(), QStringView::indexOf(), QString::indexOf()
    +*/
    +
     /*!
         \fn QLatin1String::const_iterator QLatin1String::begin() const
         \since 5.10
    @@ -11514,7 +11545,7 @@ bool QStringRef::endsWith(const QStringRef &str, Qt::CaseSensitivity cs) const
         return qt_ends_with(*this, str, cs);
     }
     
    -
    +#if QT_STRINGVIEW_LEVEL < 2
     /*! \fn bool QStringRef::contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
     
         \since 4.8
    @@ -11526,6 +11557,7 @@ bool QStringRef::endsWith(const QStringRef &str, Qt::CaseSensitivity cs) const
     
         \sa indexOf(), count()
     */
    +#endif // QT_STRINGVIEW_LEVEL < 2
     
     /*! \fn bool QStringRef::contains(QChar ch, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
     
    @@ -11540,6 +11572,7 @@ bool QStringRef::endsWith(const QStringRef &str, Qt::CaseSensitivity cs) const
     
     */
     
    +#if QT_STRINGVIEW_LEVEL < 2
     /*! \fn bool QStringRef::contains(const QStringRef &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
         \overload contains()
         \since 4.8
    @@ -11552,6 +11585,7 @@ bool QStringRef::endsWith(const QStringRef &str, Qt::CaseSensitivity cs) const
     
         \sa indexOf(), count()
     */
    +#endif // QT_STRINGVIEW_LEVEL < 2
     
     /*! \fn bool QStringRef::contains(QLatin1String str, Qt::CaseSensitivity cs) const
         \since 4.8
    @@ -11566,6 +11600,19 @@ bool QStringRef::endsWith(const QStringRef &str, Qt::CaseSensitivity cs) const
         \sa indexOf(), count()
     */
     
    +/*! \fn bool QStringRef::contains(QStringView str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
    +    \since 5.14
    +    \overload contains()
    +
    +    Returns \c true if this string reference contains an occurrence of
    +    the string view \a str; otherwise returns \c false.
    +
    +    If \a cs is Qt::CaseSensitive (default), the search is
    +    case sensitive; otherwise the search is case insensitive.
    +
    +    \sa indexOf(), count()
    +*/
    +
     static inline qsizetype qt_last_index_of(QStringView haystack, QChar needle,
                                        qsizetype from, Qt::CaseSensitivity cs)
     {
    diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h
    index 0f7b015bef..da8260a999 100644
    --- a/src/corelib/tools/qstring.h
    +++ b/src/corelib/tools/qstring.h
    @@ -138,6 +138,13 @@ public:
         Q_REQUIRED_RESULT inline int indexOf(QChar c, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
         { return int(QtPrivate::findString(*this, from, QStringView(&c, 1), cs)); } // ### Qt6: qsize
     
    +    Q_REQUIRED_RESULT bool contains(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
    +    { return indexOf(s, 0, cs) != -1; }
    +    Q_REQUIRED_RESULT bool contains(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
    +    { return indexOf(s, 0, cs) != -1; }
    +    Q_REQUIRED_RESULT inline bool contains(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
    +    { return indexOf(QStringView(&c, 1), 0, cs) != -1; }
    +
         using value_type = const char;
         using reference = value_type&;
         using const_reference = reference;
    @@ -224,6 +231,8 @@ bool QStringView::endsWith(QLatin1String s, Qt::CaseSensitivity cs) const noexce
     { return QtPrivate::endsWith(*this, s, cs); }
     qsizetype QStringView::indexOf(QLatin1String s, qsizetype from, Qt::CaseSensitivity cs) const noexcept
     { return QtPrivate::findString(*this, from, s, cs); }
    +bool QStringView::contains(QLatin1String s, Qt::CaseSensitivity cs) const noexcept
    +{ return indexOf(s, 0, cs) != qsizetype(-1); }
     
     class Q_CORE_EXPORT QString
     {
    @@ -351,9 +360,12 @@ public:
         int lastIndexOf(const QStringRef &s, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
     
         inline bool contains(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
    +#if QT_STRINGVIEW_LEVEL < 2
         inline bool contains(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
    -    inline bool contains(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
         inline bool contains(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
    +#endif
    +    inline bool contains(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
    +    inline bool contains(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
         int count(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
         int count(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
         int count(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
    @@ -1240,14 +1252,18 @@ inline QString::const_iterator QString::cend() const
     { return reinterpret_cast(d->data() + d->size); }
     inline QString::const_iterator QString::constEnd() const
     { return reinterpret_cast(d->data() + d->size); }
    +#if QT_STRINGVIEW_LEVEL < 2
     inline bool QString::contains(const QString &s, Qt::CaseSensitivity cs) const
     { return indexOf(s, 0, cs) != -1; }
     inline bool QString::contains(const QStringRef &s, Qt::CaseSensitivity cs) const
     { return indexOf(s, 0, cs) != -1; }
    +#endif
     inline bool QString::contains(QLatin1String s, Qt::CaseSensitivity cs) const
     { return indexOf(s, 0, cs) != -1; }
     inline bool QString::contains(QChar c, Qt::CaseSensitivity cs) const
     { return indexOf(c, 0, cs) != -1; }
    +inline bool QString::contains(QStringView s, Qt::CaseSensitivity cs) const noexcept
    +{ return indexOf(s, 0, cs) != -1; }
     
     #if QT_DEPRECATED_SINCE(5, 9)
     inline bool operator==(QString::Null, QString::Null) { return true; }
    @@ -1528,10 +1544,13 @@ public:
         int lastIndexOf(QLatin1String str, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
         int lastIndexOf(const QStringRef &str, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
     
    +#if QT_STRINGVIEW_LEVEL < 2
         inline bool contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
    +    inline bool contains(const QStringRef &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
    +#endif
         inline bool contains(QChar ch, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
         inline bool contains(QLatin1String str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
    -    inline bool contains(const QStringRef &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
    +    inline bool contains(QStringView str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
     
         int count(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
         int count(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
    @@ -1893,13 +1912,17 @@ inline int QStringRef::localeAwareCompare(const QStringRef &s1, const QString &s
     inline int QStringRef::localeAwareCompare(const QStringRef &s1, const QStringRef &s2)
     { return QString::localeAwareCompare_helper(s1.constData(), s1.length(), s2.constData(), s2.length()); }
     
    +#if QT_STRINGVIEW_LEVEL < 2
     inline bool QStringRef::contains(const QString &s, Qt::CaseSensitivity cs) const
     { return indexOf(s, 0, cs) != -1; }
    +inline bool QStringRef::contains(const QStringRef &s, Qt::CaseSensitivity cs) const
    +{ return indexOf(s, 0, cs) != -1; }
    +#endif
     inline bool QStringRef::contains(QLatin1String s, Qt::CaseSensitivity cs) const
     { return indexOf(s, 0, cs) != -1; }
     inline bool QStringRef::contains(QChar c, Qt::CaseSensitivity cs) const
     { return indexOf(c, 0, cs) != -1; }
    -inline bool QStringRef::contains(const QStringRef &s, Qt::CaseSensitivity cs) const
    +inline bool QStringRef::contains(QStringView s, Qt::CaseSensitivity cs) const noexcept
     { return indexOf(s, 0, cs) != -1; }
     
     inline QString &QString::insert(int i, const QStringRef &s)
    diff --git a/src/corelib/tools/qstringview.cpp b/src/corelib/tools/qstringview.cpp
    index 8c2b52ea09..050097b443 100644
    --- a/src/corelib/tools/qstringview.cpp
    +++ b/src/corelib/tools/qstringview.cpp
    @@ -739,6 +739,21 @@ QT_BEGIN_NAMESPACE
         \sa QString::indexOf()
     */
     
    +/*!
    +    \fn bool QStringView::contains(QStringView str, Qt::CaseSensitivity cs) const
    +    \fn bool QStringView::contains(QLatin1String l1, Qt::CaseSensitivity cs) const
    +    \fn bool QStringView::contains(QChar c, Qt::CaseSensitivity cs) const
    +    \since 5.14
    +
    +    Returns \c true if this string-view contains an occurrence of the string-view
    +    \a str, Latin-1 string \a l1, or character \a ch; otherwise returns \c false.
    +
    +    If \a cs is Qt::CaseSensitive (the default), the search is
    +    case-sensitive; otherwise the search is case-insensitive.
    +
    +    \sa indexOf()
    +*/
    +
     /*!
         \fn QByteArray QStringView::toLatin1() const
     
    diff --git a/src/corelib/tools/qstringview.h b/src/corelib/tools/qstringview.h
    index bbf51b24f6..2c93b31385 100644
    --- a/src/corelib/tools/qstringview.h
    +++ b/src/corelib/tools/qstringview.h
    @@ -276,6 +276,12 @@ public:
         { return QtPrivate::findString(*this, from, s, cs); }
         Q_REQUIRED_RESULT inline qsizetype indexOf(QLatin1String s, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
     
    +    Q_REQUIRED_RESULT bool contains(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
    +    { return indexOf(QStringView(&c, 1), 0, cs) != qsizetype(-1); }
    +    Q_REQUIRED_RESULT bool contains(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
    +    { return indexOf(s, 0, cs) != qsizetype(-1); }
    +    Q_REQUIRED_RESULT inline bool contains(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
    +
         Q_REQUIRED_RESULT bool isRightToLeft() const noexcept
         { return QtPrivate::isRightToLeft(*this); }
     
    -- 
    cgit v1.2.3
    
    
    From 5905f7a4af4885024455ede3dc2daf5d3adaa18c Mon Sep 17 00:00:00 2001
    From: Kai Koehne 
    Date: Tue, 4 Jun 2019 14:44:42 +0200
    Subject: Fix definition of QT_DEPRECATED_SINCE
    MIME-Version: 1.0
    Content-Type: text/plain; charset=UTF-8
    Content-Transfer-Encoding: 8bit
    
    Otherwise any use of QT_DEPRECATED_SINCE will cause a warning:
    
    src/corelib/global/qglobal.h:382:77: error: expected unqualified-id before ‘)’ token
    
    This amends 220028d37c
    
    Change-Id: Ifa2be1dd8852e4aac0db83b0b4ae15d2f666c550
    Reviewed-by: Christian Ehrlicher 
    ---
     src/corelib/global/qglobal.h | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    (limited to 'src')
    
    diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
    index 24d250d923..87ae704ca4 100644
    --- a/src/corelib/global/qglobal.h
    +++ b/src/corelib/global/qglobal.h
    @@ -379,7 +379,7 @@ typedef double qreal;
     #define QT_DEPRECATED_VERSION_X_5(minor, text)      QT_DEPRECATED_VERSION_X_5_##minor(text)
     #define QT_DEPRECATED_VERSION_X(major, minor, text) QT_DEPRECATED_VERSION_X_##major(minor, text)
     
    -#define QT_DEPRECATED_VERSION_5(minor)      QT_DEPRECATED_VERSION_5_##minor()
    +#define QT_DEPRECATED_VERSION_5(minor)      QT_DEPRECATED_VERSION_5_##minor
     #define QT_DEPRECATED_VERSION(major, minor) QT_DEPRECATED_VERSION_##major(minor)
     
     /*
    -- 
    cgit v1.2.3
    
    
    From b2587f9ea40c89e8d7c21bfeb34ccdb67c804c81 Mon Sep 17 00:00:00 2001
    From: Marc Mutz 
    Date: Sat, 1 Jun 2019 06:25:38 +0200
    Subject: QFile: fix coding style violation
    MIME-Version: 1.0
    Content-Type: text/plain; charset=UTF-8
    Content-Transfer-Encoding: 8bit
    
    Amends dd8131e3b25a4ac60eb55022b69b374f0b9a476c.
    
    Change-Id: Ic7d440816ee7bada49740f15919e404860dd8ac7
    Reviewed-by: Giuseppe D'Angelo 
    Reviewed-by: Thiago Macieira 
    
    
    
    Reviewed-by: Mårten Nordheim 
    ---
     src/corelib/io/qfile.cpp | 3 ++-
     1 file changed, 2 insertions(+), 1 deletion(-)
    
    (limited to 'src')
    
    diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp
    index 13af113da1..8d871904bc 100644
    --- a/src/corelib/io/qfile.cpp
    +++ b/src/corelib/io/qfile.cpp
    @@ -62,7 +62,8 @@
     QT_BEGIN_NAMESPACE
     
     Q_DECL_COLD_FUNCTION
    -static bool file_already_open(QFile &file, const char *where = nullptr) {
    +static bool file_already_open(QFile &file, const char *where = nullptr)
    +{
         qWarning("QFile::%s: File (%ls) already open", where ? where : "open", qUtf16Printable(file.fileName()));
         return false;
     }
    -- 
    cgit v1.2.3
    
    
    From 2596a8a55ce3c9532701c2cf1f353b93df4bd893 Mon Sep 17 00:00:00 2001
    From: Marc Mutz 
    Date: Mon, 27 May 2019 16:56:12 +0200
    Subject: QSharedNetworkSessionManager: clean up
    MIME-Version: 1.0
    Content-Type: text/plain; charset=UTF-8
    Content-Transfer-Encoding: 8bit
    
    Under no circumstance must Qt code define a non-public qHash()
    overload of a public Qt type. If you can't provide a public qHash()
    for the type, you can't use QHash. Period. This is because if we don't
    provide a qHash() function, the user will have to provide one, and
    then we have an ODR violation, iow: UB.
    
    So, port away from QHash and qHash and use std::unordered_map, which
    allows to pass a custom hash function - just what we needed.
    
    Also fix other issues of the code:
    
    - Use a function object as the deleter of the QSharedPointer, to allow
      inlining the function call.
    
    - Avoid double lookup in case of a cache miss.
    
    - Don't use direct initialization syntax for pointer variables. That's
      just ... weird.
    
    Change-Id: Ica8bff728c1bd1cbb2fb43aa03a99bcb7ac2f7cc
    Reviewed-by: Mårten Nordheim 
    ---
     src/network/bearer/qsharednetworksession.cpp | 34 ++++++++++++----------------
     src/network/bearer/qsharednetworksession_p.h | 16 ++++++++++---
     2 files changed, 27 insertions(+), 23 deletions(-)
    
    (limited to 'src')
    
    diff --git a/src/network/bearer/qsharednetworksession.cpp b/src/network/bearer/qsharednetworksession.cpp
    index fc01acb8b4..af543f77e3 100644
    --- a/src/network/bearer/qsharednetworksession.cpp
    +++ b/src/network/bearer/qsharednetworksession.cpp
    @@ -57,36 +57,30 @@ inline QSharedNetworkSessionManager* sharedNetworkSessionManager()
         return rv;
     }
     
    -static void doDeleteLater(QObject* obj)
    -{
    -    obj->deleteLater();
    -}
    +struct DeleteLater {
    +    void operator()(QObject* obj) const
    +    {
    +        obj->deleteLater();
    +    }
    +};
     
     QSharedPointer QSharedNetworkSessionManager::getSession(const QNetworkConfiguration &config)
     {
    -    QSharedNetworkSessionManager *m(sharedNetworkSessionManager());
    -    const auto it = m->sessions.constFind(config);
    +    QSharedNetworkSessionManager *m = sharedNetworkSessionManager();
    +    auto &entry = m->sessions[config];
         //if already have a session, return it
    -    if (it != m->sessions.cend()) {
    -        QSharedPointer p = it.value().toStrongRef();
    -        if (!p.isNull())
    -            return p;
    -    }
    +    if (auto p = entry.toStrongRef())
    +        return p;
         //otherwise make one
    -    QSharedPointer session(new QNetworkSession(config), doDeleteLater);
    -    m->sessions[config] = session;
    +    QSharedPointer session(new QNetworkSession(config), DeleteLater{});
    +    entry = session;
         return session;
     }
     
     void QSharedNetworkSessionManager::setSession(const QNetworkConfiguration &config, QSharedPointer session)
     {
    -    QSharedNetworkSessionManager *m(sharedNetworkSessionManager());
    -    m->sessions[config] = session;
    -}
    -
    -uint qHash(const QNetworkConfiguration& config)
    -{
    -    return ((uint)config.type()) | (((uint)config.bearerType()) << 8) | (((uint)config.purpose()) << 16);
    +    QSharedNetworkSessionManager *m = sharedNetworkSessionManager();
    +    m->sessions[config] = std::move(session);
     }
     
     QT_END_NAMESPACE
    diff --git a/src/network/bearer/qsharednetworksession_p.h b/src/network/bearer/qsharednetworksession_p.h
    index 001b8af02a..f22f9eeacb 100644
    --- a/src/network/bearer/qsharednetworksession_p.h
    +++ b/src/network/bearer/qsharednetworksession_p.h
    @@ -54,16 +54,26 @@
     #include 
     #include "qnetworksession.h"
     #include "qnetworkconfiguration.h"
    -#include 
     #include 
     #include 
     #include 
     
    +#include 
    +
     #ifndef QT_NO_BEARERMANAGEMENT
     
     QT_BEGIN_NAMESPACE
     
    -uint qHash(const QNetworkConfiguration& config);
    +namespace QtPrivate {
    +struct NetworkConfigurationHash {
    +    using result_type = size_t;
    +    using argument_type = QNetworkConfiguration;
    +    size_t operator()(const QNetworkConfiguration &config) const noexcept
    +    {
    +        return std::hash{}(size_t(config.type()) | (size_t(config.bearerType()) << 8) | (size_t(config.purpose()) << 16));
    +    }
    +};
    +}
     
     class QSharedNetworkSessionManager
     {
    @@ -71,7 +81,7 @@ public:
         static QSharedPointer getSession(const QNetworkConfiguration &config);
         static void setSession(const QNetworkConfiguration &config, QSharedPointer session);
     private:
    -    QHash > sessions;
    +    std::unordered_map, QtPrivate::NetworkConfigurationHash> sessions;
     };
     
     QT_END_NAMESPACE
    -- 
    cgit v1.2.3
    
    
    From dea7110b29c5c68a5b09454c968324042ed1b607 Mon Sep 17 00:00:00 2001
    From: Marc Mutz 
    Date: Sat, 16 Dec 2017 19:19:38 +0100
    Subject: QGestureManager: clean up cleanupCachedGestures()
    
    - use logarithmic QMap::find() instead of iterate-and-compare-with-key
      (linear)
    
    - don't convert a QList to a QSet just to use QSet -=, just iterate
      over QSet::remove(): QSet::subtract() doesn't do anything more
      fancy, either (saves memory allocations)
    
    - replace Q_FOREACH with ranged-for, avoid copies
    
    Change-Id: I451f034767b079efa9ee19e2c1fe7dc4af2d9bea
    Reviewed-by: Richard Moe Gustavsen 
    ---
     src/widgets/kernel/qgesturemanager.cpp | 40 +++++++++++++++-------------------
     1 file changed, 18 insertions(+), 22 deletions(-)
    
    (limited to 'src')
    
    diff --git a/src/widgets/kernel/qgesturemanager.cpp b/src/widgets/kernel/qgesturemanager.cpp
    index 7632521117..ff7bc1eccf 100644
    --- a/src/widgets/kernel/qgesturemanager.cpp
    +++ b/src/widgets/kernel/qgesturemanager.cpp
    @@ -167,30 +167,26 @@ void QGestureManager::unregisterGestureRecognizer(Qt::GestureType type)
     
     void QGestureManager::cleanupCachedGestures(QObject *target, Qt::GestureType type)
     {
    -    QMap >::Iterator iter = m_objectGestures.begin();
    -    while (iter != m_objectGestures.end()) {
    -        ObjectGesture objectGesture = iter.key();
    -        if (objectGesture.gesture == type && target == objectGesture.object) {
    -            QSet gestures = QSet(iter.value().constBegin(), iter.value().constEnd());
    -            for (QHash >::iterator
    -                 it = m_obsoleteGestures.begin(), e = m_obsoleteGestures.end(); it != e; ++it) {
    -                it.value() -= gestures;
    -            }
    -            foreach (QGesture *g, gestures) {
    -                m_deletedRecognizers.remove(g);
    -                m_gestureToRecognizer.remove(g);
    -                m_maybeGestures.remove(g);
    -                m_activeGestures.remove(g);
    -                m_gestureOwners.remove(g);
    -                m_gestureTargets.remove(g);
    -                m_gesturesToDelete.insert(g);
    -            }
    +    const auto iter = m_objectGestures.find({target, type});
    +    if (iter == m_objectGestures.end())
    +        return;
     
    -            iter = m_objectGestures.erase(iter);
    -        } else {
    -            ++iter;
    -        }
    +    const QList &gestures = iter.value();
    +    for (auto &e : m_obsoleteGestures) {
    +        for (QGesture *g : gestures)
    +            e -= g;
         }
    +    for (QGesture *g : gestures) {
    +        m_deletedRecognizers.remove(g);
    +        m_gestureToRecognizer.remove(g);
    +        m_maybeGestures.remove(g);
    +        m_activeGestures.remove(g);
    +        m_gestureOwners.remove(g);
    +        m_gestureTargets.remove(g);
    +        m_gesturesToDelete.insert(g);
    +    }
    +
    +    m_objectGestures.erase(iter);
     }
     
     // get or create a QGesture object that will represent the state for a given object, used by the recognizer
    -- 
    cgit v1.2.3
    
    
    From b3c52e82245f46af9ce633a6de1e4e41fb9f3f6d Mon Sep 17 00:00:00 2001
    From: Giuseppe D'Angelo 
    Date: Sun, 10 Feb 2019 18:43:05 +0100
    Subject: Simplify {to,from}Std{List,Vector}
    
    Use the newly-added range constructors.
    
    Change-Id: I7f1d2699d88656fb7dddd11a9d781d810d45b0b4
    Reviewed-by: Marc Mutz 
    ---
     src/corelib/tools/qlist.h   | 15 ++++-----------
     src/corelib/tools/qvector.h |  2 +-
     2 files changed, 5 insertions(+), 12 deletions(-)
    
    (limited to 'src')
    
    diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h
    index 04c1f12f5f..70bbc11ad2 100644
    --- a/src/corelib/tools/qlist.h
    +++ b/src/corelib/tools/qlist.h
    @@ -414,10 +414,10 @@ public:
     
         Q_DECL_DEPRECATED_X("Use QList(list.begin(), list.end()) instead.")
         static inline QList fromStdList(const std::list &list)
    -    { QList tmp; std::copy(list.begin(), list.end(), std::back_inserter(tmp)); return tmp; }
    +    { return QList(list.begin(), list.end()); }
         Q_DECL_DEPRECATED_X("Use std::list(list.begin(), list.end()) instead.")
         inline std::list toStdList() const
    -    { std::list tmp; std::copy(constBegin(), constEnd(), std::back_inserter(tmp)); return tmp; }
    +    { return std::list(begin(), end()); }
     #endif
     
     private:
    @@ -1105,10 +1105,7 @@ inline int QList::count_impl(const T &t, QListData::ArrayCompatibleLayout) co
     template 
     Q_OUTOFLINE_TEMPLATE QVector QList::toVector() const
     {
    -    QVector result(size());
    -    for (int i = 0; i < size(); ++i)
    -        result[i] = at(i);
    -    return result;
    +    return QVector(begin(), end());
     }
     
     template 
    @@ -1120,11 +1117,7 @@ QList QList::fromVector(const QVector &vector)
     template 
     Q_OUTOFLINE_TEMPLATE QList QVector::toList() const
     {
    -    QList result;
    -    result.reserve(size());
    -    for (int i = 0; i < size(); ++i)
    -        result.append(at(i));
    -    return result;
    +    return QList(begin(), end());
     }
     
     template 
    diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h
    index c223e4efa0..5d68a283bd 100644
    --- a/src/corelib/tools/qvector.h
    +++ b/src/corelib/tools/qvector.h
    @@ -303,7 +303,7 @@ public:
     #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
         Q_DECL_DEPRECATED_X("Use QVector(vector.begin(), vector.end()) instead.")
         static inline QVector fromStdVector(const std::vector &vector)
    -    { QVector tmp; tmp.reserve(int(vector.size())); std::copy(vector.begin(), vector.end(), std::back_inserter(tmp)); return tmp; }
    +    { return QVector(vector.begin(), vector.end()); }
         Q_DECL_DEPRECATED_X("Use std::vector(vector.begin(), vector.end()) instead.")
         inline std::vector toStdVector() const
         { return std::vector(d->begin(), d->end()); }
    -- 
    cgit v1.2.3
    
    
    From d7093487a36b0b1a35c28d065f4f0a5890676216 Mon Sep 17 00:00:00 2001
    From: Mikhail Svetkin 
    Date: Tue, 20 Mar 2018 14:27:45 +0100
    Subject: rtems: Disable fork feature and fix compilation in corelib/io
    
    RTEMS does not support fork.
    RTEMS has LOCK_EX and LOCK_NB defines but does not have flock.
    
    Change-Id: I2b1774435bc972f53596f4163ec410b9d22aca4a
    Reviewed-by: Ryan Chu 
    ---
     src/corelib/io/io.pri                | 2 +-
     src/corelib/io/qlockfile_unix.cpp    | 5 +++++
     src/corelib/io/qstorageinfo_unix.cpp | 4 ++--
     3 files changed, 8 insertions(+), 3 deletions(-)
    
    (limited to 'src')
    
    diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri
    index 13b43ad8f7..fe81689932 100644
    --- a/src/corelib/io/io.pri
    +++ b/src/corelib/io/io.pri
    @@ -172,7 +172,7 @@ win32 {
                     io/qlockfile_unix.cpp \
                     io/qfilesystemiterator_unix.cpp
     
    -        !integrity:!uikit {
    +        !integrity:!uikit:!rtems {
                 SOURCES += io/forkfd_qt.cpp
                 HEADERS += \
                          ../3rdparty/forkfd/forkfd.h
    diff --git a/src/corelib/io/qlockfile_unix.cpp b/src/corelib/io/qlockfile_unix.cpp
    index 4a12157607..b2bf77c0da 100644
    --- a/src/corelib/io/qlockfile_unix.cpp
    +++ b/src/corelib/io/qlockfile_unix.cpp
    @@ -58,6 +58,11 @@
     #include   // flock
     #endif
     
    +#if defined(Q_OS_RTEMS)
    +#  undef LOCK_EX
    +#  undef LOCK_NB
    +#endif
    +
     #include  // kill
     #include     // kill
     #include     // gethostname
    diff --git a/src/corelib/io/qstorageinfo_unix.cpp b/src/corelib/io/qstorageinfo_unix.cpp
    index b7621b5d2f..d25a607d9f 100644
    --- a/src/corelib/io/qstorageinfo_unix.cpp
    +++ b/src/corelib/io/qstorageinfo_unix.cpp
    @@ -812,7 +812,7 @@ void QStorageInfoPrivate::retrieveVolumeInfo()
             valid = true;
             ready = true;
     
    -#if defined(Q_OS_INTEGRITY) || (defined(Q_OS_BSD4) && !defined(Q_OS_NETBSD))
    +#if defined(Q_OS_INTEGRITY) || (defined(Q_OS_BSD4) && !defined(Q_OS_NETBSD)) || defined(Q_OS_RTEMS)
             bytesTotal = statfs_buf.f_blocks * statfs_buf.f_bsize;
             bytesFree = statfs_buf.f_bfree * statfs_buf.f_bsize;
             bytesAvailable = statfs_buf.f_bavail * statfs_buf.f_bsize;
    @@ -822,7 +822,7 @@ void QStorageInfoPrivate::retrieveVolumeInfo()
             bytesAvailable = statfs_buf.f_bavail * statfs_buf.f_frsize;
     #endif
             blockSize = statfs_buf.f_bsize;
    -#if defined(Q_OS_ANDROID) || defined(Q_OS_BSD4) || defined(Q_OS_INTEGRITY)
    +#if defined(Q_OS_ANDROID) || defined(Q_OS_BSD4) || defined(Q_OS_INTEGRITY) || defined(Q_OS_RTEMS)
     #if defined(_STATFS_F_FLAGS)
             readOnly = (statfs_buf.f_flags & ST_RDONLY) != 0;
     #endif
    -- 
    cgit v1.2.3
    
    
    From 3e75c2965c96fa014ab74121e84d623fd04a27f7 Mon Sep 17 00:00:00 2001
    From: Giuseppe D'Angelo 
    Date: Mon, 10 Jun 2019 00:09:10 +0200
    Subject: Remove QLatin1Literal usages
    
    That's an undocumented Qt 4/3/2 remnant, start remove usages.
    
    Fix incorrect include header in qclass_lib_map.h as a drive-by.
    
    Change-Id: I939be2621bc03e5c75f7e3f152546d3af6d37b91
    Reviewed-by: Marc Mutz 
    Reviewed-by: Thiago Macieira 
    ---
     src/gui/painting/qbrush.cpp                        | 16 +++++++--------
     src/plugins/platforms/ios/qioscontext.mm           |  2 +-
     .../xcb/nativepainting/qpaintengine_x11.cpp        |  2 +-
     src/testlib/qtaptestlogger.cpp                     | 24 +++++++++++-----------
     src/tools/uic/qclass_lib_map.h                     |  2 +-
     5 files changed, 23 insertions(+), 23 deletions(-)
    
    (limited to 'src')
    
    diff --git a/src/gui/painting/qbrush.cpp b/src/gui/painting/qbrush.cpp
    index 13d986073e..21e41979af 100644
    --- a/src/gui/painting/qbrush.cpp
    +++ b/src/gui/painting/qbrush.cpp
    @@ -1385,16 +1385,16 @@ QGradient::QGradient(Preset preset)
             setCoordinateMode(ObjectMode);
             setSpread(PadSpread);
     
    -        const QJsonValue start = presetData[QLatin1Literal("start")];
    -        const QJsonValue end = presetData[QLatin1Literal("end")];
    -        m_data.linear.x1 = start[QLatin1Literal("x")].toDouble();
    -        m_data.linear.y1 = start[QLatin1Literal("y")].toDouble();
    -        m_data.linear.x2 = end[QLatin1Literal("x")].toDouble();
    -        m_data.linear.y2 = end[QLatin1Literal("y")].toDouble();
    +        const QJsonValue start = presetData[QLatin1String("start")];
    +        const QJsonValue end = presetData[QLatin1String("end")];
    +        m_data.linear.x1 = start[QLatin1String("x")].toDouble();
    +        m_data.linear.y1 = start[QLatin1String("y")].toDouble();
    +        m_data.linear.x2 = end[QLatin1String("x")].toDouble();
    +        m_data.linear.y2 = end[QLatin1String("y")].toDouble();
     
             for (const QJsonValue &stop : presetData[QLatin1String("stops")].toArray()) {
    -            setColorAt(stop[QLatin1Literal("position")].toDouble(),
    -                QColor(QRgb(stop[QLatin1Literal("color")].toInt())));
    +            setColorAt(stop[QLatin1String("position")].toDouble(),
    +                QColor(QRgb(stop[QLatin1String("color")].toInt())));
             }
     
             cachedPresets.insert(preset, *this);
    diff --git a/src/plugins/platforms/ios/qioscontext.mm b/src/plugins/platforms/ios/qioscontext.mm
    index 535e7d7aa6..c9509ae599 100644
    --- a/src/plugins/platforms/ios/qioscontext.mm
    +++ b/src/plugins/platforms/ios/qioscontext.mm
    @@ -118,7 +118,7 @@ QSurfaceFormat QIOSContext::format() const
         return m_format;
     }
     
    -#define QT_IOS_GL_STATUS_CASE(val) case val: return QLatin1Literal(#val)
    +#define QT_IOS_GL_STATUS_CASE(val) case val: return QLatin1String(#val)
     
     static QString fboStatusString(GLenum status)
     {
    diff --git a/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11.cpp b/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11.cpp
    index 8d958aae94..82b6d60bcd 100644
    --- a/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11.cpp
    +++ b/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11.cpp
    @@ -455,7 +455,7 @@ static const uchar base_dither_matrix[DITHER_SIZE][DITHER_SIZE] = {
     static QPixmap qt_patternForAlpha(uchar alpha, int screen)
     {
         QPixmap pm;
    -    QString key = QLatin1Literal("$qt-alpha-brush$")
    +    QString key = QLatin1String("$qt-alpha-brush$")
                       % HexString(alpha)
                       % HexString(screen);
     
    diff --git a/src/testlib/qtaptestlogger.cpp b/src/testlib/qtaptestlogger.cpp
    index 540b36e273..476761e602 100644
    --- a/src/testlib/qtaptestlogger.cpp
    +++ b/src/testlib/qtaptestlogger.cpp
    @@ -154,10 +154,10 @@ void QTapTestLogger::addIncident(IncidentTypes type, const char *description,
                 // This is fragile, but unfortunately testlib doesn't plumb
                 // the expected and actual values to the loggers (yet).
                 static QRegularExpression verifyRegex(
    -                QLatin1Literal("^'(?.*)' returned (?\\w+).+\\((?.*)\\)$"));
    +                QLatin1String("^'(?.*)' returned (?\\w+).+\\((?.*)\\)$"));
     
                 static QRegularExpression comparRegex(
    -                QLatin1Literal("^(?.*)\n"
    +                QLatin1String("^(?.*)\n"
                         "\\s*Actual\\s+\\((?.*)\\)\\s*: (?.*)\n"
                         "\\s*Expected\\s+\\((?.*)\\)\\s*: (?.*)$"));
     
    @@ -168,22 +168,22 @@ void QTapTestLogger::addIncident(IncidentTypes type, const char *description,
     
                 if (match.hasMatch()) {
                     bool isVerify = match.regularExpression() == verifyRegex;
    -                QString message = match.captured(QLatin1Literal("message"));
    +                QString message = match.captured(QLatin1String("message"));
                     QString expected;
                     QString actual;
     
                     if (isVerify) {
    -                    QString expression = QLatin1Literal(" (")
    -                        % match.captured(QLatin1Literal("actualexpression")) % QLatin1Char(')') ;
    -                    actual = match.captured(QLatin1Literal("actual")).toLower() % expression;
    -                    expected = (actual.startsWith(QLatin1Literal("true")) ? QLatin1Literal("false") : QLatin1Literal("true")) % expression;
    +                    QString expression = QLatin1String(" (")
    +                        % match.captured(QLatin1String("actualexpression")) % QLatin1Char(')') ;
    +                    actual = match.captured(QLatin1String("actual")).toLower() % expression;
    +                    expected = (actual.startsWith(QLatin1String("true")) ? QLatin1String("false") : QLatin1String("true")) % expression;
                         if (message.isEmpty())
    -                        message = QLatin1Literal("Verification failed");
    +                        message = QLatin1String("Verification failed");
                     } else {
    -                    expected = match.captured(QLatin1Literal("expected"))
    -                        % QLatin1Literal(" (") % match.captured(QLatin1Literal("expectedexpresssion")) % QLatin1Char(')');
    -                    actual = match.captured(QLatin1Literal("actual"))
    -                        % QLatin1Literal(" (") % match.captured(QLatin1Literal("actualexpression")) % QLatin1Char(')');
    +                    expected = match.captured(QLatin1String("expected"))
    +                        % QLatin1String(" (") % match.captured(QLatin1String("expectedexpresssion")) % QLatin1Char(')');
    +                    actual = match.captured(QLatin1String("actual"))
    +                        % QLatin1String(" (") % match.captured(QLatin1String("actualexpression")) % QLatin1Char(')');
                     }
     
                     QTestCharBuffer diagnosticsYamlish;
    diff --git a/src/tools/uic/qclass_lib_map.h b/src/tools/uic/qclass_lib_map.h
    index 8e1afa0878..8cebe65a00 100644
    --- a/src/tools/uic/qclass_lib_map.h
    +++ b/src/tools/uic/qclass_lib_map.h
    @@ -249,7 +249,7 @@ QT_CLASS_LIB(QLatin1String, QtCore, qstring.h)
     QT_CLASS_LIB(QCharRef, QtCore, qstring.h)
     QT_CLASS_LIB(QConstString, QtCore, qstring.h)
     QT_CLASS_LIB(QStringRef, QtCore, qstring.h)
    -QT_CLASS_LIB(QLatin1Literal, QtCore, qstringbuilder.h)
    +QT_CLASS_LIB(QLatin1Literal, QtCore, qstring.h)
     QT_CLASS_LIB(QAbstractConcatenable, QtCore, qstringbuilder.h)
     QT_CLASS_LIB(QConcatenable, QtCore, qstringbuilder.h)
     QT_CLASS_LIB(QStringBuilder, QtCore, qstringbuilder.h)
    -- 
    cgit v1.2.3