summaryrefslogtreecommitdiffstats
path: root/src/corelib/tools
diff options
context:
space:
mode:
authorQt by Nokia <qt-info@nokia.com>2011-04-27 12:05:43 +0200
committeraxis <qt-info@nokia.com>2011-04-27 12:05:43 +0200
commit38be0d13830efd2d98281c645c3a60afe05ffece (patch)
tree6ea73f3ec77f7d153333779883e8120f82820abe /src/corelib/tools
Initial import from the monolithic Qt.
This is the beginning of revision history for this module. If you want to look at revision history older than this, please refer to the Qt Git wiki for how to use Git history grafting. At the time of writing, this wiki is located here: http://qt.gitorious.org/qt/pages/GitIntroductionWithQt If you have already performed the grafting and you don't see any history beyond this commit, try running "git log" with the "--follow" argument. Branched from the monolithic repo, Qt master branch, at commit 896db169ea224deb96c59ce8af800d019de63f12
Diffstat (limited to 'src/corelib/tools')
-rw-r--r--src/corelib/tools/qalgorithms.h526
-rw-r--r--src/corelib/tools/qalgorithms.qdoc637
-rw-r--r--src/corelib/tools/qbitarray.cpp738
-rw-r--r--src/corelib/tools/qbitarray.h180
-rw-r--r--src/corelib/tools/qbytearray.cpp4394
-rw-r--r--src/corelib/tools/qbytearray.h622
-rw-r--r--src/corelib/tools/qbytearraymatcher.cpp324
-rw-r--r--src/corelib/tools/qbytearraymatcher.h103
-rw-r--r--src/corelib/tools/qbytedata_p.h220
-rw-r--r--src/corelib/tools/qcache.h217
-rw-r--r--src/corelib/tools/qcache.qdoc230
-rw-r--r--src/corelib/tools/qchar.cpp1654
-rw-r--r--src/corelib/tools/qchar.h404
-rw-r--r--src/corelib/tools/qcontainerfwd.h71
-rw-r--r--src/corelib/tools/qcontiguouscache.cpp474
-rw-r--r--src/corelib/tools/qcontiguouscache.h466
-rw-r--r--src/corelib/tools/qcryptographichash.cpp200
-rw-r--r--src/corelib/tools/qcryptographichash.h84
-rw-r--r--src/corelib/tools/qdatetime.cpp5881
-rw-r--r--src/corelib/tools/qdatetime.h340
-rw-r--r--src/corelib/tools/qdatetime_p.h289
-rw-r--r--src/corelib/tools/qeasingcurve.cpp937
-rw-r--r--src/corelib/tools/qeasingcurve.h125
-rw-r--r--src/corelib/tools/qelapsedtimer.cpp264
-rw-r--r--src/corelib/tools/qelapsedtimer.h95
-rw-r--r--src/corelib/tools/qelapsedtimer_generic.cpp194
-rw-r--r--src/corelib/tools/qelapsedtimer_mac.cpp132
-rw-r--r--src/corelib/tools/qelapsedtimer_symbian.cpp131
-rw-r--r--src/corelib/tools/qelapsedtimer_unix.cpp209
-rw-r--r--src/corelib/tools/qelapsedtimer_win.cpp183
-rw-r--r--src/corelib/tools/qharfbuzz.cpp140
-rw-r--r--src/corelib/tools/qharfbuzz_p.h77
-rw-r--r--src/corelib/tools/qhash.cpp1914
-rw-r--r--src/corelib/tools/qhash.h1043
-rw-r--r--src/corelib/tools/qiterator.h202
-rw-r--r--src/corelib/tools/qiterator.qdoc1417
-rw-r--r--src/corelib/tools/qline.cpp867
-rw-r--r--src/corelib/tools/qline.h424
-rw-r--r--src/corelib/tools/qlinkedlist.cpp1170
-rw-r--r--src/corelib/tools/qlinkedlist.h525
-rw-r--r--src/corelib/tools/qlist.cpp1919
-rw-r--r--src/corelib/tools/qlist.h900
-rw-r--r--src/corelib/tools/qlocale.cpp3281
-rw-r--r--src/corelib/tools/qlocale.h818
-rw-r--r--src/corelib/tools/qlocale.qdoc905
-rw-r--r--src/corelib/tools/qlocale_data_p.h6518
-rw-r--r--src/corelib/tools/qlocale_icu.cpp224
-rw-r--r--src/corelib/tools/qlocale_mac.mm463
-rw-r--r--src/corelib/tools/qlocale_p.h283
-rw-r--r--src/corelib/tools/qlocale_symbian.cpp929
-rw-r--r--src/corelib/tools/qlocale_tools.cpp2961
-rw-r--r--src/corelib/tools/qlocale_tools_p.h122
-rw-r--r--src/corelib/tools/qlocale_unix.cpp226
-rw-r--r--src/corelib/tools/qlocale_win.cpp988
-rw-r--r--src/corelib/tools/qmap.cpp1646
-rw-r--r--src/corelib/tools/qmap.h1090
-rw-r--r--src/corelib/tools/qmargins.cpp167
-rw-r--r--src/corelib/tools/qmargins.h147
-rw-r--r--src/corelib/tools/qpair.h127
-rw-r--r--src/corelib/tools/qpair.qdoc215
-rw-r--r--src/corelib/tools/qpodlist_p.h115
-rw-r--r--src/corelib/tools/qpoint.cpp741
-rw-r--r--src/corelib/tools/qpoint.h389
-rw-r--r--src/corelib/tools/qqueue.cpp137
-rw-r--r--src/corelib/tools/qqueue.h70
-rw-r--r--src/corelib/tools/qrect.cpp2465
-rw-r--r--src/corelib/tools/qrect.h858
-rw-r--r--src/corelib/tools/qregexp.cpp4503
-rw-r--r--src/corelib/tools/qregexp.h169
-rw-r--r--src/corelib/tools/qringbuffer_p.h451
-rw-r--r--src/corelib/tools/qscopedpointer.cpp283
-rw-r--r--src/corelib/tools/qscopedpointer.h245
-rw-r--r--src/corelib/tools/qscopedpointer_p.h151
-rw-r--r--src/corelib/tools/qscopedvaluerollback.cpp84
-rw-r--r--src/corelib/tools/qscopedvaluerollback.h81
-rw-r--r--src/corelib/tools/qset.h371
-rw-r--r--src/corelib/tools/qset.qdoc946
-rw-r--r--src/corelib/tools/qshareddata.cpp568
-rw-r--r--src/corelib/tools/qshareddata.h286
-rw-r--r--src/corelib/tools/qsharedpointer.cpp1501
-rw-r--r--src/corelib/tools/qsharedpointer.h152
-rw-r--r--src/corelib/tools/qsharedpointer_impl.h898
-rw-r--r--src/corelib/tools/qsimd.cpp413
-rw-r--r--src/corelib/tools/qsimd_p.h172
-rw-r--r--src/corelib/tools/qsize.cpp828
-rw-r--r--src/corelib/tools/qsize.h368
-rw-r--r--src/corelib/tools/qstack.cpp137
-rw-r--r--src/corelib/tools/qstack.h83
-rw-r--r--src/corelib/tools/qstring.cpp9129
-rw-r--r--src/corelib/tools/qstring.h1295
-rw-r--r--src/corelib/tools/qstringbuilder.cpp193
-rw-r--r--src/corelib/tools/qstringbuilder.h455
-rw-r--r--src/corelib/tools/qstringlist.cpp692
-rw-r--r--src/corelib/tools/qstringlist.h262
-rw-r--r--src/corelib/tools/qstringmatcher.cpp322
-rw-r--r--src/corelib/tools/qstringmatcher.h103
-rw-r--r--src/corelib/tools/qtextboundaryfinder.cpp479
-rw-r--r--src/corelib/tools/qtextboundaryfinder.h114
-rw-r--r--src/corelib/tools/qtimeline.cpp787
-rw-r--r--src/corelib/tools/qtimeline.h147
-rw-r--r--src/corelib/tools/qtools_p.h65
-rw-r--r--src/corelib/tools/qunicodetables.cpp9486
-rw-r--r--src/corelib/tools/qunicodetables_p.h232
-rw-r--r--src/corelib/tools/qvarlengtharray.h404
-rw-r--r--src/corelib/tools/qvarlengtharray.qdoc547
-rw-r--r--src/corelib/tools/qvector.cpp1017
-rw-r--r--src/corelib/tools/qvector.h829
-rw-r--r--src/corelib/tools/qvsnprintf.cpp133
-rw-r--r--src/corelib/tools/tools.pri124
109 files changed, 96312 insertions, 0 deletions
diff --git a/src/corelib/tools/qalgorithms.h b/src/corelib/tools/qalgorithms.h
new file mode 100644
index 0000000000..6b870397b6
--- /dev/null
+++ b/src/corelib/tools/qalgorithms.h
@@ -0,0 +1,526 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QALGORITHMS_H
+#define QALGORITHMS_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+/*
+ Warning: The contents of QAlgorithmsPrivate is not a part of the public Qt API
+ and may be changed from version to version or even be completely removed.
+*/
+namespace QAlgorithmsPrivate {
+
+template <typename RandomAccessIterator, typename T, typename LessThan>
+Q_OUTOFLINE_TEMPLATE void qSortHelper(RandomAccessIterator start, RandomAccessIterator end, const T &t, LessThan lessThan);
+template <typename RandomAccessIterator, typename T>
+inline void qSortHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &dummy);
+
+template <typename RandomAccessIterator, typename T, typename LessThan>
+Q_OUTOFLINE_TEMPLATE void qStableSortHelper(RandomAccessIterator start, RandomAccessIterator end, const T &t, LessThan lessThan);
+template <typename RandomAccessIterator, typename T>
+inline void qStableSortHelper(RandomAccessIterator, RandomAccessIterator, const T &);
+
+template <typename RandomAccessIterator, typename T, typename LessThan>
+Q_OUTOFLINE_TEMPLATE RandomAccessIterator qLowerBoundHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan);
+template <typename RandomAccessIterator, typename T, typename LessThan>
+Q_OUTOFLINE_TEMPLATE RandomAccessIterator qUpperBoundHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan);
+template <typename RandomAccessIterator, typename T, typename LessThan>
+Q_OUTOFLINE_TEMPLATE RandomAccessIterator qBinaryFindHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan);
+
+}
+
+template <typename InputIterator, typename OutputIterator>
+inline OutputIterator qCopy(InputIterator begin, InputIterator end, OutputIterator dest)
+{
+ while (begin != end)
+ *dest++ = *begin++;
+ return dest;
+}
+
+template <typename BiIterator1, typename BiIterator2>
+inline BiIterator2 qCopyBackward(BiIterator1 begin, BiIterator1 end, BiIterator2 dest)
+{
+ while (begin != end)
+ *--dest = *--end;
+ return dest;
+}
+
+template <typename InputIterator1, typename InputIterator2>
+inline bool qEqual(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2)
+{
+ for (; first1 != last1; ++first1, ++first2)
+ if (!(*first1 == *first2))
+ return false;
+ return true;
+}
+
+template <typename ForwardIterator, typename T>
+inline void qFill(ForwardIterator first, ForwardIterator last, const T &val)
+{
+ for (; first != last; ++first)
+ *first = val;
+}
+
+template <typename Container, typename T>
+inline void qFill(Container &container, const T &val)
+{
+ qFill(container.begin(), container.end(), val);
+}
+
+template <typename InputIterator, typename T>
+inline InputIterator qFind(InputIterator first, InputIterator last, const T &val)
+{
+ while (first != last && !(*first == val))
+ ++first;
+ return first;
+}
+
+template <typename Container, typename T>
+inline typename Container::const_iterator qFind(const Container &container, const T &val)
+{
+ return qFind(container.constBegin(), container.constEnd(), val);
+}
+
+template <typename InputIterator, typename T, typename Size>
+inline void qCount(InputIterator first, InputIterator last, const T &value, Size &n)
+{
+ for (; first != last; ++first)
+ if (*first == value)
+ ++n;
+}
+
+template <typename Container, typename T, typename Size>
+inline void qCount(const Container &container, const T &value, Size &n)
+{
+ qCount(container.constBegin(), container.constEnd(), value, n);
+}
+
+#ifdef qdoc
+template <typename T>
+LessThan qLess()
+{
+}
+
+template <typename T>
+LessThan qGreater()
+{
+}
+#else
+template <typename T>
+class qLess
+{
+public:
+ inline bool operator()(const T &t1, const T &t2) const
+ {
+ return (t1 < t2);
+ }
+};
+
+template <typename T>
+class qGreater
+{
+public:
+ inline bool operator()(const T &t1, const T &t2) const
+ {
+ return (t2 < t1);
+ }
+};
+#endif
+
+template <typename RandomAccessIterator>
+inline void qSort(RandomAccessIterator start, RandomAccessIterator end)
+{
+ if (start != end)
+ QAlgorithmsPrivate::qSortHelper(start, end, *start);
+}
+
+template <typename RandomAccessIterator, typename LessThan>
+inline void qSort(RandomAccessIterator start, RandomAccessIterator end, LessThan lessThan)
+{
+ if (start != end)
+ QAlgorithmsPrivate::qSortHelper(start, end, *start, lessThan);
+}
+
+template<typename Container>
+inline void qSort(Container &c)
+{
+#ifdef Q_CC_BOR
+ // Work around Borland 5.5 optimizer bug
+ c.detach();
+#endif
+ if (!c.empty())
+ QAlgorithmsPrivate::qSortHelper(c.begin(), c.end(), *c.begin());
+}
+
+template <typename RandomAccessIterator>
+inline void qStableSort(RandomAccessIterator start, RandomAccessIterator end)
+{
+ if (start != end)
+ QAlgorithmsPrivate::qStableSortHelper(start, end, *start);
+}
+
+template <typename RandomAccessIterator, typename LessThan>
+inline void qStableSort(RandomAccessIterator start, RandomAccessIterator end, LessThan lessThan)
+{
+ if (start != end)
+ QAlgorithmsPrivate::qStableSortHelper(start, end, *start, lessThan);
+}
+
+template<typename Container>
+inline void qStableSort(Container &c)
+{
+#ifdef Q_CC_BOR
+ // Work around Borland 5.5 optimizer bug
+ c.detach();
+#endif
+ if (!c.empty())
+ QAlgorithmsPrivate::qStableSortHelper(c.begin(), c.end(), *c.begin());
+}
+
+template <typename RandomAccessIterator, typename T>
+Q_OUTOFLINE_TEMPLATE RandomAccessIterator qLowerBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value)
+{
+ // Implementation is duplicated from QAlgorithmsPrivate to keep existing code
+ // compiling. We have to allow using *begin and value with different types,
+ // and then implementing operator< for those types.
+ RandomAccessIterator middle;
+ int n = end - begin;
+ int half;
+
+ while (n > 0) {
+ half = n >> 1;
+ middle = begin + half;
+ if (*middle < value) {
+ begin = middle + 1;
+ n -= half + 1;
+ } else {
+ n = half;
+ }
+ }
+ return begin;
+}
+
+template <typename RandomAccessIterator, typename T, typename LessThan>
+Q_OUTOFLINE_TEMPLATE RandomAccessIterator qLowerBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan)
+{
+ return QAlgorithmsPrivate::qLowerBoundHelper(begin, end, value, lessThan);
+}
+
+template <typename Container, typename T>
+Q_OUTOFLINE_TEMPLATE typename Container::const_iterator qLowerBound(const Container &container, const T &value)
+{
+ return QAlgorithmsPrivate::qLowerBoundHelper(container.constBegin(), container.constEnd(), value, qLess<T>());
+}
+
+template <typename RandomAccessIterator, typename T>
+Q_OUTOFLINE_TEMPLATE RandomAccessIterator qUpperBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value)
+{
+ // Implementation is duplicated from QAlgorithmsPrivate.
+ RandomAccessIterator middle;
+ int n = end - begin;
+ int half;
+
+ while (n > 0) {
+ half = n >> 1;
+ middle = begin + half;
+ if (value < *middle) {
+ n = half;
+ } else {
+ begin = middle + 1;
+ n -= half + 1;
+ }
+ }
+ return begin;
+}
+
+template <typename RandomAccessIterator, typename T, typename LessThan>
+Q_OUTOFLINE_TEMPLATE RandomAccessIterator qUpperBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan)
+{
+ return QAlgorithmsPrivate::qUpperBoundHelper(begin, end, value, lessThan);
+}
+
+template <typename Container, typename T>
+Q_OUTOFLINE_TEMPLATE typename Container::const_iterator qUpperBound(const Container &container, const T &value)
+{
+ return QAlgorithmsPrivate::qUpperBoundHelper(container.constBegin(), container.constEnd(), value, qLess<T>());
+}
+
+template <typename RandomAccessIterator, typename T>
+Q_OUTOFLINE_TEMPLATE RandomAccessIterator qBinaryFind(RandomAccessIterator begin, RandomAccessIterator end, const T &value)
+{
+ // Implementation is duplicated from QAlgorithmsPrivate.
+ RandomAccessIterator it = qLowerBound(begin, end, value);
+
+ if (it == end || value < *it)
+ return end;
+
+ return it;
+}
+
+template <typename RandomAccessIterator, typename T, typename LessThan>
+Q_OUTOFLINE_TEMPLATE RandomAccessIterator qBinaryFind(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan)
+{
+ return QAlgorithmsPrivate::qBinaryFindHelper(begin, end, value, lessThan);
+}
+
+template <typename Container, typename T>
+Q_OUTOFLINE_TEMPLATE typename Container::const_iterator qBinaryFind(const Container &container, const T &value)
+{
+ return QAlgorithmsPrivate::qBinaryFindHelper(container.constBegin(), container.constEnd(), value, qLess<T>());
+}
+
+template <typename ForwardIterator>
+Q_OUTOFLINE_TEMPLATE void qDeleteAll(ForwardIterator begin, ForwardIterator end)
+{
+ while (begin != end) {
+ delete *begin;
+ ++begin;
+ }
+}
+
+template <typename Container>
+inline void qDeleteAll(const Container &c)
+{
+ qDeleteAll(c.begin(), c.end());
+}
+
+/*
+ Warning: The contents of QAlgorithmsPrivate is not a part of the public Qt API
+ and may be changed from version to version or even be completely removed.
+*/
+namespace QAlgorithmsPrivate {
+
+template <typename RandomAccessIterator, typename T, typename LessThan>
+Q_OUTOFLINE_TEMPLATE void qSortHelper(RandomAccessIterator start, RandomAccessIterator end, const T &t, LessThan lessThan)
+{
+top:
+ int span = int(end - start);
+ if (span < 2)
+ return;
+
+ --end;
+ RandomAccessIterator low = start, high = end - 1;
+ RandomAccessIterator pivot = start + span / 2;
+
+ if (lessThan(*end, *start))
+ qSwap(*end, *start);
+ if (span == 2)
+ return;
+
+ if (lessThan(*pivot, *start))
+ qSwap(*pivot, *start);
+ if (lessThan(*end, *pivot))
+ qSwap(*end, *pivot);
+ if (span == 3)
+ return;
+
+ qSwap(*pivot, *end);
+
+ while (low < high) {
+ while (low < high && lessThan(*low, *end))
+ ++low;
+
+ while (high > low && lessThan(*end, *high))
+ --high;
+
+ if (low < high) {
+ qSwap(*low, *high);
+ ++low;
+ --high;
+ } else {
+ break;
+ }
+ }
+
+ if (lessThan(*low, *end))
+ ++low;
+
+ qSwap(*end, *low);
+ qSortHelper(start, low, t, lessThan);
+
+ start = low + 1;
+ ++end;
+ goto top;
+}
+
+template <typename RandomAccessIterator, typename T>
+inline void qSortHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &dummy)
+{
+ qSortHelper(begin, end, dummy, qLess<T>());
+}
+
+template <typename RandomAccessIterator>
+Q_OUTOFLINE_TEMPLATE void qReverse(RandomAccessIterator begin, RandomAccessIterator end)
+{
+ --end;
+ while (begin < end)
+ qSwap(*begin++, *end--);
+}
+
+template <typename RandomAccessIterator>
+Q_OUTOFLINE_TEMPLATE void qRotate(RandomAccessIterator begin, RandomAccessIterator middle, RandomAccessIterator end)
+{
+ qReverse(begin, middle);
+ qReverse(middle, end);
+ qReverse(begin, end);
+}
+
+template <typename RandomAccessIterator, typename T, typename LessThan>
+Q_OUTOFLINE_TEMPLATE void qMerge(RandomAccessIterator begin, RandomAccessIterator pivot, RandomAccessIterator end, T &t, LessThan lessThan)
+{
+ const int len1 = pivot - begin;
+ const int len2 = end - pivot;
+
+ if (len1 == 0 || len2 == 0)
+ return;
+
+ if (len1 + len2 == 2) {
+ if (lessThan(*(begin + 1), *(begin)))
+ qSwap(*begin, *(begin + 1));
+ return;
+ }
+
+ RandomAccessIterator firstCut;
+ RandomAccessIterator secondCut;
+ int len2Half;
+ if (len1 > len2) {
+ const int len1Half = len1 / 2;
+ firstCut = begin + len1Half;
+ secondCut = qLowerBound(pivot, end, *firstCut, lessThan);
+ len2Half = secondCut - pivot;
+ } else {
+ len2Half = len2 / 2;
+ secondCut = pivot + len2Half;
+ firstCut = qUpperBound(begin, pivot, *secondCut, lessThan);
+ }
+
+ qRotate(firstCut, pivot, secondCut);
+ const RandomAccessIterator newPivot = firstCut + len2Half;
+ qMerge(begin, firstCut, newPivot, t, lessThan);
+ qMerge(newPivot, secondCut, end, t, lessThan);
+}
+
+template <typename RandomAccessIterator, typename T, typename LessThan>
+Q_OUTOFLINE_TEMPLATE void qStableSortHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &t, LessThan lessThan)
+{
+ const int span = end - begin;
+ if (span < 2)
+ return;
+
+ const RandomAccessIterator middle = begin + span / 2;
+ qStableSortHelper(begin, middle, t, lessThan);
+ qStableSortHelper(middle, end, t, lessThan);
+ qMerge(begin, middle, end, t, lessThan);
+}
+
+template <typename RandomAccessIterator, typename T>
+inline void qStableSortHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &dummy)
+{
+ qStableSortHelper(begin, end, dummy, qLess<T>());
+}
+
+template <typename RandomAccessIterator, typename T, typename LessThan>
+Q_OUTOFLINE_TEMPLATE RandomAccessIterator qLowerBoundHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan)
+{
+ RandomAccessIterator middle;
+ int n = int(end - begin);
+ int half;
+
+ while (n > 0) {
+ half = n >> 1;
+ middle = begin + half;
+ if (lessThan(*middle, value)) {
+ begin = middle + 1;
+ n -= half + 1;
+ } else {
+ n = half;
+ }
+ }
+ return begin;
+}
+
+
+template <typename RandomAccessIterator, typename T, typename LessThan>
+Q_OUTOFLINE_TEMPLATE RandomAccessIterator qUpperBoundHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan)
+{
+ RandomAccessIterator middle;
+ int n = end - begin;
+ int half;
+
+ while (n > 0) {
+ half = n >> 1;
+ middle = begin + half;
+ if (lessThan(value, *middle)) {
+ n = half;
+ } else {
+ begin = middle + 1;
+ n -= half + 1;
+ }
+ }
+ return begin;
+}
+
+template <typename RandomAccessIterator, typename T, typename LessThan>
+Q_OUTOFLINE_TEMPLATE RandomAccessIterator qBinaryFindHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan)
+{
+ RandomAccessIterator it = qLowerBoundHelper(begin, end, value, lessThan);
+
+ if (it == end || lessThan(value, *it))
+ return end;
+
+ return it;
+}
+
+} //namespace QAlgorithmsPrivate
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QALGORITHMS_H
diff --git a/src/corelib/tools/qalgorithms.qdoc b/src/corelib/tools/qalgorithms.qdoc
new file mode 100644
index 0000000000..a9b7ddca7a
--- /dev/null
+++ b/src/corelib/tools/qalgorithms.qdoc
@@ -0,0 +1,637 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Free Documentation License
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of this
+** file.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \headerfile <QtAlgorithms>
+ \title Generic Algorithms
+ \ingroup funclists
+
+ \brief The <QtAlgorithms> header includes the generic, template-based algorithms.
+
+ Qt provides a number of global template functions in \c
+ <QtAlgorithms> that work on containers and perform well-know
+ algorithms. You can use these algorithms with any \l {container
+ class} that provides STL-style iterators, including Qt's QList,
+ QLinkedList, QVector, QMap, and QHash classes.
+
+ These functions have taken their inspiration from similar
+ functions available in the STL \c <algorithm> header. Most of them
+ have a direct STL equivalent; for example, qCopyBackward() is the
+ same as STL's copy_backward() algorithm.
+
+ If STL is available on all your target platforms, you can use the
+ STL algorithms instead of their Qt counterparts. One reason why
+ you might want to use the STL algorithms is that STL provides
+ dozens and dozens of algorithms, whereas Qt only provides the most
+ important ones, making no attempt to duplicate functionality that
+ is already provided by the C++ standard.
+
+ Most algorithms take \l {STL-style iterators} as parameters. The
+ algorithms are generic in the sense that they aren't bound to a
+ specific iterator class; you can use them with any iterators that
+ meet a certain set of requirements.
+
+ Let's take the qFill() algorithm as an example. Unlike QVector,
+ QList has no fill() function that can be used to fill a list with
+ a particular value. If you need that functionality, you can use
+ qFill():
+
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.cpp 0
+
+ qFill() takes a begin iterator, an end iterator, and a value.
+ In the example above, we pass \c list.begin() and \c list.end()
+ as the begin and end iterators, but this doesn't have to be
+ the case:
+
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.cpp 1
+
+ Different algorithms can have different requirements for the
+ iterators they accept. For example, qFill() accepts two
+ \l {forward iterators}. The iterator types required are specified
+ for each algorithm. If an iterator of the wrong type is passed (for
+ example, if QList::ConstIterator is passed as an \l {output
+ iterator}), you will always get a compiler error, although not
+ necessarily a very informative one.
+
+ Some algorithms have special requirements on the value type
+ stored in the containers. For example, qEqual() requires that the
+ value type supports operator==(), which it uses to compare items.
+ Similarly, qDeleteAll() requires that the value type is a
+ non-const pointer type (for example, QWidget *). The value type
+ requirements are specified for each algorithm, and the compiler
+ will produce an error if a requirement isn't met.
+
+ \target binaryFind example
+
+ The generic algorithms can be used on other container classes
+ than those provided by Qt and STL. The syntax of STL-style
+ iterators is modeled after C++ pointers, so it's possible to use
+ plain arrays as containers and plain pointers as iterators. A
+ common idiom is to use qBinaryFind() together with two static
+ arrays: one that contains a list of keys, and another that
+ contains a list of associated values. For example, the following
+ code will look up an HTML entity (e.g., \c &amp;) in the \c
+ name_table array and return the corresponding Unicode value from
+ the \c value_table if the entity is recognized:
+
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.cpp 2
+
+ This kind of code is for advanced users only; for most
+ applications, a QMap- or QHash-based approach would work just as
+ well:
+
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.cpp 3
+
+ \section1 Types of Iterators
+
+ The algorithms have certain requirements on the iterator types
+ they accept, and these are specified individually for each
+ function. The compiler will produce an error if a requirement
+ isn't met.
+
+ \section2 Input Iterators
+
+ An \e{input iterator} is an iterator that can be used for reading
+ data sequentially from a container. It must provide the following
+ operators: \c{==} and \c{!=} for comparing two iterators, unary
+ \c{*} for retrieving the value stored in the item, and prefix
+ \c{++} for advancing to the next item.
+
+ The Qt containers' iterator types (const and non-const) are all
+ input iterators.
+
+ \section2 Output Iterators
+
+ An \e{output iterator} is an iterator that can be used for
+ writing data sequentially to a container or to some output
+ stream. It must provide the following operators: unary \c{*} for
+ writing a value (i.e., \c{*it = val}) and prefix \c{++} for
+ advancing to the next item.
+
+ The Qt containers' non-const iterator types are all output
+ iterators.
+
+ \section2 Forward Iterators
+
+ A \e{forward iterator} is an iterator that meets the requirements
+ of both input iterators and output iterators.
+
+ The Qt containers' non-const iterator types are all forward
+ iterators.
+
+ \section2 Bidirectional Iterators
+
+ A \e{bidirectional iterator} is an iterator that meets the
+ requirements of forward iterators but that in addition supports
+ prefix \c{--} for iterating backward.
+
+ The Qt containers' non-const iterator types are all bidirectional
+ iterators.
+
+ \section2 Random Access Iterators
+
+ The last category, \e{random access iterators}, is the most
+ powerful type of iterator. It supports all the requirements of a
+ bidirectional iterator, and supports the following operations:
+
+ \table
+ \row \i \c{i += n} \i advances iterator \c i by \c n positions
+ \row \i \c{i -= n} \i moves iterator \c i back by \c n positions
+ \row \i \c{i + n} or \c{n + i} \i returns the iterator for the item \c
+ n positions ahead of iterator \c i
+ \row \i \c{i - n} \i returns the iterator for the item \c n positions behind of iterator \c i
+ \row \i \c{i - j} \i returns the number of items between iterators \c i and \c j
+ \row \i \c{i[n]} \i same as \c{*(i + n)}
+ \row \i \c{i < j} \i returns true if iterator \c j comes after iterator \c i
+ \endtable
+
+ QList and QVector's non-const iterator types are random access iterators.
+
+ \sa {container classes}, <QtGlobal>
+*/
+
+/*! \fn OutputIterator qCopy(InputIterator begin1, InputIterator end1, OutputIterator begin2)
+ \relates <QtAlgorithms>
+
+ Copies the items from range [\a begin1, \a end1) to range [\a
+ begin2, ...), in the order in which they appear.
+
+ The item at position \a begin1 is assigned to that at position \a
+ begin2; the item at position \a begin1 + 1 is assigned to that at
+ position \a begin2 + 1; and so on.
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.cpp 4
+
+ \sa qCopyBackward(), {input iterators}, {output iterators}
+*/
+
+/*! \fn BiIterator2 qCopyBackward(BiIterator1 begin1, BiIterator1 end1, BiIterator2 end2)
+ \relates <QtAlgorithms>
+
+ Copies the items from range [\a begin1, \a end1) to range [...,
+ \a end2).
+
+ The item at position \a end1 - 1 is assigned to that at position
+ \a end2 - 1; the item at position \a end1 - 2 is assigned to that
+ at position \a end2 - 2; and so on.
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.cpp 5
+
+ \sa qCopy(), {bidirectional iterators}
+*/
+
+/*! \fn bool qEqual(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2)
+ \relates <QtAlgorithms>
+
+ Compares the items in the range [\a begin1, \a end1) with the
+ items in the range [\a begin2, ...). Returns true if all the
+ items compare equal; otherwise returns false.
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.cpp 6
+
+ This function requires the item type (in the example above,
+ QString) to implement \c operator==().
+
+ \sa {input iterators}
+*/
+
+/*! \fn void qFill(ForwardIterator begin, ForwardIterator end, const T &value)
+ \relates <QtAlgorithms>
+
+ Fills the range [\a begin, \a end) with \a value.
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.cpp 7
+
+ \sa qCopy(), {forward iterators}
+*/
+
+/*! \fn void qFill(Container &container, const T &value)
+ \relates <QtAlgorithms>
+
+ \overload
+
+ This is the same as qFill(\a{container}.begin(), \a{container}.end(), \a value);
+*/
+
+/*! \fn InputIterator qFind(InputIterator begin, InputIterator end, const T &value)
+ \relates <QtAlgorithms>
+
+ Returns an iterator to the first occurrence of \a value in a
+ container in the range [\a begin, \a end). Returns \a end if \a
+ value isn't found.
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.cpp 8
+
+ This function requires the item type (in the example above,
+ QString) to implement \c operator==().
+
+ If the items in the range are in ascending order, you can get
+ faster results by using qLowerBound() or qBinaryFind() instead of
+ qFind().
+
+ \sa qBinaryFind(), {input iterators}
+*/
+
+/*! \fn void qFind(const Container &container, const T &value)
+ \relates <QtAlgorithms>
+
+ \overload
+
+ This is the same as qFind(\a{container}.constBegin(), \a{container}.constEnd(), value);
+*/
+
+/*! \fn void qCount(InputIterator begin, InputIterator end, const T &value, Size &n)
+ \relates <QtAlgorithms>
+
+ Returns the number of occurrences of \a value in the range [\a begin, \a end),
+ which is returned in \a n. \a n is never initialized, the count is added to \a n.
+ It is the caller's responsibility to initialize \a n.
+
+ Example:
+
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.cpp 9
+
+ This function requires the item type (in the example above,
+ \c int) to implement \c operator==().
+
+ \sa {input iterators}
+*/
+
+/*! \fn void qCount(const Container &container, const T &value, Size &n)
+\relates <QtAlgorithms>
+
+\overload
+
+Instead of operating on iterators, as in the other overload, this function
+operates on the specified \a container to obtain the number of instances
+of \a value in the variable passed as a reference in argument \a n.
+*/
+
+/*! \fn void qSwap(T &var1, T &var2)
+ \relates <QtAlgorithms>
+
+ Exchanges the values of variables \a var1 and \a var2.
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.cpp 10
+*/
+
+/*! \fn void qSort(RandomAccessIterator begin, RandomAccessIterator end)
+ \relates <QtAlgorithms>
+
+ Sorts the items in range [\a begin, \a end) in ascending order
+ using the quicksort algorithm.
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.cpp 11
+
+ The sort algorithm is efficient on large data sets. It operates
+ in \l {linear-logarithmic time}, O(\e{n} log \e{n}).
+
+ This function requires the item type (in the example above,
+ \c{int}) to implement \c operator<().
+
+ If neither of the two items is "less than" the other, the items are
+ taken to be equal. It is then undefined which one of the two
+ items will appear before the other after the sort.
+
+ \sa qStableSort(), {random access iterators}
+*/
+
+/*! \fn void qSort(RandomAccessIterator begin, RandomAccessIterator end, LessThan lessThan)
+ \relates <QtAlgorithms>
+
+ \overload
+
+ Uses the \a lessThan function instead of \c operator<() to
+ compare the items.
+
+ For example, here's how to sort the strings in a QStringList
+ in case-insensitive alphabetical order:
+
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.cpp 12
+
+ To sort values in reverse order, pass
+ \l{qGreater()}{qGreater<T>()} as the \a lessThan parameter. For
+ example:
+
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.cpp 13
+
+ If neither of the two items is "less than" the other, the items are
+ taken to be equal. It is then undefined which one of the two
+ items will appear before the other after the sort.
+
+ An alternative to using qSort() is to put the items to sort in a
+ QMap, using the sort key as the QMap key. This is often more
+ convenient than defining a \a lessThan function. For example, the
+ following code shows how to sort a list of strings case
+ insensitively using QMap:
+
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.cpp 14
+
+ \sa QMap
+*/
+
+/*! \fn void qSort(Container &container)
+ \relates <QtAlgorithms>
+
+ \overload
+
+ This is the same as qSort(\a{container}.begin(), \a{container}.end());
+*/
+
+/*!
+ \fn void qStableSort(RandomAccessIterator begin, RandomAccessIterator end)
+ \relates <QtAlgorithms>
+
+ Sorts the items in range [\a begin, \a end) in ascending order
+ using a stable sorting algorithm.
+
+ If neither of the two items is "less than" the other, the items are
+ taken to be equal. The item that appeared before the other in the
+ original container will still appear first after the sort. This
+ property is often useful when sorting user-visible data.
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.cpp 15
+
+ The sort algorithm is efficient on large data sets. It operates
+ in \l {linear-logarithmic time}, O(\e{n} log \e{n}).
+
+ This function requires the item type (in the example above,
+ \c{int}) to implement \c operator<().
+
+ \sa qSort(), {random access iterators}
+*/
+
+/*!
+ \fn void qStableSort(RandomAccessIterator begin, RandomAccessIterator end, LessThan lessThan)
+ \relates <QtAlgorithms>
+
+ \overload
+
+ Uses the \a lessThan function instead of \c operator<() to
+ compare the items.
+
+ For example, here's how to sort the strings in a QStringList
+ in case-insensitive alphabetical order:
+
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.cpp 16
+
+ Note that earlier versions of Qt allowed using a lessThan function that took its
+ arguments by non-const reference. From 4.3 and on this is no longer possible,
+ the arguments has to be passed by const reference or value.
+
+ To sort values in reverse order, pass
+ \l{qGreater()}{qGreater<T>()} as the \a lessThan parameter. For
+ example:
+
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.cpp 17
+
+ If neither of the two items is "less than" the other, the items are
+ taken to be equal. The item that appeared before the other in the
+ original container will still appear first after the sort. This
+ property is often useful when sorting user-visible data.
+*/
+
+/*!
+ \fn void qStableSort(Container &container)
+ \relates <QtAlgorithms>
+
+ \overload
+
+ This is the same as qStableSort(\a{container}.begin(), \a{container}.end());
+*/
+
+/*! \fn RandomAccessIterator qLowerBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value)
+ \relates <QtAlgorithms>
+
+ Performs a binary search of the range [\a begin, \a end) and
+ returns the position of the first ocurrence of \a value. If no
+ such item is found, returns the position where it should be
+ inserted.
+
+ The items in the range [\a begin, \e end) must be sorted in
+ ascending order; see qSort().
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.cpp 18
+
+ This function requires the item type (in the example above,
+ \c{int}) to implement \c operator<().
+
+ qLowerBound() can be used in conjunction with qUpperBound() to
+ iterate over all occurrences of the same value:
+
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.cpp 19
+
+ \sa qUpperBound(), qBinaryFind()
+*/
+
+/*!
+ \fn RandomAccessIterator qLowerBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan)
+ \relates <QtAlgorithms>
+
+ \overload
+
+ Uses the \a lessThan function instead of \c operator<() to
+ compare the items.
+
+ Note that the items in the range must be sorted according to the order
+ specified by the \a lessThan object.
+*/
+
+/*!
+ \fn void qLowerBound(const Container &container, const T &value)
+ \relates <QtAlgorithms>
+
+ \overload
+
+ For read-only iteration over containers, this function is broadly equivalent to
+ qLowerBound(\a{container}.begin(), \a{container}.end(), value). However, since it
+ returns a const iterator, you cannot use it to modify the container; for example,
+ to insert items.
+*/
+
+/*! \fn RandomAccessIterator qUpperBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value)
+ \relates <QtAlgorithms>
+
+ Performs a binary search of the range [\a begin, \a end) and
+ returns the position of the one-past-the-last occurrence of \a
+ value. If no such item is found, returns the position where the
+ item should be inserted.
+
+ The items in the range [\a begin, \e end) must be sorted in
+ ascending order; see qSort().
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.cpp 20
+
+ This function requires the item type (in the example above,
+ \c{int}) to implement \c operator<().
+
+ qUpperBound() can be used in conjunction with qLowerBound() to
+ iterate over all occurrences of the same value:
+
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.cpp 21
+
+ \sa qLowerBound(), qBinaryFind()
+*/
+
+/*!
+ \fn RandomAccessIterator qUpperBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan)
+ \relates <QtAlgorithms>
+
+ \overload
+
+ Uses the \a lessThan function instead of \c operator<() to
+ compare the items.
+
+ Note that the items in the range must be sorted according to the order
+ specified by the \a lessThan object.
+*/
+
+/*!
+ \fn void qUpperBound(const Container &container, const T &value)
+ \relates <QtAlgorithms>
+
+ \overload
+
+ This is the same as qUpperBound(\a{container}.begin(), \a{container}.end(), value);
+*/
+
+
+/*! \fn RandomAccessIterator qBinaryFind(RandomAccessIterator begin, RandomAccessIterator end, const T &value)
+ \relates <QtAlgorithms>
+
+ Performs a binary search of the range [\a begin, \a end) and
+ returns the position of an occurrence of \a value. If there are
+ no occurrences of \a value, returns \a end.
+
+ The items in the range [\a begin, \a end) must be sorted in
+ ascending order; see qSort().
+
+ If there are many occurrences of the same value, any one of them
+ could be returned. Use qLowerBound() or qUpperBound() if you need
+ finer control.
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.cpp 22
+
+ This function requires the item type (in the example above,
+ QString) to implement \c operator<().
+
+ See the \l{<QtAlgorithms>#binaryFind example}{detailed
+ description} for an example usage.
+
+ \sa qLowerBound(), qUpperBound(), {random access iterators}
+*/
+
+/*! \fn RandomAccessIterator qBinaryFind(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan)
+ \relates <QtAlgorithms>
+
+ \overload
+
+ Uses the \a lessThan function instead of \c operator<() to
+ compare the items.
+
+ Note that the items in the range must be sorted according to the order
+ specified by the \a lessThan object.
+*/
+
+/*!
+ \fn void qBinaryFind(const Container &container, const T &value)
+ \relates <QtAlgorithms>
+
+ \overload
+
+ This is the same as qBinaryFind(\a{container}.begin(), \a{container}.end(), value);
+*/
+
+
+/*!
+ \fn void qDeleteAll(ForwardIterator begin, ForwardIterator end)
+ \relates <QtAlgorithms>
+
+ Deletes all the items in the range [\a begin, \a end) using the
+ C++ \c delete operator. The item type must be a pointer type (for
+ example, \c{QWidget *}).
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.cpp 23
+
+ Notice that qDeleteAll() doesn't remove the items from the
+ container; it merely calls \c delete on them. In the example
+ above, we call clear() on the container to remove the items.
+
+ This function can also be used to delete items stored in
+ associative containers, such as QMap and QHash. Only the objects
+ stored in each container will be deleted by this function; objects
+ used as keys will not be deleted.
+
+ \sa {forward iterators}
+*/
+
+/*!
+ \fn void qDeleteAll(const Container &c)
+ \relates <QtAlgorithms>
+
+ \overload
+
+ This is the same as qDeleteAll(\a{c}.begin(), \a{c}.end()).
+*/
+
+/*! \fn LessThan qLess()
+ \relates <QtAlgorithms>
+
+ Returns a functional object, or functor, that can be passed to qSort()
+ or qStableSort().
+
+ Example:
+
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.cpp 24
+
+ \sa {qGreater()}{qGreater<T>()}
+*/
+
+/*! \fn LessThan qGreater()
+ \relates <QtAlgorithms>
+
+ Returns a functional object, or functor, that can be passed to qSort()
+ or qStableSort().
+
+ Example:
+
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.cpp 25
+
+ \sa {qLess()}{qLess<T>()}
+*/
diff --git a/src/corelib/tools/qbitarray.cpp b/src/corelib/tools/qbitarray.cpp
new file mode 100644
index 0000000000..6181c82580
--- /dev/null
+++ b/src/corelib/tools/qbitarray.cpp
@@ -0,0 +1,738 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qbitarray.h"
+#include <qdatastream.h>
+#include <qdebug.h>
+#include <string.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QBitArray
+ \brief The QBitArray class provides an array of bits.
+
+ \ingroup tools
+ \ingroup shared
+ \reentrant
+
+ A QBitArray is an array that gives access to individual bits and
+ provides operators (\link operator&() AND\endlink, \link
+ operator|() OR\endlink, \link operator^() XOR\endlink, and \link
+ operator~() NOT\endlink) that work on entire arrays of bits. It
+ uses \l{implicit sharing} (copy-on-write) to reduce memory usage
+ and to avoid the needless copying of data.
+
+ The following code constructs a QBitArray containing 200 bits
+ initialized to false (0):
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qbitarray.cpp 0
+
+ To initialize the bits to true, either pass \c true as second
+ argument to the constructor, or call fill() later on.
+
+ QBitArray uses 0-based indexes, just like C++ arrays. To access
+ the bit at a particular index position, you can use operator[]().
+ On non-const bit arrays, operator[]() returns a reference to a
+ bit that can be used on the left side of an assignment. For
+ example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qbitarray.cpp 1
+
+ For technical reasons, it is more efficient to use testBit() and
+ setBit() to access bits in the array than operator[](). For
+ example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qbitarray.cpp 2
+
+ QBitArray supports \c{&} (\link operator&() AND\endlink), \c{|}
+ (\link operator|() OR\endlink), \c{^} (\link operator^()
+ XOR\endlink), \c{~} (\link operator~() NOT\endlink), as well as
+ \c{&=}, \c{|=}, and \c{^=}. These operators work in the same way
+ as the built-in C++ bitwise operators of the same name. For
+ example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qbitarray.cpp 3
+
+ For historical reasons, QBitArray distinguishes between a null
+ bit array and an empty bit array. A \e null bit array is a bit
+ array that is initialized using QBitArray's default constructor.
+ An \e empty bit array is any bit array with size 0. A null bit
+ array is always empty, but an empty bit array isn't necessarily
+ null:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qbitarray.cpp 4
+
+ All functions except isNull() treat null bit arrays the same as
+ empty bit arrays; for example, QBitArray() compares equal to
+ QBitArray(0). We recommend that you always use isEmpty() and
+ avoid isNull().
+
+ \sa QByteArray, QVector
+*/
+
+/*! \fn QBitArray::QBitArray()
+
+ Constructs an empty bit array.
+
+ \sa isEmpty()
+*/
+
+/*!
+ Constructs a bit array containing \a size bits. The bits are
+ initialized with \a value, which defaults to false (0).
+*/
+QBitArray::QBitArray(int size, bool value)
+{
+ if (!size) {
+ d.resize(0);
+ return;
+ }
+ d.resize(1 + (size+7)/8);
+ uchar* c = reinterpret_cast<uchar*>(d.data());
+ memset(c, value ? 0xff : 0, d.size());
+ *c = d.size()*8 - size;
+ if (value && size && size % 8)
+ *(c+1+size/8) &= (1 << (size%8)) - 1;
+}
+
+/*! \fn int QBitArray::size() const
+
+ Returns the number of bits stored in the bit array.
+
+ \sa resize()
+*/
+
+/*! \fn int QBitArray::count() const
+
+ Same as size().
+*/
+
+/*!
+ If \a on is true, this function returns the number of
+ 1-bits stored in the bit array; otherwise the number
+ of 0-bits is returned.
+*/
+int QBitArray::count(bool on) const
+{
+ int numBits = 0;
+ int len = size();
+#if 0
+ for (int i = 0; i < len; ++i)
+ numBits += testBit(i);
+#else
+ // See http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
+ const quint8 *bits = reinterpret_cast<const quint8 *>(d.data()) + 1;
+ while (len >= 32) {
+ quint32 v = quint32(bits[0]) | (quint32(bits[1]) << 8) | (quint32(bits[2]) << 16) | (quint32(bits[3]) << 24);
+ quint32 c = ((v & 0xfff) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f;
+ c += (((v & 0xfff000) >> 12) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f;
+ c += ((v >> 24) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f;
+ len -= 32;
+ bits += 4;
+ numBits += int(c);
+ }
+ while (len >= 24) {
+ quint32 v = quint32(bits[0]) | (quint32(bits[1]) << 8) | (quint32(bits[2]) << 16);
+ quint32 c = ((v & 0xfff) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f;
+ c += (((v & 0xfff000) >> 12) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f;
+ len -= 24;
+ bits += 3;
+ numBits += int(c);
+ }
+ while (len >= 0) {
+ if (bits[len / 8] & (1 << ((len - 1) & 7)))
+ ++numBits;
+ --len;
+ }
+#endif
+ return on ? numBits : size() - numBits;
+}
+
+/*!
+ Resizes the bit array to \a size bits.
+
+ If \a size is greater than the current size, the bit array is
+ extended to make it \a size bits with the extra bits added to the
+ end. The new bits are initialized to false (0).
+
+ If \a size is less than the current size, bits are removed from
+ the end.
+
+ \sa size()
+*/
+void QBitArray::resize(int size)
+{
+ if (!size) {
+ d.resize(0);
+ } else {
+ int s = d.size();
+ d.resize(1 + (size+7)/8);
+ uchar* c = reinterpret_cast<uchar*>(d.data());
+ if (size > (s << 3))
+ memset(c + s, 0, d.size() - s);
+ else if ( size % 8)
+ *(c+1+size/8) &= (1 << (size%8)) - 1;
+ *c = d.size()*8 - size;
+ }
+}
+
+/*! \fn bool QBitArray::isEmpty() const
+
+ Returns true if this bit array has size 0; otherwise returns
+ false.
+
+ \sa size()
+*/
+
+/*! \fn bool QBitArray::isNull() const
+
+ Returns true if this bit array is null; otherwise returns false.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbitarray.cpp 5
+
+ Qt makes a distinction between null bit arrays and empty bit
+ arrays for historical reasons. For most applications, what
+ matters is whether or not a bit array contains any data,
+ and this can be determined using isEmpty().
+
+ \sa isEmpty()
+*/
+
+/*! \fn bool QBitArray::fill(bool value, int size = -1)
+
+ Sets every bit in the bit array to \a value, returning true if successful;
+ otherwise returns false. If \a size is different from -1 (the default),
+ the bit array is resized to \a size beforehand.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbitarray.cpp 6
+
+ \sa resize()
+*/
+
+/*!
+ \overload
+
+ Sets bits at index positions \a begin up to and excluding \a end
+ to \a value.
+
+ \a begin and \a end must be a valid index position in the bit
+ array (i.e., 0 <= \a begin <= size() and 0 <= \a end <= size()).
+*/
+
+void QBitArray::fill(bool value, int begin, int end)
+{
+ while (begin < end && begin & 0x7)
+ setBit(begin++, value);
+ int len = end - begin;
+ if (len <= 0)
+ return;
+ int s = len & ~0x7;
+ uchar *c = reinterpret_cast<uchar*>(d.data());
+ memset(c + (begin >> 3) + 1, value ? 0xff : 0, s >> 3);
+ begin += s;
+ while (begin < end)
+ setBit(begin++, value);
+}
+
+/*! \fn bool QBitArray::isDetached() const
+
+ \internal
+*/
+
+/*! \fn void QBitArray::detach()
+
+ \internal
+*/
+
+/*! \fn void QBitArray::clear()
+
+ Clears the contents of the bit array and makes it empty.
+
+ \sa resize(), isEmpty()
+*/
+
+/*! \fn void QBitArray::truncate(int pos)
+
+ Truncates the bit array at index position \a pos.
+
+ If \a pos is beyond the end of the array, nothing happens.
+
+ \sa resize()
+*/
+
+/*! \fn bool QBitArray::toggleBit(int i)
+
+ Inverts the value of the bit at index position \a i, returning the
+ previous value of that bit as either true (if it was set) or false (if
+ it was unset).
+
+ If the previous value was 0, the new value will be 1. If the
+ previous value was 1, the new value will be 0.
+
+ \a i must be a valid index position in the bit array (i.e., 0 <=
+ \a i < size()).
+
+ \sa setBit(), clearBit()
+*/
+
+/*! \fn bool QBitArray::testBit(int i) const
+
+ Returns true if the bit at index position \a i is 1; otherwise
+ returns false.
+
+ \a i must be a valid index position in the bit array (i.e., 0 <=
+ \a i < size()).
+
+ \sa setBit(), clearBit()
+*/
+
+/*! \fn bool QBitArray::setBit(int i)
+
+ Sets the bit at index position \a i to 1.
+
+ \a i must be a valid index position in the bit array (i.e., 0 <=
+ \a i < size()).
+
+ \sa clearBit(), toggleBit()
+*/
+
+/*! \fn void QBitArray::setBit(int i, bool value)
+
+ \overload
+
+ Sets the bit at index position \a i to \a value.
+*/
+
+/*! \fn void QBitArray::clearBit(int i)
+
+ Sets the bit at index position \a i to 0.
+
+ \a i must be a valid index position in the bit array (i.e., 0 <=
+ \a i < size()).
+
+ \sa setBit(), toggleBit()
+*/
+
+/*! \fn bool QBitArray::at(int i) const
+
+ Returns the value of the bit at index position \a i.
+
+ \a i must be a valid index position in the bit array (i.e., 0 <=
+ \a i < size()).
+
+ \sa operator[]()
+*/
+
+/*! \fn QBitRef QBitArray::operator[](int i)
+
+ Returns the bit at index position \a i as a modifiable reference.
+
+ \a i must be a valid index position in the bit array (i.e., 0 <=
+ \a i < size()).
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbitarray.cpp 7
+
+ The return value is of type QBitRef, a helper class for QBitArray.
+ When you get an object of type QBitRef, you can assign to
+ it, and the assignment will apply to the bit in the QBitArray
+ from which you got the reference.
+
+ The functions testBit(), setBit(), and clearBit() are slightly
+ faster.
+
+ \sa at(), testBit(), setBit(), clearBit()
+*/
+
+/*! \fn bool QBitArray::operator[](int i) const
+
+ \overload
+*/
+
+/*! \fn bool QBitArray::operator[](uint i)
+
+ \overload
+*/
+
+/*! \fn bool QBitArray::operator[](uint i) const
+
+ \overload
+*/
+
+/*! \fn QBitArray::QBitArray(const QBitArray &other)
+
+ Constructs a copy of \a other.
+
+ This operation takes \l{constant time}, because QBitArray is
+ \l{implicitly shared}. This makes returning a QBitArray from a
+ function very fast. If a shared instance is modified, it will be
+ copied (copy-on-write), and that takes \l{linear time}.
+
+ \sa operator=()
+*/
+
+/*! \fn QBitArray &QBitArray::operator=(const QBitArray &other)
+
+ Assigns \a other to this bit array and returns a reference to
+ this bit array.
+*/
+
+/*! \fn void QBitArray::swap(QBitArray &other)
+ \since 4.8
+
+ Swaps bit array \a other with this bit array. This operation is very
+ fast and never fails.
+*/
+
+/*! \fn bool QBitArray::operator==(const QBitArray &other) const
+
+ Returns true if \a other is equal to this bit array; otherwise
+ returns false.
+
+ \sa operator!=()
+*/
+
+/*! \fn bool QBitArray::operator!=(const QBitArray &other) const
+
+ Returns true if \a other is not equal to this bit array;
+ otherwise returns false.
+
+ \sa operator==()
+*/
+
+/*!
+ Performs the AND operation between all bits in this bit array and
+ \a other. Assigns the result to this bit array, and returns a
+ reference to it.
+
+ The result has the length of the longest of the two bit arrays,
+ with any missing bits (if one array is shorter than the other)
+ taken to be 0.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbitarray.cpp 8
+
+ \sa operator&(), operator|=(), operator^=(), operator~()
+*/
+
+QBitArray &QBitArray::operator&=(const QBitArray &other)
+{
+ resize(qMax(size(), other.size()));
+ uchar *a1 = reinterpret_cast<uchar*>(d.data()) + 1;
+ const uchar *a2 = reinterpret_cast<const uchar*>(other.d.constData()) + 1;
+ int n = other.d.size() -1 ;
+ int p = d.size() - 1 - n;
+ while (n-- > 0)
+ *a1++ &= *a2++;
+ while (p-- > 0)
+ *a1++ = 0;
+ return *this;
+}
+
+/*!
+ Performs the OR operation between all bits in this bit array and
+ \a other. Assigns the result to this bit array, and returns a
+ reference to it.
+
+ The result has the length of the longest of the two bit arrays,
+ with any missing bits (if one array is shorter than the other)
+ taken to be 0.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbitarray.cpp 9
+
+ \sa operator|(), operator&=(), operator^=(), operator~()
+*/
+
+QBitArray &QBitArray::operator|=(const QBitArray &other)
+{
+ resize(qMax(size(), other.size()));
+ uchar *a1 = reinterpret_cast<uchar*>(d.data()) + 1;
+ const uchar *a2 = reinterpret_cast<const uchar *>(other.d.constData()) + 1;
+ int n = other.d.size() - 1;
+ while (n-- > 0)
+ *a1++ |= *a2++;
+ return *this;
+}
+
+/*!
+ Performs the XOR operation between all bits in this bit array and
+ \a other. Assigns the result to this bit array, and returns a
+ reference to it.
+
+ The result has the length of the longest of the two bit arrays,
+ with any missing bits (if one array is shorter than the other)
+ taken to be 0.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbitarray.cpp 10
+
+ \sa operator^(), operator&=(), operator|=(), operator~()
+*/
+
+QBitArray &QBitArray::operator^=(const QBitArray &other)
+{
+ resize(qMax(size(), other.size()));
+ uchar *a1 = reinterpret_cast<uchar*>(d.data()) + 1;
+ const uchar *a2 = reinterpret_cast<const uchar *>(other.d.constData()) + 1;
+ int n = other.d.size() - 1;
+ while (n-- > 0)
+ *a1++ ^= *a2++;
+ return *this;
+}
+
+/*!
+ Returns a bit array that contains the inverted bits of this bit
+ array.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbitarray.cpp 11
+
+ \sa operator&(), operator|(), operator^()
+*/
+
+QBitArray QBitArray::operator~() const
+{
+ int sz = size();
+ QBitArray a(sz);
+ const uchar *a1 = reinterpret_cast<const uchar *>(d.constData()) + 1;
+ uchar *a2 = reinterpret_cast<uchar*>(a.d.data()) + 1;
+ int n = d.size() - 1;
+
+ while (n-- > 0)
+ *a2++ = ~*a1++;
+
+ if (sz && sz%8)
+ *(a2-1) &= (1 << (sz%8)) - 1;
+ return a;
+}
+
+/*!
+ \relates QBitArray
+
+ Returns a bit array that is the AND of the bit arrays \a a1 and \a
+ a2.
+
+ The result has the length of the longest of the two bit arrays,
+ with any missing bits (if one array is shorter than the other)
+ taken to be 0.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbitarray.cpp 12
+
+ \sa QBitArray::operator&=(), operator|(), operator^()
+*/
+
+QBitArray operator&(const QBitArray &a1, const QBitArray &a2)
+{
+ QBitArray tmp = a1;
+ tmp &= a2;
+ return tmp;
+}
+
+/*!
+ \relates QBitArray
+
+ Returns a bit array that is the OR of the bit arrays \a a1 and \a
+ a2.
+
+ The result has the length of the longest of the two bit arrays,
+ with any missing bits (if one array is shorter than the other)
+ taken to be 0.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbitarray.cpp 13
+
+ \sa QBitArray::operator|=(), operator&(), operator^()
+*/
+
+QBitArray operator|(const QBitArray &a1, const QBitArray &a2)
+{
+ QBitArray tmp = a1;
+ tmp |= a2;
+ return tmp;
+}
+
+/*!
+ \relates QBitArray
+
+ Returns a bit array that is the XOR of the bit arrays \a a1 and \a
+ a2.
+
+ The result has the length of the longest of the two bit arrays,
+ with any missing bits (if one array is shorter than the other)
+ taken to be 0.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbitarray.cpp 14
+
+ \sa QBitArray::operator^=(), operator&(), operator|()
+*/
+
+QBitArray operator^(const QBitArray &a1, const QBitArray &a2)
+{
+ QBitArray tmp = a1;
+ tmp ^= a2;
+ return tmp;
+}
+
+/*!
+ \class QBitRef
+ \reentrant
+ \brief The QBitRef class is an internal class, used with QBitArray.
+
+ \internal
+
+ The QBitRef is required by the indexing [] operator on bit arrays.
+ It is not for use in any other context.
+*/
+
+/*! \fn QBitRef::QBitRef (QBitArray& a, int i)
+
+ Constructs a reference to element \a i in the QBitArray \a a.
+ This is what QBitArray::operator[] constructs its return value
+ with.
+*/
+
+/*! \fn QBitRef::operator bool() const
+
+ Returns the value referenced by the QBitRef.
+*/
+
+/*! \fn bool QBitRef::operator!() const
+
+ \internal
+*/
+
+/*! \fn QBitRef& QBitRef::operator= (const QBitRef& v)
+
+ Sets the value referenced by the QBitRef to that referenced by
+ QBitRef \a v.
+*/
+
+/*! \fn QBitRef& QBitRef::operator= (bool v)
+ \overload
+
+ Sets the value referenced by the QBitRef to \a v.
+*/
+
+
+/*****************************************************************************
+ QBitArray stream functions
+ *****************************************************************************/
+
+#ifndef QT_NO_DATASTREAM
+/*!
+ \relates QBitArray
+
+ Writes bit array \a ba to stream \a out.
+
+ \sa \link datastreamformat.html Format of the QDataStream operators \endlink
+*/
+
+QDataStream &operator<<(QDataStream &out, const QBitArray &ba)
+{
+ quint32 len = ba.size();
+ out << len;
+ if (len > 0)
+ out.writeRawData(ba.d.constData() + 1, ba.d.size() - 1);
+ return out;
+}
+
+/*!
+ \relates QBitArray
+
+ Reads a bit array into \a ba from stream \a in.
+
+ \sa \link datastreamformat.html Format of the QDataStream operators \endlink
+*/
+
+QDataStream &operator>>(QDataStream &in, QBitArray &ba)
+{
+ ba.clear();
+ quint32 len;
+ in >> len;
+ if (len == 0) {
+ ba.clear();
+ return in;
+ }
+
+ const quint32 Step = 8 * 1024 * 1024;
+ quint32 totalBytes = (len + 7) / 8;
+ quint32 allocated = 0;
+
+ while (allocated < totalBytes) {
+ int blockSize = qMin(Step, totalBytes - allocated);
+ ba.d.resize(allocated + blockSize + 1);
+ if (in.readRawData(ba.d.data() + 1 + allocated, blockSize) != blockSize) {
+ ba.clear();
+ in.setStatus(QDataStream::ReadPastEnd);
+ return in;
+ }
+ allocated += blockSize;
+ }
+
+ int paddingMask = ~((0x1 << (len & 0x7)) - 1);
+ if (paddingMask != ~0x0 && (ba.d.constData()[ba.d.size() - 1] & paddingMask)) {
+ ba.clear();
+ in.setStatus(QDataStream::ReadCorruptData);
+ return in;
+ }
+
+ *ba.d.data() = ba.d.size() * 8 - len;
+ return in;
+}
+#endif // QT_NO_DATASTREAM
+
+/*!
+ \fn DataPtr &QBitArray::data_ptr()
+ \internal
+*/
+
+/*!
+ \typedef QBitArray::DataPtr
+ \internal
+*/
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qbitarray.h b/src/corelib/tools/qbitarray.h
new file mode 100644
index 0000000000..cec338c394
--- /dev/null
+++ b/src/corelib/tools/qbitarray.h
@@ -0,0 +1,180 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBITARRAY_H
+#define QBITARRAY_H
+
+#include <QtCore/qbytearray.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QBitRef;
+class Q_CORE_EXPORT QBitArray
+{
+ friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QBitArray &);
+ friend Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QBitArray &);
+ friend Q_CORE_EXPORT uint qHash(const QBitArray &key);
+ QByteArray d;
+
+public:
+ inline QBitArray() {}
+ explicit QBitArray(int size, bool val = false);
+ QBitArray(const QBitArray &other) : d(other.d) {}
+ inline QBitArray &operator=(const QBitArray &other) { d = other.d; return *this; }
+#ifdef Q_COMPILER_RVALUE_REFS
+ inline QBitArray &operator=(QBitArray &&other)
+ { qSwap(d, other.d); return *this; }
+#endif
+
+ inline void swap(QBitArray &other) { qSwap(d, other.d); }
+
+ inline int size() const { return (d.size() << 3) - *d.constData(); }
+ inline int count() const { return (d.size() << 3) - *d.constData(); }
+ int count(bool on) const;
+ // ### Qt 5: Store the number of set bits separately
+
+ inline bool isEmpty() const { return d.isEmpty(); }
+ inline bool isNull() const { return d.isNull(); }
+
+ void resize(int size);
+
+ inline void detach() { d.detach(); }
+ inline bool isDetached() const { return d.isDetached(); }
+ inline void clear() { d.clear(); }
+
+ bool testBit(int i) const;
+ void setBit(int i);
+ void setBit(int i, bool val);
+ void clearBit(int i);
+ bool toggleBit(int i);
+
+ bool at(int i) const;
+ QBitRef operator[](int i);
+ bool operator[](int i) const;
+ QBitRef operator[](uint i);
+ bool operator[](uint i) const;
+
+ QBitArray& operator&=(const QBitArray &);
+ QBitArray& operator|=(const QBitArray &);
+ QBitArray& operator^=(const QBitArray &);
+ QBitArray operator~() const;
+
+ inline bool operator==(const QBitArray& a) const { return d == a.d; }
+ inline bool operator!=(const QBitArray& a) const { return d != a.d; }
+
+ inline bool fill(bool val, int size = -1);
+ void fill(bool val, int first, int last);
+
+ inline void truncate(int pos) { if (pos < size()) resize(pos); }
+
+public:
+ typedef QByteArray::DataPtr DataPtr;
+ inline DataPtr &data_ptr() { return d.data_ptr(); }
+};
+
+inline bool QBitArray::fill(bool aval, int asize)
+{ *this = QBitArray((asize < 0 ? this->size() : asize), aval); return true; }
+
+Q_CORE_EXPORT QBitArray operator&(const QBitArray &, const QBitArray &);
+Q_CORE_EXPORT QBitArray operator|(const QBitArray &, const QBitArray &);
+Q_CORE_EXPORT QBitArray operator^(const QBitArray &, const QBitArray &);
+
+inline bool QBitArray::testBit(int i) const
+{ Q_ASSERT(i >= 0 && i < size());
+ return (*(reinterpret_cast<const uchar*>(d.constData())+1+(i>>3)) & (1 << (i & 7))) != 0; }
+
+inline void QBitArray::setBit(int i)
+{ Q_ASSERT(i >= 0 && i < size());
+ *(reinterpret_cast<uchar*>(d.data())+1+(i>>3)) |= uchar(1 << (i & 7)); }
+
+inline void QBitArray::clearBit(int i)
+{ Q_ASSERT(i >= 0 && i < size());
+ *(reinterpret_cast<uchar*>(d.data())+1+(i>>3)) &= ~uchar(1 << (i & 7)); }
+
+inline void QBitArray::setBit(int i, bool val)
+{ if (val) setBit(i); else clearBit(i); }
+
+inline bool QBitArray::toggleBit(int i)
+{ Q_ASSERT(i >= 0 && i < size());
+ uchar b = uchar(1<<(i&7)); uchar* p = reinterpret_cast<uchar*>(d.data())+1+(i>>3);
+ uchar c = uchar(*p&b); *p^=b; return c!=0; }
+
+inline bool QBitArray::operator[](int i) const { return testBit(i); }
+inline bool QBitArray::operator[](uint i) const { return testBit(i); }
+inline bool QBitArray::at(int i) const { return testBit(i); }
+
+class Q_CORE_EXPORT QBitRef
+{
+private:
+ QBitArray& a;
+ int i;
+ inline QBitRef(QBitArray& array, int idx) : a(array), i(idx) {}
+ friend class QBitArray;
+public:
+ inline operator bool() const { return a.testBit(i); }
+ inline bool operator!() const { return !a.testBit(i); }
+ QBitRef& operator=(const QBitRef& val) { a.setBit(i, val); return *this; }
+ QBitRef& operator=(bool val) { a.setBit(i, val); return *this; }
+};
+
+inline QBitRef QBitArray::operator[](int i)
+{ Q_ASSERT(i >= 0); return QBitRef(*this, i); }
+inline QBitRef QBitArray::operator[](uint i)
+{ return QBitRef(*this, i); }
+
+
+#ifndef QT_NO_DATASTREAM
+Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QBitArray &);
+Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QBitArray &);
+#endif
+
+Q_DECLARE_TYPEINFO(QBitArray, Q_MOVABLE_TYPE);
+Q_DECLARE_SHARED(QBitArray)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QBITARRAY_H
diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp
new file mode 100644
index 0000000000..1c9b6541e3
--- /dev/null
+++ b/src/corelib/tools/qbytearray.cpp
@@ -0,0 +1,4394 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qbytearray.h"
+#include "qbytearraymatcher.h"
+#include "qtools_p.h"
+#include "qstring.h"
+#include "qlist.h"
+#include "qlocale.h"
+#include "qlocale_p.h"
+#include "qscopedpointer.h"
+#include <qdatastream.h>
+
+#ifndef QT_NO_COMPRESS
+#include <zlib.h>
+#endif
+#include <ctype.h>
+#include <limits.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define IS_RAW_DATA(d) ((d)->data != (d)->array)
+
+QT_BEGIN_NAMESPACE
+
+
+int qFindByteArray(
+ const char *haystack0, int haystackLen, int from,
+ const char *needle0, int needleLen);
+
+
+int qAllocMore(int alloc, int extra)
+{
+ if (alloc == 0 && extra == 0)
+ return 0;
+ const int page = 1 << 12;
+ int nalloc;
+ alloc += extra;
+ if (alloc < 1<<6) {
+ nalloc = (1<<3) + ((alloc >>3) << 3);
+ } else {
+ // don't do anything if the loop will overflow signed int.
+ if (alloc >= INT_MAX/2)
+ return INT_MAX;
+ nalloc = (alloc < page) ? 1 << 3 : page;
+ while (nalloc < alloc) {
+ if (nalloc <= 0)
+ return INT_MAX;
+ nalloc *= 2;
+ }
+ }
+ return nalloc - extra;
+}
+
+/*****************************************************************************
+ Safe and portable C string functions; extensions to standard string.h
+ *****************************************************************************/
+
+/*! \relates QByteArray
+
+ Returns a duplicate string.
+
+ Allocates space for a copy of \a src, copies it, and returns a
+ pointer to the copy. If \a src is 0, it immediately returns 0.
+
+ Ownership is passed to the caller, so the returned string must be
+ deleted using \c delete[].
+*/
+
+char *qstrdup(const char *src)
+{
+ if (!src)
+ return 0;
+ char *dst = new char[strlen(src) + 1];
+ return qstrcpy(dst, src);
+}
+
+/*! \relates QByteArray
+
+ Copies all the characters up to and including the '\\0' from \a
+ src into \a dst and returns a pointer to \a dst. If \a src is 0,
+ it immediately returns 0.
+
+ This function assumes that \a dst is large enough to hold the
+ contents of \a src.
+
+ \sa qstrncpy()
+*/
+
+char *qstrcpy(char *dst, const char *src)
+{
+ if (!src)
+ return 0;
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+ int len = qstrlen(src);
+ // This is actually not secure!!! It will be fixed
+ // properly in a later release!
+ if (len >= 0 && strcpy_s(dst, len+1, src) == 0)
+ return dst;
+ return 0;
+#else
+ return strcpy(dst, src);
+#endif
+}
+
+/*! \relates QByteArray
+
+ A safe \c strncpy() function.
+
+ Copies at most \a len bytes from \a src (stopping at \a len or the
+ terminating '\\0' whichever comes first) into \a dst and returns a
+ pointer to \a dst. Guarantees that \a dst is '\\0'-terminated. If
+ \a src or \a dst is 0, returns 0 immediately.
+
+ This function assumes that \a dst is at least \a len characters
+ long.
+
+ \note When compiling with Visual C++ compiler version 14.00
+ (Visual C++ 2005) or later, internally the function strncpy_s
+ will be used.
+
+ \sa qstrcpy()
+*/
+
+char *qstrncpy(char *dst, const char *src, uint len)
+{
+ if (!src || !dst)
+ return 0;
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+ strncpy_s(dst, len, src, len-1);
+#else
+ strncpy(dst, src, len);
+#endif
+ if (len > 0)
+ dst[len-1] = '\0';
+ return dst;
+}
+
+/*! \fn uint qstrlen(const char *str)
+ \relates QByteArray
+
+ A safe \c strlen() function.
+
+ Returns the number of characters that precede the terminating '\\0',
+ or 0 if \a str is 0.
+
+ \sa qstrnlen()
+*/
+
+/*! \fn uint qstrnlen(const char *str, uint maxlen)
+ \relates QByteArray
+ \since 4.2
+
+ A safe \c strnlen() function.
+
+ Returns the number of characters that precede the terminating '\\0', but
+ at most \a maxlen. If \a str is 0, returns 0.
+
+ \sa qstrlen()
+*/
+
+/*!
+ \relates QByteArray
+
+ A safe \c strcmp() function.
+
+ Compares \a str1 and \a str2. Returns a negative value if \a str1
+ is less than \a str2, 0 if \a str1 is equal to \a str2 or a
+ positive value if \a str1 is greater than \a str2.
+
+ Special case 1: Returns 0 if \a str1 and \a str2 are both 0.
+
+ Special case 2: Returns an arbitrary non-zero value if \a str1 is 0
+ or \a str2 is 0 (but not both).
+
+ \sa qstrncmp(), qstricmp(), qstrnicmp(), {8-bit Character Comparisons}
+*/
+int qstrcmp(const char *str1, const char *str2)
+{
+ return (str1 && str2) ? strcmp(str1, str2)
+ : (str1 ? 1 : (str2 ? -1 : 0));
+}
+
+/*! \fn int qstrncmp(const char *str1, const char *str2, uint len);
+
+ \relates QByteArray
+
+ A safe \c strncmp() function.
+
+ Compares at most \a len bytes of \a str1 and \a str2.
+
+ Returns a negative value if \a str1 is less than \a str2, 0 if \a
+ str1 is equal to \a str2 or a positive value if \a str1 is greater
+ than \a str2.
+
+ Special case 1: Returns 0 if \a str1 and \a str2 are both 0.
+
+ Special case 2: Returns a random non-zero value if \a str1 is 0
+ or \a str2 is 0 (but not both).
+
+ \sa qstrcmp(), qstricmp(), qstrnicmp(), {8-bit Character Comparisons}
+*/
+
+/*! \relates QByteArray
+
+ A safe \c stricmp() function.
+
+ Compares \a str1 and \a str2 ignoring the case of the
+ characters. The encoding of the strings is assumed to be Latin-1.
+
+ Returns a negative value if \a str1 is less than \a str2, 0 if \a
+ str1 is equal to \a str2 or a positive value if \a str1 is greater
+ than \a str2.
+
+ Special case 1: Returns 0 if \a str1 and \a str2 are both 0.
+
+ Special case 2: Returns a random non-zero value if \a str1 is 0
+ or \a str2 is 0 (but not both).
+
+ \sa qstrcmp(), qstrncmp(), qstrnicmp(), {8-bit Character Comparisons}
+*/
+
+int qstricmp(const char *str1, const char *str2)
+{
+ register const uchar *s1 = reinterpret_cast<const uchar *>(str1);
+ register const uchar *s2 = reinterpret_cast<const uchar *>(str2);
+ int res;
+ uchar c;
+ if (!s1 || !s2)
+ return s1 ? 1 : (s2 ? -1 : 0);
+ for (; !(res = (c = QChar::toLower((ushort)*s1)) - QChar::toLower((ushort)*s2)); s1++, s2++)
+ if (!c) // strings are equal
+ break;
+ return res;
+}
+
+/*! \relates QByteArray
+
+ A safe \c strnicmp() function.
+
+ Compares at most \a len bytes of \a str1 and \a str2 ignoring the
+ case of the characters. The encoding of the strings is assumed to
+ be Latin-1.
+
+ Returns a negative value if \a str1 is less than \a str2, 0 if \a str1
+ is equal to \a str2 or a positive value if \a str1 is greater than \a
+ str2.
+
+ Special case 1: Returns 0 if \a str1 and \a str2 are both 0.
+
+ Special case 2: Returns a random non-zero value if \a str1 is 0
+ or \a str2 is 0 (but not both).
+
+ \sa qstrcmp(), qstrncmp(), qstricmp(), {8-bit Character Comparisons}
+*/
+
+int qstrnicmp(const char *str1, const char *str2, uint len)
+{
+ register const uchar *s1 = reinterpret_cast<const uchar *>(str1);
+ register const uchar *s2 = reinterpret_cast<const uchar *>(str2);
+ int res;
+ uchar c;
+ if (!s1 || !s2)
+ return s1 ? 1 : (s2 ? -1 : 0);
+ for (; len--; s1++, s2++) {
+ if ((res = (c = QChar::toLower((ushort)*s1)) - QChar::toLower((ushort)*s2)))
+ return res;
+ if (!c) // strings are equal
+ break;
+ }
+ return 0;
+}
+
+/*!
+ \internal
+ */
+int qstrcmp(const QByteArray &str1, const char *str2)
+{
+ if (!str2)
+ return str1.isEmpty() ? 0 : +1;
+
+ const char *str1data = str1.constData();
+ const char *str1end = str1data + str1.length();
+ for ( ; str1data < str1end && *str2; ++str1data, ++str2) {
+ register int diff = int(uchar(*str1data)) - uchar(*str2);
+ if (diff)
+ // found a difference
+ return diff;
+ }
+
+ // Why did we stop?
+ if (*str2 != '\0')
+ // not the null, so we stopped because str1 is shorter
+ return -1;
+ if (str1data < str1end)
+ // we haven't reached the end, so str1 must be longer
+ return +1;
+ return 0;
+}
+
+/*!
+ \internal
+ */
+int qstrcmp(const QByteArray &str1, const QByteArray &str2)
+{
+ int l1 = str1.length();
+ int l2 = str2.length();
+ int ret = memcmp(str1, str2, qMin(l1, l2));
+ if (ret != 0)
+ return ret;
+
+ // they matched qMin(l1, l2) bytes
+ // so the longer one is lexically after the shorter one
+ return l1 - l2;
+}
+
+// the CRC table below is created by the following piece of code
+#if 0
+static void createCRC16Table() // build CRC16 lookup table
+{
+ register unsigned int i;
+ register unsigned int j;
+ unsigned short crc_tbl[16];
+ unsigned int v0, v1, v2, v3;
+ for (i = 0; i < 16; i++) {
+ v0 = i & 1;
+ v1 = (i >> 1) & 1;
+ v2 = (i >> 2) & 1;
+ v3 = (i >> 3) & 1;
+ j = 0;
+#undef SET_BIT
+#define SET_BIT(x, b, v) (x) |= (v) << (b)
+ SET_BIT(j, 0, v0);
+ SET_BIT(j, 7, v0);
+ SET_BIT(j, 12, v0);
+ SET_BIT(j, 1, v1);
+ SET_BIT(j, 8, v1);
+ SET_BIT(j, 13, v1);
+ SET_BIT(j, 2, v2);
+ SET_BIT(j, 9, v2);
+ SET_BIT(j, 14, v2);
+ SET_BIT(j, 3, v3);
+ SET_BIT(j, 10, v3);
+ SET_BIT(j, 15, v3);
+ crc_tbl[i] = j;
+ }
+ printf("static const quint16 crc_tbl[16] = {\n");
+ for (int i = 0; i < 16; i +=4)
+ printf(" 0x%04x, 0x%04x, 0x%04x, 0x%04x,\n", crc_tbl[i], crc_tbl[i+1], crc_tbl[i+2], crc_tbl[i+3]);
+ printf("};\n");
+}
+#endif
+
+static const quint16 crc_tbl[16] = {
+ 0x0000, 0x1081, 0x2102, 0x3183,
+ 0x4204, 0x5285, 0x6306, 0x7387,
+ 0x8408, 0x9489, 0xa50a, 0xb58b,
+ 0xc60c, 0xd68d, 0xe70e, 0xf78f
+};
+
+/*!
+ \relates QByteArray
+
+ Returns the CRC-16 checksum of the first \a len bytes of \a data.
+
+ The checksum is independent of the byte order (endianness).
+
+ \note This function is a 16-bit cache conserving (16 entry table)
+ implementation of the CRC-16-CCITT algorithm.
+*/
+
+quint16 qChecksum(const char *data, uint len)
+{
+ register quint16 crc = 0xffff;
+ uchar c;
+ const uchar *p = reinterpret_cast<const uchar *>(data);
+ while (len--) {
+ c = *p++;
+ crc = ((crc >> 4) & 0x0fff) ^ crc_tbl[((crc ^ c) & 15)];
+ c >>= 4;
+ crc = ((crc >> 4) & 0x0fff) ^ crc_tbl[((crc ^ c) & 15)];
+ }
+ return ~crc & 0xffff;
+}
+
+/*!
+ \fn QByteArray qCompress(const QByteArray& data, int compressionLevel)
+
+ \relates QByteArray
+
+ Compresses the \a data byte array and returns the compressed data
+ in a new byte array.
+
+ The \a compressionLevel parameter specifies how much compression
+ should be used. Valid values are between 0 and 9, with 9
+ corresponding to the greatest compression (i.e. smaller compressed
+ data) at the cost of using a slower algorithm. Smaller values (8,
+ 7, ..., 1) provide successively less compression at slightly
+ faster speeds. The value 0 corresponds to no compression at all.
+ The default value is -1, which specifies zlib's default
+ compression.
+
+ \sa qUncompress()
+*/
+
+/*! \relates QByteArray
+
+ \overload
+
+ Compresses the first \a nbytes of \a data and returns the
+ compressed data in a new byte array.
+*/
+
+#ifndef QT_NO_COMPRESS
+QByteArray qCompress(const uchar* data, int nbytes, int compressionLevel)
+{
+ if (nbytes == 0) {
+ return QByteArray(4, '\0');
+ }
+ if (!data) {
+ qWarning("qCompress: Data is null");
+ return QByteArray();
+ }
+ if (compressionLevel < -1 || compressionLevel > 9)
+ compressionLevel = -1;
+
+ ulong len = nbytes + nbytes / 100 + 13;
+ QByteArray bazip;
+ int res;
+ do {
+ bazip.resize(len + 4);
+ res = ::compress2((uchar*)bazip.data()+4, &len, (uchar*)data, nbytes, compressionLevel);
+
+ switch (res) {
+ case Z_OK:
+ bazip.resize(len + 4);
+ bazip[0] = (nbytes & 0xff000000) >> 24;
+ bazip[1] = (nbytes & 0x00ff0000) >> 16;
+ bazip[2] = (nbytes & 0x0000ff00) >> 8;
+ bazip[3] = (nbytes & 0x000000ff);
+ break;
+ case Z_MEM_ERROR:
+ qWarning("qCompress: Z_MEM_ERROR: Not enough memory");
+ bazip.resize(0);
+ break;
+ case Z_BUF_ERROR:
+ len *= 2;
+ break;
+ }
+ } while (res == Z_BUF_ERROR);
+
+ return bazip;
+}
+#endif
+
+/*!
+ \fn QByteArray qUncompress(const QByteArray &data)
+
+ \relates QByteArray
+
+ Uncompresses the \a data byte array and returns a new byte array
+ with the uncompressed data.
+
+ Returns an empty QByteArray if the input data was corrupt.
+
+ This function will uncompress data compressed with qCompress()
+ from this and any earlier Qt version, back to Qt 3.1 when this
+ feature was added.
+
+ \bold{Note:} If you want to use this function to uncompress external
+ data that was compressed using zlib, you first need to prepend a four
+ byte header to the byte array containing the data. The header must
+ contain the expected length (in bytes) of the uncompressed data,
+ expressed as an unsigned, big-endian, 32-bit integer.
+
+ \sa qCompress()
+*/
+
+/*! \relates QByteArray
+
+ \overload
+
+ Uncompresses the first \a nbytes of \a data and returns a new byte
+ array with the uncompressed data.
+*/
+
+#ifndef QT_NO_COMPRESS
+QByteArray qUncompress(const uchar* data, int nbytes)
+{
+ if (!data) {
+ qWarning("qUncompress: Data is null");
+ return QByteArray();
+ }
+ if (nbytes <= 4) {
+ if (nbytes < 4 || (data[0]!=0 || data[1]!=0 || data[2]!=0 || data[3]!=0))
+ qWarning("qUncompress: Input data is corrupted");
+ return QByteArray();
+ }
+ ulong expectedSize = (data[0] << 24) | (data[1] << 16) |
+ (data[2] << 8) | (data[3] );
+ ulong len = qMax(expectedSize, 1ul);
+ QScopedPointer<QByteArray::Data, QScopedPointerPodDeleter> d;
+
+ forever {
+ ulong alloc = len;
+ if (len >= (1 << 31) - sizeof(QByteArray::Data)) {
+ //QByteArray does not support that huge size anyway.
+ qWarning("qUncompress: Input data is corrupted");
+ return QByteArray();
+ }
+ QByteArray::Data *p = static_cast<QByteArray::Data *>(qRealloc(d.data(), sizeof(QByteArray::Data) + alloc));
+ if (!p) {
+ // we are not allowed to crash here when compiling with QT_NO_EXCEPTIONS
+ qWarning("qUncompress: could not allocate enough memory to uncompress data");
+ return QByteArray();
+ }
+ d.take(); // realloc was successful
+ d.reset(p);
+
+ int res = ::uncompress((uchar*)d->array, &len,
+ (uchar*)data+4, nbytes-4);
+
+ switch (res) {
+ case Z_OK:
+ if (len != alloc) {
+ if (len >= (1 << 31) - sizeof(QByteArray::Data)) {
+ //QByteArray does not support that huge size anyway.
+ qWarning("qUncompress: Input data is corrupted");
+ return QByteArray();
+ }
+ QByteArray::Data *p = static_cast<QByteArray::Data *>(qRealloc(d.data(), sizeof(QByteArray::Data) + len));
+ if (!p) {
+ // we are not allowed to crash here when compiling with QT_NO_EXCEPTIONS
+ qWarning("qUncompress: could not allocate enough memory to uncompress data");
+ return QByteArray();
+ }
+ d.take(); // realloc was successful
+ d.reset(p);
+ }
+ d->ref = 1;
+ d->alloc = d->size = len;
+ d->data = d->array;
+ d->array[len] = 0;
+
+ return QByteArray(d.take(), 0, 0);
+
+ case Z_MEM_ERROR:
+ qWarning("qUncompress: Z_MEM_ERROR: Not enough memory");
+ return QByteArray();
+
+ case Z_BUF_ERROR:
+ len *= 2;
+ continue;
+
+ case Z_DATA_ERROR:
+ qWarning("qUncompress: Z_DATA_ERROR: Input data is corrupted");
+ return QByteArray();
+ }
+ }
+}
+#endif
+
+static inline bool qIsUpper(char c)
+{
+ return c >= 'A' && c <= 'Z';
+}
+
+static inline char qToLower(char c)
+{
+ if (c >= 'A' && c <= 'Z')
+ return c - 'A' + 'a';
+ else
+ return c;
+}
+
+QByteArray::Data QByteArray::shared_null = {Q_BASIC_ATOMIC_INITIALIZER(1),
+ 0, 0, shared_null.array, {0} };
+QByteArray::Data QByteArray::shared_empty = { Q_BASIC_ATOMIC_INITIALIZER(1),
+ 0, 0, shared_empty.array, {0} };
+
+/*!
+ \class QByteArray
+ \brief The QByteArray class provides an array of bytes.
+
+ \ingroup tools
+ \ingroup shared
+ \ingroup string-processing
+
+ \reentrant
+
+ QByteArray can be used to store both raw bytes (including '\\0's)
+ and traditional 8-bit '\\0'-terminated strings. Using QByteArray
+ is much more convenient than using \c{const char *}. Behind the
+ scenes, it always ensures that the data is followed by a '\\0'
+ terminator, and uses \l{implicit sharing} (copy-on-write) to
+ reduce memory usage and avoid needless copying of data.
+
+ In addition to QByteArray, Qt also provides the QString class to
+ store string data. For most purposes, QString is the class you
+ want to use. It stores 16-bit Unicode characters, making it easy
+ to store non-ASCII/non-Latin-1 characters in your application.
+ Furthermore, QString is used throughout in the Qt API. The two
+ main cases where QByteArray is appropriate are when you need to
+ store raw binary data, and when memory conservation is critical
+ (e.g., with Qt for Embedded Linux).
+
+ One way to initialize a QByteArray is simply to pass a \c{const
+ char *} to its constructor. For example, the following code
+ creates a byte array of size 5 containing the data "Hello":
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 0
+
+ Although the size() is 5, the byte array also maintains an extra
+ '\\0' character at the end so that if a function is used that
+ asks for a pointer to the underlying data (e.g. a call to
+ data()), the data pointed to is guaranteed to be
+ '\\0'-terminated.
+
+ QByteArray makes a deep copy of the \c{const char *} data, so you
+ can modify it later without experiencing side effects. (If for
+ performance reasons you don't want to take a deep copy of the
+ character data, use QByteArray::fromRawData() instead.)
+
+ Another approach is to set the size of the array using resize()
+ and to initialize the data byte per byte. QByteArray uses 0-based
+ indexes, just like C++ arrays. To access the byte at a particular
+ index position, you can use operator[](). On non-const byte
+ arrays, operator[]() returns a reference to a byte that can be
+ used on the left side of an assignment. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 1
+
+ For read-only access, an alternative syntax is to use at():
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 2
+
+ at() can be faster than operator[](), because it never causes a
+ \l{deep copy} to occur.
+
+ To extract many bytes at a time, use left(), right(), or mid().
+
+ A QByteArray can embed '\\0' bytes. The size() function always
+ returns the size of the whole array, including embedded '\\0'
+ bytes. If you want to obtain the length of the data up to and
+ excluding the first '\\0' character, call qstrlen() on the byte
+ array.
+
+ After a call to resize(), newly allocated bytes have undefined
+ values. To set all the bytes to a particular value, call fill().
+
+ To obtain a pointer to the actual character data, call data() or
+ constData(). These functions return a pointer to the beginning of the data.
+ The pointer is guaranteed to remain valid until a non-const function is
+ called on the QByteArray. It is also guaranteed that the data ends with a
+ '\\0' byte unless the QByteArray was created from a \l{fromRawData()}{raw
+ data}. This '\\0' byte is automatically provided by QByteArray and is not
+ counted in size().
+
+ QByteArray provides the following basic functions for modifying
+ the byte data: append(), prepend(), insert(), replace(), and
+ remove(). For example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 3
+
+ The replace() and remove() functions' first two arguments are the
+ position from which to start erasing and the number of bytes that
+ should be erased.
+
+ When you append() data to a non-empty array, the array will be
+ reallocated and the new data copied to it. You can avoid this
+ behavior by calling reserve(), which preallocates a certain amount
+ of memory. You can also call capacity() to find out how much
+ memory QByteArray actually allocated. Data appended to an empty
+ array is not copied.
+
+ A frequent requirement is to remove whitespace characters from a
+ byte array ('\\n', '\\t', ' ', etc.). If you want to remove
+ whitespace from both ends of a QByteArray, use trimmed(). If you
+ want to remove whitespace from both ends and replace multiple
+ consecutive whitespaces with a single space character within the
+ byte array, use simplified().
+
+ If you want to find all occurrences of a particular character or
+ substring in a QByteArray, use indexOf() or lastIndexOf(). The
+ former searches forward starting from a given index position, the
+ latter searches backward. Both return the index position of the
+ character or substring if they find it; otherwise, they return -1.
+ For example, here's a typical loop that finds all occurrences of a
+ particular substring:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 4
+
+ If you simply want to check whether a QByteArray contains a
+ particular character or substring, use contains(). If you want to
+ find out how many times a particular character or substring
+ occurs in the byte array, use count(). If you want to replace all
+ occurrences of a particular value with another, use one of the
+ two-parameter replace() overloads.
+
+ QByteArrays can be compared using overloaded operators such as
+ operator<(), operator<=(), operator==(), operator>=(), and so on.
+ The comparison is based exclusively on the numeric values
+ of the characters and is very fast, but is not what a human would
+ expect. QString::localeAwareCompare() is a better choice for
+ sorting user-interface strings.
+
+ For historical reasons, QByteArray distinguishes between a null
+ byte array and an empty byte array. A \e null byte array is a
+ byte array that is initialized using QByteArray's default
+ constructor or by passing (const char *)0 to the constructor. An
+ \e empty byte array is any byte array with size 0. A null byte
+ array is always empty, but an empty byte array isn't necessarily
+ null:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 5
+
+ All functions except isNull() treat null byte arrays the same as
+ empty byte arrays. For example, data() returns a pointer to a
+ '\\0' character for a null byte array (\e not a null pointer),
+ and QByteArray() compares equal to QByteArray(""). We recommend
+ that you always use isEmpty() and avoid isNull().
+
+ \section1 Notes on Locale
+
+ \section2 Number-String Conversions
+
+ Functions that perform conversions between numeric data types and
+ strings are performed in the C locale, irrespective of the user's
+ locale settings. Use QString to perform locale-aware conversions
+ between numbers and strings.
+
+ \section2 8-bit Character Comparisons
+
+ In QByteArray, the notion of uppercase and lowercase and of which
+ character is greater than or less than another character is
+ locale dependent. This affects functions that support a case
+ insensitive option or that compare or lowercase or uppercase
+ their arguments. Case insensitive operations and comparisons will
+ be accurate if both strings contain only ASCII characters. (If \c
+ $LC_CTYPE is set, most Unix systems do "the right thing".)
+ Functions that this affects include contains(), indexOf(),
+ lastIndexOf(), operator<(), operator<=(), operator>(),
+ operator>=(), toLower() and toUpper().
+
+ This issue does not apply to QStrings since they represent
+ characters using Unicode.
+
+ \sa QString, QBitArray
+*/
+
+/*! \fn QByteArray::iterator QByteArray::begin()
+
+ \internal
+*/
+
+/*! \fn QByteArray::const_iterator QByteArray::begin() const
+
+ \internal
+*/
+
+/*! \fn QByteArray::const_iterator QByteArray::constBegin() const
+
+ \internal
+*/
+
+/*! \fn QByteArray::iterator QByteArray::end()
+
+ \internal
+*/
+
+/*! \fn QByteArray::const_iterator QByteArray::end() const
+
+ \internal
+*/
+
+/*! \fn QByteArray::const_iterator QByteArray::constEnd() const
+
+ \internal
+*/
+
+/*! \fn void QByteArray::push_back(const QByteArray &other)
+
+ This function is provided for STL compatibility. It is equivalent
+ to append(\a other).
+*/
+
+/*! \fn void QByteArray::push_back(const char *str)
+
+ \overload
+
+ Same as append(\a str).
+*/
+
+/*! \fn void QByteArray::push_back(char ch)
+
+ \overload
+
+ Same as append(\a ch).
+*/
+
+/*! \fn void QByteArray::push_front(const QByteArray &other)
+
+ This function is provided for STL compatibility. It is equivalent
+ to prepend(\a other).
+*/
+
+/*! \fn void QByteArray::push_front(const char *str)
+
+ \overload
+
+ Same as prepend(\a str).
+*/
+
+/*! \fn void QByteArray::push_front(char ch)
+
+ \overload
+
+ Same as prepend(\a ch).
+*/
+
+/*! \fn QByteArray::QByteArray(const QByteArray &other)
+
+ Constructs a copy of \a other.
+
+ This operation takes \l{constant time}, because QByteArray is
+ \l{implicitly shared}. This makes returning a QByteArray from a
+ function very fast. If a shared instance is modified, it will be
+ copied (copy-on-write), taking \l{linear time}.
+
+ \sa operator=()
+*/
+
+/*! \fn QByteArray::~QByteArray()
+ Destroys the byte array.
+*/
+
+/*!
+ Assigns \a other to this byte array and returns a reference to
+ this byte array.
+*/
+QByteArray &QByteArray::operator=(const QByteArray & other)
+{
+ other.d->ref.ref();
+ if (!d->ref.deref())
+ qFree(d);
+ d = other.d;
+ return *this;
+}
+
+
+/*!
+ \overload
+
+ Assigns \a str to this byte array.
+*/
+
+QByteArray &QByteArray::operator=(const char *str)
+{
+ Data *x;
+ if (!str) {
+ x = &shared_null;
+ } else if (!*str) {
+ x = &shared_empty;
+ } else {
+ int len = qstrlen(str);
+ if (d->ref != 1 || len > d->alloc || (len < d->size && len < d->alloc >> 1))
+ realloc(len);
+ x = d;
+ memcpy(x->data, str, len + 1); // include null terminator
+ x->size = len;
+ }
+ x->ref.ref();
+ if (!d->ref.deref())
+ qFree(d);
+ d = x;
+ return *this;
+}
+
+/*! \fn void QByteArray::swap(QByteArray &other)
+ \since 4.8
+
+ Swaps byte array \a other with this byte array. This operation is very
+ fast and never fails.
+*/
+
+/*! \fn int QByteArray::size() const
+
+ Returns the number of bytes in this byte array.
+
+ The last byte in the byte array is at position size() - 1. In addition,
+ QByteArray ensures that the byte at position size() is always '\\0', so
+ that you can use the return value of data() and constData() as arguments to
+ functions that expect '\\0'-terminated strings. If the QByteArray object
+ was created from a \l{fromRawData()}{raw data} that didn't include the
+ trailing null-termination character then QByteArray doesn't add it
+ automaticall unless the \l{deep copy} is created.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 6
+
+ \sa isEmpty(), resize()
+*/
+
+/*! \fn bool QByteArray::isEmpty() const
+
+ Returns true if the byte array has size 0; otherwise returns false.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 7
+
+ \sa size()
+*/
+
+/*! \fn int QByteArray::capacity() const
+
+ Returns the maximum number of bytes that can be stored in the
+ byte array without forcing a reallocation.
+
+ The sole purpose of this function is to provide a means of fine
+ tuning QByteArray's memory usage. In general, you will rarely
+ ever need to call this function. If you want to know how many
+ bytes are in the byte array, call size().
+
+ \sa reserve(), squeeze()
+*/
+
+/*! \fn void QByteArray::reserve(int size)
+
+ Attempts to allocate memory for at least \a size bytes. If you
+ know in advance how large the byte array will be, you can call
+ this function, and if you call resize() often you are likely to
+ get better performance. If \a size is an underestimate, the worst
+ that will happen is that the QByteArray will be a bit slower.
+
+ The sole purpose of this function is to provide a means of fine
+ tuning QByteArray's memory usage. In general, you will rarely
+ ever need to call this function. If you want to change the size
+ of the byte array, call resize().
+
+ \sa squeeze(), capacity()
+*/
+
+/*! \fn void QByteArray::squeeze()
+
+ Releases any memory not required to store the array's data.
+
+ The sole purpose of this function is to provide a means of fine
+ tuning QByteArray's memory usage. In general, you will rarely
+ ever need to call this function.
+
+ \sa reserve(), capacity()
+*/
+
+/*! \fn QByteArray::operator const char *() const
+ \fn QByteArray::operator const void *() const
+
+ Returns a pointer to the data stored in the byte array. The
+ pointer can be used to access the bytes that compose the array.
+ The data is '\\0'-terminated. The pointer remains valid as long
+ as the array isn't reallocated or destroyed.
+
+ This operator is mostly useful to pass a byte array to a function
+ that accepts a \c{const char *}.
+
+ You can disable this operator by defining \c
+ QT_NO_CAST_FROM_BYTEARRAY when you compile your applications.
+
+ Note: A QByteArray can store any byte values including '\\0's,
+ but most functions that take \c{char *} arguments assume that the
+ data ends at the first '\\0' they encounter.
+
+ \sa constData()
+*/
+
+/*!
+ \macro QT_NO_CAST_FROM_BYTEARRAY
+ \relates QByteArray
+
+ Disables automatic conversions from QByteArray to
+ const char * or const void *.
+
+ \sa QT_NO_CAST_TO_ASCII, QT_NO_CAST_FROM_ASCII
+*/
+
+/*! \fn char *QByteArray::data()
+
+ Returns a pointer to the data stored in the byte array. The
+ pointer can be used to access and modify the bytes that compose
+ the array. The data is '\\0'-terminated, i.e. the number of
+ bytes in the returned character string is size() + 1 for the
+ '\\0' terminator.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 8
+
+ The pointer remains valid as long as the byte array isn't
+ reallocated or destroyed. For read-only access, constData() is
+ faster because it never causes a \l{deep copy} to occur.
+
+ This function is mostly useful to pass a byte array to a function
+ that accepts a \c{const char *}.
+
+ The following example makes a copy of the char* returned by
+ data(), but it will corrupt the heap and cause a crash because it
+ does not allocate a byte for the '\\0' at the end:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 46
+
+ This one allocates the correct amount of space:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 47
+
+ Note: A QByteArray can store any byte values including '\\0's,
+ but most functions that take \c{char *} arguments assume that the
+ data ends at the first '\\0' they encounter.
+
+ \sa constData(), operator[]()
+*/
+
+/*! \fn const char *QByteArray::data() const
+
+ \overload
+*/
+
+/*! \fn const char *QByteArray::constData() const
+
+ Returns a pointer to the data stored in the byte array. The pointer can be
+ used to access the bytes that compose the array. The data is
+ '\\0'-terminated unless the QByteArray object was created from raw data.
+ The pointer remains valid as long as the byte array isn't reallocated or
+ destroyed.
+
+ This function is mostly useful to pass a byte array to a function
+ that accepts a \c{const char *}.
+
+ Note: A QByteArray can store any byte values including '\\0's,
+ but most functions that take \c{char *} arguments assume that the
+ data ends at the first '\\0' they encounter.
+
+ \sa data(), operator[](), fromRawData()
+*/
+
+/*! \fn void QByteArray::detach()
+
+ \internal
+*/
+
+/*! \fn bool QByteArray::isDetached() const
+
+ \internal
+*/
+
+/*! \fn bool QByteArray::isSharedWith(const QByteArray &other) const
+
+ \internal
+*/
+
+/*! \fn char QByteArray::at(int i) const
+
+ Returns the character at index position \a i in the byte array.
+
+ \a i must be a valid index position in the byte array (i.e., 0 <=
+ \a i < size()).
+
+ \sa operator[]()
+*/
+
+/*! \fn QByteRef QByteArray::operator[](int i)
+
+ Returns the byte at index position \a i as a modifiable reference.
+
+ If an assignment is made beyond the end of the byte array, the
+ array is extended with resize() before the assignment takes
+ place.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 9
+
+ The return value is of type QByteRef, a helper class for
+ QByteArray. When you get an object of type QByteRef, you can use
+ it as if it were a char &. If you assign to it, the assignment
+ will apply to the character in the QByteArray from which you got
+ the reference.
+
+ \sa at()
+*/
+
+/*! \fn char QByteArray::operator[](int i) const
+
+ \overload
+
+ Same as at(\a i).
+*/
+
+/*! \fn QByteRef QByteArray::operator[](uint i)
+
+ \overload
+*/
+
+/*! \fn char QByteArray::operator[](uint i) const
+
+ \overload
+*/
+
+/*! \fn QBool QByteArray::contains(const QByteArray &ba) const
+
+ Returns true if the byte array contains an occurrence of the byte
+ array \a ba; otherwise returns false.
+
+ \sa indexOf(), count()
+*/
+
+/*! \fn QBool QByteArray::contains(const char *str) const
+
+ \overload
+
+ Returns true if the byte array contains the string \a str;
+ otherwise returns false.
+*/
+
+/*! \fn QBool QByteArray::contains(char ch) const
+
+ \overload
+
+ Returns true if the byte array contains the character \a ch;
+ otherwise returns false.
+*/
+
+/*!
+
+ Truncates the byte array at index position \a pos.
+
+ If \a pos is beyond the end of the array, nothing happens.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 10
+
+ \sa chop(), resize(), left()
+*/
+void QByteArray::truncate(int pos)
+{
+ if (pos < d->size)
+ resize(pos);
+}
+
+/*!
+
+ Removes \a n bytes from the end of the byte array.
+
+ If \a n is greater than size(), the result is an empty byte
+ array.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 11
+
+ \sa truncate(), resize(), left()
+*/
+
+void QByteArray::chop(int n)
+{
+ if (n > 0)
+ resize(d->size - n);
+}
+
+
+/*! \fn QByteArray &QByteArray::operator+=(const QByteArray &ba)
+
+ Appends the byte array \a ba onto the end of this byte array and
+ returns a reference to this byte array.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 12
+
+ Note: QByteArray is an \l{implicitly shared} class. Consequently,
+ if \e this is an empty QByteArray, then \e this will just share
+ the data held in \a ba. In this case, no copying of data is done,
+ taking \l{constant time}. If a shared instance is modified, it will
+ be copied (copy-on-write), taking \l{linear time}.
+
+ If \e this is not an empty QByteArray, a deep copy of the data is
+ performed, taking \l{linear time}.
+
+ This operation typically does not suffer from allocation overhead,
+ because QByteArray preallocates extra space at the end of the data
+ so that it may grow without reallocating for each append operation.
+
+ \sa append(), prepend()
+*/
+
+/*! \fn QByteArray &QByteArray::operator+=(const QString &str)
+
+ \overload
+
+ Appends the string \a str onto the end of this byte array and
+ returns a reference to this byte array. The Unicode data is
+ converted into 8-bit characters using QString::toAscii().
+
+ If the QString contains non-ASCII Unicode characters, using this
+ operator can lead to loss of information. You can disable this
+ operator by defining \c QT_NO_CAST_TO_ASCII when you compile your
+ applications. You then need to call QString::toAscii() (or
+ QString::toLatin1() or QString::toUtf8() or QString::toLocal8Bit())
+ explicitly if you want to convert the data to \c{const char *}.
+*/
+
+/*! \fn QByteArray &QByteArray::operator+=(const char *str)
+
+ \overload
+
+ Appends the string \a str onto the end of this byte array and
+ returns a reference to this byte array.
+*/
+
+/*! \fn QByteArray &QByteArray::operator+=(char ch)
+
+ \overload
+
+ Appends the character \a ch onto the end of this byte array and
+ returns a reference to this byte array.
+*/
+
+/*! \fn int QByteArray::length() const
+
+ Same as size().
+*/
+
+/*! \fn bool QByteArray::isNull() const
+
+ Returns true if this byte array is null; otherwise returns false.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 13
+
+ Qt makes a distinction between null byte arrays and empty byte
+ arrays for historical reasons. For most applications, what
+ matters is whether or not a byte array contains any data,
+ and this can be determined using isEmpty().
+
+ \sa isEmpty()
+*/
+
+/*! \fn QByteArray::QByteArray()
+
+ Constructs an empty byte array.
+
+ \sa isEmpty()
+*/
+
+/*! \fn QByteArray::QByteArray(const char *str)
+
+ Constructs a byte array initialized with the string \a str.
+
+ QByteArray makes a deep copy of the string data.
+*/
+
+QByteArray::QByteArray(const char *str)
+{
+ if (!str) {
+ d = &shared_null;
+ } else if (!*str) {
+ d = &shared_empty;
+ } else {
+ int len = qstrlen(str);
+ d = static_cast<Data *>(qMalloc(sizeof(Data)+len));
+ Q_CHECK_PTR(d);
+ d->ref = 0;;
+ d->alloc = d->size = len;
+ d->data = d->array;
+ memcpy(d->array, str, len+1); // include null terminator
+ }
+ d->ref.ref();
+}
+
+/*!
+ Constructs a byte array containing the first \a size bytes of
+ array \a data.
+
+ If \a data is 0, a null byte array is constructed.
+
+ QByteArray makes a deep copy of the string data.
+
+ \sa fromRawData()
+*/
+
+QByteArray::QByteArray(const char *data, int size)
+{
+ if (!data) {
+ d = &shared_null;
+ } else if (size <= 0) {
+ d = &shared_empty;
+ } else {
+ d = static_cast<Data *>(qMalloc(sizeof(Data) + size));
+ Q_CHECK_PTR(d);
+ d->ref = 0;
+ d->alloc = d->size = size;
+ d->data = d->array;
+ memcpy(d->array, data, size);
+ d->array[size] = '\0';
+ }
+ d->ref.ref();
+}
+
+/*!
+ Constructs a byte array of size \a size with every byte set to
+ character \a ch.
+
+ \sa fill()
+*/
+
+QByteArray::QByteArray(int size, char ch)
+{
+ if (size <= 0) {
+ d = &shared_null;
+ } else {
+ d = static_cast<Data *>(qMalloc(sizeof(Data)+size));
+ Q_CHECK_PTR(d);
+ d->ref = 0;
+ d->alloc = d->size = size;
+ d->data = d->array;
+ d->array[size] = '\0';
+ memset(d->array, ch, size);
+ }
+ d->ref.ref();
+}
+
+/*!
+ \internal
+
+ Constructs a byte array of size \a size with uninitialized contents.
+*/
+
+QByteArray::QByteArray(int size, Qt::Initialization)
+{
+ d = static_cast<Data *>(qMalloc(sizeof(Data)+size));
+ Q_CHECK_PTR(d);
+ d->ref = 1;
+ d->alloc = d->size = size;
+ d->data = d->array;
+ d->array[size] = '\0';
+}
+
+/*!
+ Sets the size of the byte array to \a size bytes.
+
+ If \a size is greater than the current size, the byte array is
+ extended to make it \a size bytes with the extra bytes added to
+ the end. The new bytes are uninitialized.
+
+ If \a size is less than the current size, bytes are removed from
+ the end.
+
+ \sa size(), truncate()
+*/
+
+void QByteArray::resize(int size)
+{
+ if (size <= 0) {
+ Data *x = &shared_empty;
+ x->ref.ref();
+ if (!d->ref.deref())
+ qFree(d);
+ d = x;
+ } else if (d == &shared_null) {
+ //
+ // Optimize the idiom:
+ // QByteArray a;
+ // a.resize(sz);
+ // ...
+ // which is used in place of the Qt 3 idiom:
+ // QByteArray a(sz);
+ //
+ Data *x = static_cast<Data *>(qMalloc(sizeof(Data)+size));
+ Q_CHECK_PTR(x);
+ x->ref = 1;
+ x->alloc = x->size = size;
+ x->data = x->array;
+ x->array[size] = '\0';
+ (void) d->ref.deref(); // cannot be 0, x points to shared_null
+ d = x;
+ } else {
+ if (d->ref != 1 || size > d->alloc || (size < d->size && size < d->alloc >> 1))
+ realloc(qAllocMore(size, sizeof(Data)));
+ if (d->alloc >= size) {
+ d->size = size;
+ if (d->data == d->array) {
+ d->array[size] = '\0';
+ }
+ }
+ }
+}
+
+/*!
+ Sets every byte in the byte array to character \a ch. If \a size
+ is different from -1 (the default), the byte array is resized to
+ size \a size beforehand.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 14
+
+ \sa resize()
+*/
+
+QByteArray &QByteArray::fill(char ch, int size)
+{
+ resize(size < 0 ? d->size : size);
+ if (d->size)
+ memset(d->data, ch, d->size);
+ return *this;
+}
+
+void QByteArray::realloc(int alloc)
+{
+ if (d->ref != 1 || d->data != d->array) {
+ Data *x = static_cast<Data *>(qMalloc(sizeof(Data) + alloc));
+ Q_CHECK_PTR(x);
+ x->size = qMin(alloc, d->size);
+ ::memcpy(x->array, d->data, x->size);
+ x->array[x->size] = '\0';
+ x->ref = 1;
+ x->alloc = alloc;
+ x->data = x->array;
+ if (!d->ref.deref())
+ qFree(d);
+ d = x;
+ } else {
+ Data *x = static_cast<Data *>(qRealloc(d, sizeof(Data) + alloc));
+ Q_CHECK_PTR(x);
+ x->alloc = alloc;
+ x->data = x->array;
+ d = x;
+ }
+}
+
+void QByteArray::expand(int i)
+{
+ resize(qMax(i + 1, d->size));
+}
+
+/*!
+ \internal
+ Return a QByteArray that is sure to be NUL-terminated.
+
+ By default, all QByteArray have an extra NUL at the end,
+ guaranteeing that assumption. However, if QByteArray::fromRawData
+ is used, then the NUL is there only if the user put it there. We
+ can't be sure.
+*/
+QByteArray QByteArray::nulTerminated() const
+{
+ // is this fromRawData?
+ if (d->data == d->array)
+ return *this; // no, then we're sure we're zero terminated
+
+ QByteArray copy(*this);
+ copy.detach();
+ return copy;
+}
+
+/*!
+ Prepends the byte array \a ba to this byte array and returns a
+ reference to this byte array.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 15
+
+ This is the same as insert(0, \a ba).
+
+ Note: QByteArray is an \l{implicitly shared} class. Consequently,
+ if \e this is an empty QByteArray, then \e this will just share
+ the data held in \a ba. In this case, no copying of data is done,
+ taking \l{constant time}. If a shared instance is modified, it will
+ be copied (copy-on-write), taking \l{linear time}.
+
+ If \e this is not an empty QByteArray, a deep copy of the data is
+ performed, taking \l{linear time}.
+
+ \sa append(), insert()
+*/
+
+QByteArray &QByteArray::prepend(const QByteArray &ba)
+{
+ if ((d == &shared_null || d == &shared_empty) && !IS_RAW_DATA(ba.d)) {
+ *this = ba;
+ } else if (ba.d != &shared_null) {
+ QByteArray tmp = *this;
+ *this = ba;
+ append(tmp);
+ }
+ return *this;
+}
+
+/*!
+ \overload
+
+ Prepends the string \a str to this byte array.
+*/
+
+QByteArray &QByteArray::prepend(const char *str)
+{
+ return prepend(str, qstrlen(str));
+}
+
+/*!
+ \overload
+ \since 4.6
+
+ Prepends \a len bytes of the string \a str to this byte array.
+*/
+
+QByteArray &QByteArray::prepend(const char *str, int len)
+{
+ if (str) {
+ if (d->ref != 1 || d->size + len > d->alloc)
+ realloc(qAllocMore(d->size + len, sizeof(Data)));
+ memmove(d->data+len, d->data, d->size);
+ memcpy(d->data, str, len);
+ d->size += len;
+ d->data[d->size] = '\0';
+ }
+ return *this;
+}
+
+/*!
+ \overload
+
+ Prepends the character \a ch to this byte array.
+*/
+
+QByteArray &QByteArray::prepend(char ch)
+{
+ if (d->ref != 1 || d->size + 1 > d->alloc)
+ realloc(qAllocMore(d->size + 1, sizeof(Data)));
+ memmove(d->data+1, d->data, d->size);
+ d->data[0] = ch;
+ ++d->size;
+ d->data[d->size] = '\0';
+ return *this;
+}
+
+/*!
+ Appends the byte array \a ba onto the end of this byte array.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 16
+
+ This is the same as insert(size(), \a ba).
+
+ Note: QByteArray is an \l{implicitly shared} class. Consequently,
+ if \e this is an empty QByteArray, then \e this will just share
+ the data held in \a ba. In this case, no copying of data is done,
+ taking \l{constant time}. If a shared instance is modified, it will
+ be copied (copy-on-write), taking \l{linear time}.
+
+ If \e this is not an empty QByteArray, a deep copy of the data is
+ performed, taking \l{linear time}.
+
+ This operation typically does not suffer from allocation overhead,
+ because QByteArray preallocates extra space at the end of the data
+ so that it may grow without reallocating for each append operation.
+
+ \sa operator+=(), prepend(), insert()
+*/
+
+QByteArray &QByteArray::append(const QByteArray &ba)
+{
+ if ((d == &shared_null || d == &shared_empty) && !IS_RAW_DATA(ba.d)) {
+ *this = ba;
+ } else if (ba.d != &shared_null) {
+ if (d->ref != 1 || d->size + ba.d->size > d->alloc)
+ realloc(qAllocMore(d->size + ba.d->size, sizeof(Data)));
+ memcpy(d->data + d->size, ba.d->data, ba.d->size);
+ d->size += ba.d->size;
+ d->data[d->size] = '\0';
+ }
+ return *this;
+}
+
+/*! \fn QByteArray &QByteArray::append(const QString &str)
+
+ \overload
+
+ Appends the string \a str to this byte array. The Unicode data is
+ converted into 8-bit characters using QString::toAscii().
+
+ If the QString contains non-ASCII Unicode characters, using this
+ function can lead to loss of information. You can disable this
+ function by defining \c QT_NO_CAST_TO_ASCII when you compile your
+ applications. You then need to call QString::toAscii() (or
+ QString::toLatin1() or QString::toUtf8() or QString::toLocal8Bit())
+ explicitly if you want to convert the data to \c{const char *}.
+*/
+
+/*!
+ \overload
+
+ Appends the string \a str to this byte array.
+*/
+
+QByteArray& QByteArray::append(const char *str)
+{
+ if (str) {
+ int len = qstrlen(str);
+ if (d->ref != 1 || d->size + len > d->alloc)
+ realloc(qAllocMore(d->size + len, sizeof(Data)));
+ memcpy(d->data + d->size, str, len + 1); // include null terminator
+ d->size += len;
+ }
+ return *this;
+}
+
+/*!
+ \overload append()
+
+ Appends the first \a len characters of the string \a str to this byte
+ array and returns a reference to this byte array.
+
+ If \a len is negative, the length of the string will be determined
+ automatically using qstrlen(). If \a len is zero or \a str is
+ null, nothing is appended to the byte array. Ensure that \a len is
+ \e not longer than \a str.
+*/
+
+QByteArray &QByteArray::append(const char *str, int len)
+{
+ if (len < 0)
+ len = qstrlen(str);
+ if (str && len) {
+ if (d->ref != 1 || d->size + len > d->alloc)
+ realloc(qAllocMore(d->size + len, sizeof(Data)));
+ memcpy(d->data + d->size, str, len); // include null terminator
+ d->size += len;
+ d->data[d->size] = '\0';
+ }
+ return *this;
+}
+
+/*!
+ \overload
+
+ Appends the character \a ch to this byte array.
+*/
+
+QByteArray& QByteArray::append(char ch)
+{
+ if (d->ref != 1 || d->size + 1 > d->alloc)
+ realloc(qAllocMore(d->size + 1, sizeof(Data)));
+ d->data[d->size++] = ch;
+ d->data[d->size] = '\0';
+ return *this;
+}
+
+/*!
+ \internal
+ Inserts \a len bytes from the array \a arr at position \a pos and returns a
+ reference the modified byte array.
+*/
+static inline QByteArray &qbytearray_insert(QByteArray *ba,
+ int pos, const char *arr, int len)
+{
+ Q_ASSERT(pos >= 0);
+
+ if (pos < 0 || len <= 0 || arr == 0)
+ return *ba;
+
+ int oldsize = ba->size();
+ ba->resize(qMax(pos, oldsize) + len);
+ char *dst = ba->data();
+ if (pos > oldsize)
+ ::memset(dst + oldsize, 0x20, pos - oldsize);
+ else
+ ::memmove(dst + pos + len, dst + pos, oldsize - pos);
+ memcpy(dst + pos, arr, len);
+ return *ba;
+}
+
+/*!
+ Inserts the byte array \a ba at index position \a i and returns a
+ reference to this byte array.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 17
+
+ \sa append(), prepend(), replace(), remove()
+*/
+
+QByteArray &QByteArray::insert(int i, const QByteArray &ba)
+{
+ QByteArray copy(ba);
+ return qbytearray_insert(this, i, copy.d->data, copy.d->size);
+}
+
+/*!
+ \fn QByteArray &QByteArray::insert(int i, const QString &str)
+
+ \overload
+
+ Inserts the string \a str at index position \a i in the byte
+ array. The Unicode data is converted into 8-bit characters using
+ QString::toAscii().
+
+ If \a i is greater than size(), the array is first extended using
+ resize().
+
+ If the QString contains non-ASCII Unicode characters, using this
+ function can lead to loss of information. You can disable this
+ function by defining \c QT_NO_CAST_TO_ASCII when you compile your
+ applications. You then need to call QString::toAscii() (or
+ QString::toLatin1() or QString::toUtf8() or QString::toLocal8Bit())
+ explicitly if you want to convert the data to \c{const char *}.
+*/
+
+/*!
+ \overload
+
+ Inserts the string \a str at position \a i in the byte array.
+
+ If \a i is greater than size(), the array is first extended using
+ resize().
+*/
+
+QByteArray &QByteArray::insert(int i, const char *str)
+{
+ return qbytearray_insert(this, i, str, qstrlen(str));
+}
+
+/*!
+ \overload
+ \since 4.6
+
+ Inserts \a len bytes of the string \a str at position
+ \a i in the byte array.
+
+ If \a i is greater than size(), the array is first extended using
+ resize().
+*/
+
+QByteArray &QByteArray::insert(int i, const char *str, int len)
+{
+ return qbytearray_insert(this, i, str, len);
+}
+
+/*!
+ \overload
+
+ Inserts character \a ch at index position \a i in the byte array.
+ If \a i is greater than size(), the array is first extended using
+ resize().
+*/
+
+QByteArray &QByteArray::insert(int i, char ch)
+{
+ return qbytearray_insert(this, i, &ch, 1);
+}
+
+/*!
+ Removes \a len bytes from the array, starting at index position \a
+ pos, and returns a reference to the array.
+
+ If \a pos is out of range, nothing happens. If \a pos is valid,
+ but \a pos + \a len is larger than the size of the array, the
+ array is truncated at position \a pos.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 18
+
+ \sa insert(), replace()
+*/
+
+QByteArray &QByteArray::remove(int pos, int len)
+{
+ if (len <= 0 || pos >= d->size || pos < 0)
+ return *this;
+ detach();
+ if (pos + len >= d->size) {
+ resize(pos);
+ } else {
+ memmove(d->data + pos, d->data + pos + len, d->size - pos - len);
+ resize(d->size - len);
+ }
+ return *this;
+}
+
+/*!
+ Replaces \a len bytes from index position \a pos with the byte
+ array \a after, and returns a reference to this byte array.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 19
+
+ \sa insert(), remove()
+*/
+
+QByteArray &QByteArray::replace(int pos, int len, const QByteArray &after)
+{
+ if (len == after.d->size && (pos + len <= d->size)) {
+ detach();
+ memmove(d->data + pos, after.d->data, len*sizeof(char));
+ return *this;
+ } else {
+ QByteArray copy(after);
+ // ### optimize me
+ remove(pos, len);
+ return insert(pos, copy);
+ }
+}
+
+/*! \fn QByteArray &QByteArray::replace(int pos, int len, const char *after)
+
+ \overload
+
+ Replaces \a len bytes from index position \a pos with the zero terminated
+ string \a after.
+
+ Notice: this can change the length of the byte array.
+*/
+QByteArray &QByteArray::replace(int pos, int len, const char *after)
+{
+ return replace(pos,len,after,qstrlen(after));
+}
+
+/*! \fn QByteArray &QByteArray::replace(int pos, int len, const char *after, int alen)
+
+ \overload
+
+ Replaces \a len bytes from index position \a pos with \a alen bytes
+ from the string \a after. \a after is allowed to have '\0' characters.
+
+ \since 4.7
+*/
+QByteArray &QByteArray::replace(int pos, int len, const char *after, int alen)
+{
+ if (len == alen && (pos + len <= d->size)) {
+ detach();
+ memcpy(d->data + pos, after, len*sizeof(char));
+ return *this;
+ } else {
+ remove(pos, len);
+ return qbytearray_insert(this, pos, after, alen);
+ }
+}
+
+// ### optimize all other replace method, by offering
+// QByteArray::replace(const char *before, int blen, const char *after, int alen)
+
+/*!
+ \overload
+
+ Replaces every occurrence of the byte array \a before with the
+ byte array \a after.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 20
+*/
+
+QByteArray &QByteArray::replace(const QByteArray &before, const QByteArray &after)
+{
+ if (isNull() || before.d == after.d)
+ return *this;
+
+ QByteArray aft = after;
+ if (after.d == d)
+ aft.detach();
+
+ return replace(before.constData(), before.size(), aft.constData(), aft.size());
+}
+
+/*!
+ \fn QByteArray &QByteArray::replace(const char *before, const QByteArray &after)
+ \overload
+
+ Replaces every occurrence of the string \a before with the
+ byte array \a after.
+*/
+
+QByteArray &QByteArray::replace(const char *c, const QByteArray &after)
+{
+ QByteArray aft = after;
+ if (after.d == d)
+ aft.detach();
+
+ return replace(c, qstrlen(c), aft.constData(), aft.size());
+}
+
+/*!
+ \fn QByteArray &QByteArray::replace(const char *before, int bsize, const char *after, int asize)
+ \overload
+
+ Replaces every occurrence of the string \a before with the string \a after.
+ Since the sizes of the strings are given by \a bsize and \a asize, they
+ may contain zero characters and do not need to be zero-terminated.
+*/
+
+QByteArray &QByteArray::replace(const char *before, int bsize, const char *after, int asize)
+{
+ if (isNull() || (before == after && bsize == asize))
+ return *this;
+
+ // protect against before or after being part of this
+ const char *a = after;
+ const char *b = before;
+ if (after >= d->data && after < d->data + d->size) {
+ char *copy = (char *)malloc(asize);
+ Q_CHECK_PTR(copy);
+ memcpy(copy, after, asize);
+ a = copy;
+ }
+ if (before >= d->data && before < d->data + d->size) {
+ char *copy = (char *)malloc(bsize);
+ Q_CHECK_PTR(copy);
+ memcpy(copy, before, bsize);
+ b = copy;
+ }
+
+ QByteArrayMatcher matcher(before, bsize);
+ int index = 0;
+ int len = d->size;
+ char *d = data();
+
+ if (bsize == asize) {
+ if (bsize) {
+ while ((index = matcher.indexIn(*this, index)) != -1) {
+ memcpy(d + index, after, asize);
+ index += bsize;
+ }
+ }
+ } else if (asize < bsize) {
+ uint to = 0;
+ uint movestart = 0;
+ uint num = 0;
+ while ((index = matcher.indexIn(*this, index)) != -1) {
+ if (num) {
+ int msize = index - movestart;
+ if (msize > 0) {
+ memmove(d + to, d + movestart, msize);
+ to += msize;
+ }
+ } else {
+ to = index;
+ }
+ if (asize) {
+ memcpy(d + to, after, asize);
+ to += asize;
+ }
+ index += bsize;
+ movestart = index;
+ num++;
+ }
+ if (num) {
+ int msize = len - movestart;
+ if (msize > 0)
+ memmove(d + to, d + movestart, msize);
+ resize(len - num*(bsize-asize));
+ }
+ } else {
+ // the most complex case. We don't want to lose performance by doing repeated
+ // copies and reallocs of the string.
+ while (index != -1) {
+ uint indices[4096];
+ uint pos = 0;
+ while(pos < 4095) {
+ index = matcher.indexIn(*this, index);
+ if (index == -1)
+ break;
+ indices[pos++] = index;
+ index += bsize;
+ // avoid infinite loop
+ if (!bsize)
+ index++;
+ }
+ if (!pos)
+ break;
+
+ // we have a table of replacement positions, use them for fast replacing
+ int adjust = pos*(asize-bsize);
+ // index has to be adjusted in case we get back into the loop above.
+ if (index != -1)
+ index += adjust;
+ int newlen = len + adjust;
+ int moveend = len;
+ if (newlen > len) {
+ resize(newlen);
+ len = newlen;
+ }
+ d = this->d->data;
+
+ while(pos) {
+ pos--;
+ int movestart = indices[pos] + bsize;
+ int insertstart = indices[pos] + pos*(asize-bsize);
+ int moveto = insertstart + asize;
+ memmove(d + moveto, d + movestart, (moveend - movestart));
+ if (asize)
+ memcpy(d + insertstart, after, asize);
+ moveend = movestart - bsize;
+ }
+ }
+ }
+
+ if (a != after)
+ ::free((char *)a);
+ if (b != before)
+ ::free((char *)b);
+
+
+ return *this;
+}
+
+
+/*!
+ \fn QByteArray &QByteArray::replace(const QByteArray &before, const char *after)
+ \overload
+
+ Replaces every occurrence of the byte array \a before with the
+ string \a after.
+*/
+
+/*! \fn QByteArray &QByteArray::replace(const QString &before, const QByteArray &after)
+
+ \overload
+
+ Replaces every occurrence of the string \a before with the byte
+ array \a after. The Unicode data is converted into 8-bit
+ characters using QString::toAscii().
+
+ If the QString contains non-ASCII Unicode characters, using this
+ function can lead to loss of information. You can disable this
+ function by defining \c QT_NO_CAST_TO_ASCII when you compile your
+ applications. You then need to call QString::toAscii() (or
+ QString::toLatin1() or QString::toUtf8() or QString::toLocal8Bit())
+ explicitly if you want to convert the data to \c{const char *}.
+*/
+
+/*! \fn QByteArray &QByteArray::replace(const QString &before, const char *after)
+ \overload
+
+ Replaces every occurrence of the string \a before with the string
+ \a after.
+*/
+
+/*! \fn QByteArray &QByteArray::replace(const char *before, const char *after)
+
+ \overload
+
+ Replaces every occurrence of the string \a before with the string
+ \a after.
+*/
+
+/*!
+ \overload
+
+ Replaces every occurrence of the character \a before with the
+ byte array \a after.
+*/
+
+QByteArray &QByteArray::replace(char before, const QByteArray &after)
+{
+ char b[2] = { before, '\0' };
+ QByteArray cb = fromRawData(b, 1);
+ return replace(cb, after);
+}
+
+/*! \fn QByteArray &QByteArray::replace(char before, const QString &after)
+
+ \overload
+
+ Replaces every occurrence of the character \a before with the
+ string \a after. The Unicode data is converted into 8-bit
+ characters using QString::toAscii().
+
+ If the QString contains non-ASCII Unicode characters, using this
+ function can lead to loss of information. You can disable this
+ function by defining \c QT_NO_CAST_TO_ASCII when you compile your
+ applications. You then need to call QString::toAscii() (or
+ QString::toLatin1() or QString::toUtf8() or QString::toLocal8Bit())
+ explicitly if you want to convert the data to \c{const char *}.
+*/
+
+/*! \fn QByteArray &QByteArray::replace(char before, const char *after)
+
+ \overload
+
+ Replaces every occurrence of the character \a before with the
+ string \a after.
+*/
+
+/*!
+ \overload
+
+ Replaces every occurrence of the character \a before with the
+ character \a after.
+*/
+
+QByteArray &QByteArray::replace(char before, char after)
+{
+ if (d->size) {
+ char *i = data();
+ char *e = i + d->size;
+ for (; i != e; ++i)
+ if (*i == before)
+ * i = after;
+ }
+ return *this;
+}
+
+/*!
+ Splits the byte array into subarrays wherever \a sep occurs, and
+ returns the list of those arrays. If \a sep does not match
+ anywhere in the byte array, split() returns a single-element list
+ containing this byte array.
+*/
+
+QList<QByteArray> QByteArray::split(char sep) const
+{
+ QList<QByteArray> list;
+ int start = 0;
+ int end;
+ while ((end = indexOf(sep, start)) != -1) {
+ list.append(mid(start, end - start));
+ start = end + 1;
+ }
+ list.append(mid(start));
+ return list;
+}
+
+/*!
+ \since 4.5
+
+ Returns a copy of this byte array repeated the specified number of \a times.
+
+ If \a times is less than 1, an empty byte array is returned.
+
+ Example:
+
+ \code
+ QByteArray ba("ab");
+ ba.repeated(4); // returns "abababab"
+ \endcode
+*/
+QByteArray QByteArray::repeated(int times) const
+{
+ if (d->size == 0)
+ return *this;
+
+ if (times <= 1) {
+ if (times == 1)
+ return *this;
+ return QByteArray();
+ }
+
+ const int resultSize = times * d->size;
+
+ QByteArray result;
+ result.reserve(resultSize);
+ if (result.d->alloc != resultSize)
+ return QByteArray(); // not enough memory
+
+ memcpy(result.d->data, d->data, d->size);
+
+ int sizeSoFar = d->size;
+ char *end = result.d->data + sizeSoFar;
+
+ const int halfResultSize = resultSize >> 1;
+ while (sizeSoFar <= halfResultSize) {
+ memcpy(end, result.d->data, sizeSoFar);
+ end += sizeSoFar;
+ sizeSoFar <<= 1;
+ }
+ memcpy(end, result.d->data, resultSize - sizeSoFar);
+ result.d->data[resultSize] = '\0';
+ result.d->size = resultSize;
+ return result;
+}
+
+#define REHASH(a) \
+ if (ol_minus_1 < sizeof(uint) * CHAR_BIT) \
+ hashHaystack -= (a) << ol_minus_1; \
+ hashHaystack <<= 1
+
+/*!
+ Returns the index position of the first occurrence of the byte
+ array \a ba in this byte array, searching forward from index
+ position \a from. Returns -1 if \a ba could not be found.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 21
+
+ \sa lastIndexOf(), contains(), count()
+*/
+
+int QByteArray::indexOf(const QByteArray &ba, int from) const
+{
+ const int ol = ba.d->size;
+ if (ol == 0)
+ return from;
+ if (ol == 1)
+ return indexOf(*ba.d->data, from);
+
+ const int l = d->size;
+ if (from > d->size || ol + from > l)
+ return -1;
+
+ return qFindByteArray(d->data, d->size, from, ba.d->data, ol);
+}
+
+/*! \fn int QByteArray::indexOf(const QString &str, int from) const
+
+ \overload
+
+ Returns the index position of the first occurrence of the string
+ \a str in the byte array, searching forward from index position
+ \a from. Returns -1 if \a str could not be found.
+
+ The Unicode data is converted into 8-bit characters using
+ QString::toAscii().
+
+ If the QString contains non-ASCII Unicode characters, using this
+ function can lead to loss of information. You can disable this
+ function by defining \c QT_NO_CAST_TO_ASCII when you compile your
+ applications. You then need to call QString::toAscii() (or
+ QString::toLatin1() or QString::toUtf8() or QString::toLocal8Bit())
+ explicitly if you want to convert the data to \c{const char *}.
+*/
+
+/*! \fn int QByteArray::indexOf(const char *str, int from) const
+
+ \overload
+
+ Returns the index position of the first occurrence of the string
+ \a str in the byte array, searching forward from index position \a
+ from. Returns -1 if \a str could not be found.
+*/
+int QByteArray::indexOf(const char *c, int from) const
+{
+ const int ol = qstrlen(c);
+ if (ol == 1)
+ return indexOf(*c, from);
+
+ const int l = d->size;
+ if (from > d->size || ol + from > l)
+ return -1;
+ if (ol == 0)
+ return from;
+
+ return qFindByteArray(d->data, d->size, from, c, ol);
+}
+
+/*!
+ \overload
+
+ Returns the index position of the first occurrence of the
+ character \a ch in the byte array, searching forward from index
+ position \a from. Returns -1 if \a ch could not be found.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 22
+
+ \sa lastIndexOf(), contains()
+*/
+
+int QByteArray::indexOf(char ch, int from) const
+{
+ if (from < 0)
+ from = qMax(from + d->size, 0);
+ if (from < d->size) {
+ const char *n = d->data + from - 1;
+ const char *e = d->data + d->size;
+ while (++n != e)
+ if (*n == ch)
+ return n - d->data;
+ }
+ return -1;
+}
+
+
+static int lastIndexOfHelper(const char *haystack, int l, const char *needle, int ol, int from)
+{
+ int delta = l - ol;
+ if (from < 0)
+ from = delta;
+ if (from < 0 || from > l)
+ return -1;
+ if (from > delta)
+ from = delta;
+
+ const char *end = haystack;
+ haystack += from;
+ const uint ol_minus_1 = ol - 1;
+ const char *n = needle + ol_minus_1;
+ const char *h = haystack + ol_minus_1;
+ uint hashNeedle = 0, hashHaystack = 0;
+ int idx;
+ for (idx = 0; idx < ol; ++idx) {
+ hashNeedle = ((hashNeedle<<1) + *(n-idx));
+ hashHaystack = ((hashHaystack<<1) + *(h-idx));
+ }
+ hashHaystack -= *haystack;
+ while (haystack >= end) {
+ hashHaystack += *haystack;
+ if (hashHaystack == hashNeedle && memcmp(needle, haystack, ol) == 0)
+ return haystack - end;
+ --haystack;
+ REHASH(*(haystack + ol));
+ }
+ return -1;
+
+}
+
+/*!
+ \fn int QByteArray::lastIndexOf(const QByteArray &ba, int from) const
+
+ Returns the index position of the last occurrence of the byte
+ array \a ba in this byte array, searching backward from index
+ position \a from. If \a from is -1 (the default), the search
+ starts at the last byte. Returns -1 if \a ba could not be found.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 23
+
+ \sa indexOf(), contains(), count()
+*/
+
+int QByteArray::lastIndexOf(const QByteArray &ba, int from) const
+{
+ const int ol = ba.d->size;
+ if (ol == 1)
+ return lastIndexOf(*ba.d->data, from);
+
+ return lastIndexOfHelper(d->data, d->size, ba.d->data, ol, from);
+}
+
+/*! \fn int QByteArray::lastIndexOf(const QString &str, int from) const
+
+ \overload
+
+ Returns the index position of the last occurrence of the string \a
+ str in the byte array, searching backward from index position \a
+ from. If \a from is -1 (the default), the search starts at the
+ last (size() - 1) byte. Returns -1 if \a str could not be found.
+
+ The Unicode data is converted into 8-bit characters using
+ QString::toAscii().
+
+ If the QString contains non-ASCII Unicode characters, using this
+ function can lead to loss of information. You can disable this
+ function by defining \c QT_NO_CAST_TO_ASCII when you compile your
+ applications. You then need to call QString::toAscii() (or
+ QString::toLatin1() or QString::toUtf8() or QString::toLocal8Bit())
+ explicitly if you want to convert the data to \c{const char *}.
+*/
+
+/*! \fn int QByteArray::lastIndexOf(const char *str, int from) const
+ \overload
+
+ Returns the index position of the last occurrence of the string \a
+ str in the byte array, searching backward from index position \a
+ from. If \a from is -1 (the default), the search starts at the
+ last (size() - 1) byte. Returns -1 if \a str could not be found.
+*/
+int QByteArray::lastIndexOf(const char *str, int from) const
+{
+ const int ol = qstrlen(str);
+ if (ol == 1)
+ return lastIndexOf(*str, from);
+
+ return lastIndexOfHelper(d->data, d->size, str, ol, from);
+}
+
+/*!
+ \overload
+
+ Returns the index position of the last occurrence of character \a
+ ch in the byte array, searching backward from index position \a
+ from. If \a from is -1 (the default), the search starts at the
+ last (size() - 1) byte. Returns -1 if \a ch could not be found.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 24
+
+ \sa indexOf(), contains()
+*/
+
+int QByteArray::lastIndexOf(char ch, int from) const
+{
+ if (from < 0)
+ from += d->size;
+ else if (from > d->size)
+ from = d->size-1;
+ if (from >= 0) {
+ const char *b = d->data;
+ const char *n = d->data + from + 1;
+ while (n-- != b)
+ if (*n == ch)
+ return n - b;
+ }
+ return -1;
+}
+
+/*!
+ Returns the number of (potentially overlapping) occurrences of
+ byte array \a ba in this byte array.
+
+ \sa contains(), indexOf()
+*/
+
+int QByteArray::count(const QByteArray &ba) const
+{
+ int num = 0;
+ int i = -1;
+ if (d->size > 500 && ba.d->size > 5) {
+ QByteArrayMatcher matcher(ba);
+ while ((i = matcher.indexIn(*this, i + 1)) != -1)
+ ++num;
+ } else {
+ while ((i = indexOf(ba, i + 1)) != -1)
+ ++num;
+ }
+ return num;
+}
+
+/*!
+ \overload
+
+ Returns the number of (potentially overlapping) occurrences of
+ string \a str in the byte array.
+*/
+
+int QByteArray::count(const char *str) const
+{
+ return count(fromRawData(str, qstrlen(str)));
+}
+
+/*!
+ \overload
+
+ Returns the number of occurrences of character \a ch in the byte
+ array.
+
+ \sa contains(), indexOf()
+*/
+
+int QByteArray::count(char ch) const
+{
+ int num = 0;
+ const char *i = d->data + d->size;
+ const char *b = d->data;
+ while (i != b)
+ if (*--i == ch)
+ ++num;
+ return num;
+}
+
+/*! \fn int QByteArray::count() const
+
+ \overload
+
+ Same as size().
+*/
+
+/*!
+ Returns true if this byte array starts with byte array \a ba;
+ otherwise returns false.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 25
+
+ \sa endsWith(), left()
+*/
+bool QByteArray::startsWith(const QByteArray &ba) const
+{
+ if (d == ba.d || ba.d->size == 0)
+ return true;
+ if (d->size < ba.d->size)
+ return false;
+ return memcmp(d->data, ba.d->data, ba.d->size) == 0;
+}
+
+/*! \overload
+
+ Returns true if this byte array starts with string \a str;
+ otherwise returns false.
+*/
+bool QByteArray::startsWith(const char *str) const
+{
+ if (!str || !*str)
+ return true;
+ int len = qstrlen(str);
+ if (d->size < len)
+ return false;
+ return qstrncmp(d->data, str, len) == 0;
+}
+
+/*! \overload
+
+ Returns true if this byte array starts with character \a ch;
+ otherwise returns false.
+*/
+bool QByteArray::startsWith(char ch) const
+{
+ if (d->size == 0)
+ return false;
+ return d->data[0] == ch;
+}
+
+/*!
+ Returns true if this byte array ends with byte array \a ba;
+ otherwise returns false.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 26
+
+ \sa startsWith(), right()
+*/
+bool QByteArray::endsWith(const QByteArray &ba) const
+{
+ if (d == ba.d || ba.d->size == 0)
+ return true;
+ if (d->size < ba.d->size)
+ return false;
+ return memcmp(d->data + d->size - ba.d->size, ba.d->data, ba.d->size) == 0;
+}
+
+/*! \overload
+
+ Returns true if this byte array ends with string \a str; otherwise
+ returns false.
+*/
+bool QByteArray::endsWith(const char *str) const
+{
+ if (!str || !*str)
+ return true;
+ int len = qstrlen(str);
+ if (d->size < len)
+ return false;
+ return qstrncmp(d->data + d->size - len, str, len) == 0;
+}
+
+/*! \overload
+
+ Returns true if this byte array ends with character \a ch;
+ otherwise returns false.
+*/
+bool QByteArray::endsWith(char ch) const
+{
+ if (d->size == 0)
+ return false;
+ return d->data[d->size - 1] == ch;
+}
+
+/*!
+ Returns a byte array that contains the leftmost \a len bytes of
+ this byte array.
+
+ The entire byte array is returned if \a len is greater than
+ size().
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 27
+
+ \sa right(), mid(), startsWith(), truncate()
+*/
+
+QByteArray QByteArray::left(int len) const
+{
+ if (len >= d->size)
+ return *this;
+ if (len < 0)
+ len = 0;
+ return QByteArray(d->data, len);
+}
+
+/*!
+ Returns a byte array that contains the rightmost \a len bytes of
+ this byte array.
+
+ The entire byte array is returned if \a len is greater than
+ size().
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 28
+
+ \sa endsWith(), left(), mid()
+*/
+
+QByteArray QByteArray::right(int len) const
+{
+ if (len >= d->size)
+ return *this;
+ if (len < 0)
+ len = 0;
+ return QByteArray(d->data + d->size - len, len);
+}
+
+/*!
+ Returns a byte array containing \a len bytes from this byte array,
+ starting at position \a pos.
+
+ If \a len is -1 (the default), or \a pos + \a len >= size(),
+ returns a byte array containing all bytes starting at position \a
+ pos until the end of the byte array.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 29
+
+ \sa left(), right()
+*/
+
+QByteArray QByteArray::mid(int pos, int len) const
+{
+ if (d == &shared_null || d == &shared_empty || pos >= d->size)
+ return QByteArray();
+ if (len < 0)
+ len = d->size - pos;
+ if (pos < 0) {
+ len += pos;
+ pos = 0;
+ }
+ if (len + pos > d->size)
+ len = d->size - pos;
+ if (pos == 0 && len == d->size)
+ return *this;
+ return QByteArray(d->data + pos, len);
+}
+
+/*!
+ Returns a lowercase copy of the byte array. The bytearray is
+ interpreted as a Latin-1 encoded string.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 30
+
+ \sa toUpper(), {8-bit Character Comparisons}
+*/
+QByteArray QByteArray::toLower() const
+{
+ QByteArray s(*this);
+ register uchar *p = reinterpret_cast<uchar *>(s.data());
+ if (p) {
+ while (*p) {
+ *p = QChar::toLower((ushort)*p);
+ p++;
+ }
+ }
+ return s;
+}
+
+/*!
+ Returns an uppercase copy of the byte array. The bytearray is
+ interpreted as a Latin-1 encoded string.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 31
+
+ \sa toLower(), {8-bit Character Comparisons}
+*/
+
+QByteArray QByteArray::toUpper() const
+{
+ QByteArray s(*this);
+ register uchar *p = reinterpret_cast<uchar *>(s.data());
+ if (p) {
+ while (*p) {
+ *p = QChar::toUpper((ushort)*p);
+ p++;
+ }
+ }
+ return s;
+}
+
+/*! \fn void QByteArray::clear()
+
+ Clears the contents of the byte array and makes it empty.
+
+ \sa resize(), isEmpty()
+*/
+
+void QByteArray::clear()
+{
+ if (!d->ref.deref())
+ qFree(d);
+ d = &shared_null;
+ d->ref.ref();
+}
+
+#if !defined(QT_NO_DATASTREAM) || (defined(QT_BOOTSTRAPPED) && !defined(QT_BUILD_QMAKE))
+
+/*! \relates QByteArray
+
+ Writes byte array \a ba to the stream \a out and returns a reference
+ to the stream.
+
+ \sa {Serializing Qt Data Types}
+*/
+
+QDataStream &operator<<(QDataStream &out, const QByteArray &ba)
+{
+ if (ba.isNull() && out.version() >= 6) {
+ out << (quint32)0xffffffff;
+ return out;
+ }
+ return out.writeBytes(ba, ba.size());
+}
+
+/*! \relates QByteArray
+
+ Reads a byte array into \a ba from the stream \a in and returns a
+ reference to the stream.
+
+ \sa {Serializing Qt Data Types}
+*/
+
+QDataStream &operator>>(QDataStream &in, QByteArray &ba)
+{
+ ba.clear();
+ quint32 len;
+ in >> len;
+ if (len == 0xffffffff)
+ return in;
+
+ const quint32 Step = 1024 * 1024;
+ quint32 allocated = 0;
+
+ do {
+ int blockSize = qMin(Step, len - allocated);
+ ba.resize(allocated + blockSize);
+ if (in.readRawData(ba.data() + allocated, blockSize) != blockSize) {
+ ba.clear();
+ in.setStatus(QDataStream::ReadPastEnd);
+ return in;
+ }
+ allocated += blockSize;
+ } while (allocated < len);
+
+ return in;
+}
+#endif // QT_NO_DATASTREAM
+
+/*! \fn bool QByteArray::operator==(const QString &str) const
+
+ Returns true if this byte array is equal to string \a str;
+ otherwise returns false.
+
+ The Unicode data is converted into 8-bit characters using
+ QString::toAscii().
+
+ The comparison is case sensitive.
+
+ You can disable this operator by defining \c
+ QT_NO_CAST_FROM_ASCII when you compile your applications. You
+ then need to call QString::fromAscii(), QString::fromLatin1(),
+ QString::fromUtf8(), or QString::fromLocal8Bit() explicitly if
+ you want to convert the byte array to a QString before doing the
+ comparison.
+*/
+
+/*! \fn bool QByteArray::operator!=(const QString &str) const
+
+ Returns true if this byte array is not equal to string \a str;
+ otherwise returns false.
+
+ The Unicode data is converted into 8-bit characters using
+ QString::toAscii().
+
+ The comparison is case sensitive.
+
+ You can disable this operator by defining \c
+ QT_NO_CAST_FROM_ASCII when you compile your applications. You
+ then need to call QString::fromAscii(), QString::fromLatin1(),
+ QString::fromUtf8(), or QString::fromLocal8Bit() explicitly if
+ you want to convert the byte array to a QString before doing the
+ comparison.
+*/
+
+/*! \fn bool QByteArray::operator<(const QString &str) const
+
+ Returns true if this byte array is lexically less than string \a
+ str; otherwise returns false.
+
+ The Unicode data is converted into 8-bit characters using
+ QString::toAscii().
+
+ The comparison is case sensitive.
+
+ You can disable this operator by defining \c
+ QT_NO_CAST_FROM_ASCII when you compile your applications. You
+ then need to call QString::fromAscii(), QString::fromLatin1(),
+ QString::fromUtf8(), or QString::fromLocal8Bit() explicitly if
+ you want to convert the byte array to a QString before doing the
+ comparison.
+*/
+
+/*! \fn bool QByteArray::operator>(const QString &str) const
+
+ Returns true if this byte array is lexically greater than string
+ \a str; otherwise returns false.
+
+ The Unicode data is converted into 8-bit characters using
+ QString::toAscii().
+
+ The comparison is case sensitive.
+
+ You can disable this operator by defining \c
+ QT_NO_CAST_FROM_ASCII when you compile your applications. You
+ then need to call QString::fromAscii(), QString::fromLatin1(),
+ QString::fromUtf8(), or QString::fromLocal8Bit() explicitly if
+ you want to convert the byte array to a QString before doing the
+ comparison.
+*/
+
+/*! \fn bool QByteArray::operator<=(const QString &str) const
+
+ Returns true if this byte array is lexically less than or equal
+ to string \a str; otherwise returns false.
+
+ The Unicode data is converted into 8-bit characters using
+ QString::toAscii().
+
+ The comparison is case sensitive.
+
+ You can disable this operator by defining \c
+ QT_NO_CAST_FROM_ASCII when you compile your applications. You
+ then need to call QString::fromAscii(), QString::fromLatin1(),
+ QString::fromUtf8(), or QString::fromLocal8Bit() explicitly if
+ you want to convert the byte array to a QString before doing the
+ comparison.
+*/
+
+/*! \fn bool QByteArray::operator>=(const QString &str) const
+
+ Returns true if this byte array is greater than or equal to string
+ \a str; otherwise returns false.
+
+ The Unicode data is converted into 8-bit characters using
+ QString::toAscii().
+
+ The comparison is case sensitive.
+
+ You can disable this operator by defining \c
+ QT_NO_CAST_FROM_ASCII when you compile your applications. You
+ then need to call QString::fromAscii(), QString::fromLatin1(),
+ QString::fromUtf8(), or QString::fromLocal8Bit() explicitly if
+ you want to convert the byte array to a QString before doing the
+ comparison.
+*/
+
+/*! \fn bool operator==(const QByteArray &a1, const QByteArray &a2)
+ \relates QByteArray
+
+ \overload
+
+ Returns true if byte array \a a1 is equal to byte array \a a2;
+ otherwise returns false.
+*/
+
+/*! \fn bool operator==(const QByteArray &a1, const char *a2)
+ \relates QByteArray
+
+ \overload
+
+ Returns true if byte array \a a1 is equal to string \a a2;
+ otherwise returns false.
+*/
+
+/*! \fn bool operator==(const char *a1, const QByteArray &a2)
+ \relates QByteArray
+
+ \overload
+
+ Returns true if string \a a1 is equal to byte array \a a2;
+ otherwise returns false.
+*/
+
+/*! \fn bool operator!=(const QByteArray &a1, const QByteArray &a2)
+ \relates QByteArray
+
+ \overload
+
+ Returns true if byte array \a a1 is not equal to byte array \a a2;
+ otherwise returns false.
+*/
+
+/*! \fn bool operator!=(const QByteArray &a1, const char *a2)
+ \relates QByteArray
+
+ \overload
+
+ Returns true if byte array \a a1 is not equal to string \a a2;
+ otherwise returns false.
+*/
+
+/*! \fn bool operator!=(const char *a1, const QByteArray &a2)
+ \relates QByteArray
+
+ \overload
+
+ Returns true if string \a a1 is not equal to byte array \a a2;
+ otherwise returns false.
+*/
+
+/*! \fn bool operator<(const QByteArray &a1, const QByteArray &a2)
+ \relates QByteArray
+
+ \overload
+
+ Returns true if byte array \a a1 is lexically less than byte array
+ \a a2; otherwise returns false.
+*/
+
+/*! \fn inline bool operator<(const QByteArray &a1, const char *a2)
+ \relates QByteArray
+
+ \overload
+
+ Returns true if byte array \a a1 is lexically less than string
+ \a a2; otherwise returns false.
+*/
+
+/*! \fn bool operator<(const char *a1, const QByteArray &a2)
+ \relates QByteArray
+
+ \overload
+
+ Returns true if string \a a1 is lexically less than byte array
+ \a a2; otherwise returns false.
+*/
+
+/*! \fn bool operator<=(const QByteArray &a1, const QByteArray &a2)
+ \relates QByteArray
+
+ \overload
+
+ Returns true if byte array \a a1 is lexically less than or equal
+ to byte array \a a2; otherwise returns false.
+*/
+
+/*! \fn bool operator<=(const QByteArray &a1, const char *a2)
+ \relates QByteArray
+
+ \overload
+
+ Returns true if byte array \a a1 is lexically less than or equal
+ to string \a a2; otherwise returns false.
+*/
+
+/*! \fn bool operator<=(const char *a1, const QByteArray &a2)
+ \relates QByteArray
+
+ \overload
+
+ Returns true if string \a a1 is lexically less than or equal
+ to byte array \a a2; otherwise returns false.
+*/
+
+/*! \fn bool operator>(const QByteArray &a1, const QByteArray &a2)
+ \relates QByteArray
+
+ \overload
+
+ Returns true if byte array \a a1 is lexically greater than byte
+ array \a a2; otherwise returns false.
+*/
+
+/*! \fn bool operator>(const QByteArray &a1, const char *a2)
+ \relates QByteArray
+
+ \overload
+
+ Returns true if byte array \a a1 is lexically greater than string
+ \a a2; otherwise returns false.
+*/
+
+/*! \fn bool operator>(const char *a1, const QByteArray &a2)
+ \relates QByteArray
+
+ \overload
+
+ Returns true if string \a a1 is lexically greater than byte array
+ \a a2; otherwise returns false.
+*/
+
+/*! \fn bool operator>=(const QByteArray &a1, const QByteArray &a2)
+ \relates QByteArray
+
+ \overload
+
+ Returns true if byte array \a a1 is lexically greater than or
+ equal to byte array \a a2; otherwise returns false.
+*/
+
+/*! \fn bool operator>=(const QByteArray &a1, const char *a2)
+ \relates QByteArray
+
+ \overload
+
+ Returns true if byte array \a a1 is lexically greater than or
+ equal to string \a a2; otherwise returns false.
+*/
+
+/*! \fn bool operator>=(const char *a1, const QByteArray &a2)
+ \relates QByteArray
+
+ \overload
+
+ Returns true if string \a a1 is lexically greater than or
+ equal to byte array \a a2; otherwise returns false.
+*/
+
+/*! \fn const QByteArray operator+(const QByteArray &a1, const QByteArray &a2)
+ \relates QByteArray
+
+ Returns a byte array that is the result of concatenating byte
+ array \a a1 and byte array \a a2.
+
+ \sa QByteArray::operator+=()
+*/
+
+/*! \fn const QByteArray operator+(const QByteArray &a1, const char *a2)
+ \relates QByteArray
+
+ \overload
+
+ Returns a byte array that is the result of concatenating byte
+ array \a a1 and string \a a2.
+*/
+
+/*! \fn const QByteArray operator+(const QByteArray &a1, char a2)
+ \relates QByteArray
+
+ \overload
+
+ Returns a byte array that is the result of concatenating byte
+ array \a a1 and character \a a2.
+*/
+
+/*! \fn const QByteArray operator+(const char *a1, const QByteArray &a2)
+ \relates QByteArray
+
+ \overload
+
+ Returns a byte array that is the result of concatenating string
+ \a a1 and byte array \a a2.
+*/
+
+/*! \fn const QByteArray operator+(char a1, const QByteArray &a2)
+ \relates QByteArray
+
+ \overload
+
+ Returns a byte array that is the result of concatenating character
+ \a a1 and byte array \a a2.
+*/
+
+/*!
+ Returns a byte array that has whitespace removed from the start
+ and the end, and which has each sequence of internal whitespace
+ replaced with a single space.
+
+ Whitespace means any character for which the standard C++
+ isspace() function returns true. This includes the ASCII
+ characters '\\t', '\\n', '\\v', '\\f', '\\r', and ' '.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 32
+
+ \sa trimmed()
+*/
+QByteArray QByteArray::simplified() const
+{
+ if (d->size == 0)
+ return *this;
+ QByteArray result(d->size, Qt::Uninitialized);
+ const char *from = d->data;
+ const char *fromend = from + d->size;
+ int outc=0;
+ char *to = result.d->data;
+ for (;;) {
+ while (from!=fromend && isspace(uchar(*from)))
+ from++;
+ while (from!=fromend && !isspace(uchar(*from)))
+ to[outc++] = *from++;
+ if (from!=fromend)
+ to[outc++] = ' ';
+ else
+ break;
+ }
+ if (outc > 0 && to[outc-1] == ' ')
+ outc--;
+ result.resize(outc);
+ return result;
+}
+
+/*!
+ Returns a byte array that has whitespace removed from the start
+ and the end.
+
+ Whitespace means any character for which the standard C++
+ isspace() function returns true. This includes the ASCII
+ characters '\\t', '\\n', '\\v', '\\f', '\\r', and ' '.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 33
+
+ Unlike simplified(), trimmed() leaves internal whitespace alone.
+
+ \sa simplified()
+*/
+QByteArray QByteArray::trimmed() const
+{
+ if (d->size == 0)
+ return *this;
+ const char *s = d->data;
+ if (!isspace(uchar(*s)) && !isspace(uchar(s[d->size-1])))
+ return *this;
+ int start = 0;
+ int end = d->size - 1;
+ while (start<=end && isspace(uchar(s[start]))) // skip white space from start
+ start++;
+ if (start <= end) { // only white space
+ while (end && isspace(uchar(s[end]))) // skip white space from end
+ end--;
+ }
+ int l = end - start + 1;
+ if (l <= 0) {
+ shared_empty.ref.ref();
+ return QByteArray(&shared_empty, 0, 0);
+ }
+ return QByteArray(s+start, l);
+}
+
+/*!
+ Returns a byte array of size \a width that contains this byte
+ array padded by the \a fill character.
+
+ If \a truncate is false and the size() of the byte array is more
+ than \a width, then the returned byte array is a copy of this byte
+ array.
+
+ If \a truncate is true and the size() of the byte array is more
+ than \a width, then any bytes in a copy of the byte array
+ after position \a width are removed, and the copy is returned.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 34
+
+ \sa rightJustified()
+*/
+
+QByteArray QByteArray::leftJustified(int width, char fill, bool truncate) const
+{
+ QByteArray result;
+ int len = d->size;
+ int padlen = width - len;
+ if (padlen > 0) {
+ result.resize(len+padlen);
+ if (len)
+ memcpy(result.d->data, d->data, len);
+ memset(result.d->data+len, fill, padlen);
+ } else {
+ if (truncate)
+ result = left(width);
+ else
+ result = *this;
+ }
+ return result;
+}
+
+/*!
+ Returns a byte array of size \a width that contains the \a fill
+ character followed by this byte array.
+
+ If \a truncate is false and the size of the byte array is more
+ than \a width, then the returned byte array is a copy of this byte
+ array.
+
+ If \a truncate is true and the size of the byte array is more
+ than \a width, then the resulting byte array is truncated at
+ position \a width.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 35
+
+ \sa leftJustified()
+*/
+
+QByteArray QByteArray::rightJustified(int width, char fill, bool truncate) const
+{
+ QByteArray result;
+ int len = d->size;
+ int padlen = width - len;
+ if (padlen > 0) {
+ result.resize(len+padlen);
+ if (len)
+ memcpy(result.d->data+padlen, data(), len);
+ memset(result.d->data, fill, padlen);
+ } else {
+ if (truncate)
+ result = left(width);
+ else
+ result = *this;
+ }
+ return result;
+}
+
+bool QByteArray::isNull() const { return d == &shared_null; }
+
+
+/*!
+ Returns the byte array converted to a \c {long long} using base \a
+ base, which is 10 by default and must be between 2 and 36, or 0.
+
+ If \a base is 0, the base is determined automatically using the
+ following rules: If the byte array begins with "0x", it is assumed to
+ be hexadecimal; if it begins with "0", it is assumed to be octal;
+ otherwise it is assumed to be decimal.
+
+ Returns 0 if the conversion fails.
+
+ If \a ok is not 0: if a conversion error occurs, *\a{ok} is set to
+ false; otherwise *\a{ok} is set to true.
+
+ \note The conversion of the number is performed in the default C locale,
+ irrespective of the user's locale.
+
+ \sa number()
+*/
+
+qlonglong QByteArray::toLongLong(bool *ok, int base) const
+{
+#if defined(QT_CHECK_RANGE)
+ if (base != 0 && (base < 2 || base > 36)) {
+ qWarning("QByteArray::toLongLong: Invalid base %d", base);
+ base = 10;
+ }
+#endif
+
+ return QLocalePrivate::bytearrayToLongLong(nulTerminated().constData(), base, ok);
+}
+
+/*!
+ Returns the byte array converted to an \c {unsigned long long}
+ using base \a base, which is 10 by default and must be between 2
+ and 36, or 0.
+
+ If \a base is 0, the base is determined automatically using the
+ following rules: If the byte array begins with "0x", it is assumed to
+ be hexadecimal; if it begins with "0", it is assumed to be octal;
+ otherwise it is assumed to be decimal.
+
+ Returns 0 if the conversion fails.
+
+ If \a ok is not 0: if a conversion error occurs, *\a{ok} is set to
+ false; otherwise *\a{ok} is set to true.
+
+ \note The conversion of the number is performed in the default C locale,
+ irrespective of the user's locale.
+
+ \sa number()
+*/
+
+qulonglong QByteArray::toULongLong(bool *ok, int base) const
+{
+#if defined(QT_CHECK_RANGE)
+ if (base != 0 && (base < 2 || base > 36)) {
+ qWarning("QByteArray::toULongLong: Invalid base %d", base);
+ base = 10;
+ }
+#endif
+
+ return QLocalePrivate::bytearrayToUnsLongLong(nulTerminated().constData(), base, ok);
+}
+
+
+/*!
+ Returns the byte array converted to an \c int using base \a
+ base, which is 10 by default and must be between 2 and 36, or 0.
+
+ If \a base is 0, the base is determined automatically using the
+ following rules: If the byte array begins with "0x", it is assumed to
+ be hexadecimal; if it begins with "0", it is assumed to be octal;
+ otherwise it is assumed to be decimal.
+
+ Returns 0 if the conversion fails.
+
+ If \a ok is not 0: if a conversion error occurs, *\a{ok} is set to
+ false; otherwise *\a{ok} is set to true.
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 36
+
+ \note The conversion of the number is performed in the default C locale,
+ irrespective of the user's locale.
+
+ \sa number()
+*/
+
+int QByteArray::toInt(bool *ok, int base) const
+{
+ qlonglong v = toLongLong(ok, base);
+ if (v < INT_MIN || v > INT_MAX) {
+ if (ok)
+ *ok = false;
+ v = 0;
+ }
+ return int(v);
+}
+
+/*!
+ Returns the byte array converted to an \c {unsigned int} using base \a
+ base, which is 10 by default and must be between 2 and 36, or 0.
+
+ If \a base is 0, the base is determined automatically using the
+ following rules: If the byte array begins with "0x", it is assumed to
+ be hexadecimal; if it begins with "0", it is assumed to be octal;
+ otherwise it is assumed to be decimal.
+
+ Returns 0 if the conversion fails.
+
+ If \a ok is not 0: if a conversion error occurs, *\a{ok} is set to
+ false; otherwise *\a{ok} is set to true.
+
+ \note The conversion of the number is performed in the default C locale,
+ irrespective of the user's locale.
+
+ \sa number()
+*/
+
+uint QByteArray::toUInt(bool *ok, int base) const
+{
+ qulonglong v = toULongLong(ok, base);
+ if (v > UINT_MAX) {
+ if (ok)
+ *ok = false;
+ v = 0;
+ }
+ return uint(v);
+}
+
+/*!
+ \since 4.1
+
+ Returns the byte array converted to a \c long int using base \a
+ base, which is 10 by default and must be between 2 and 36, or 0.
+
+ If \a base is 0, the base is determined automatically using the
+ following rules: If the byte array begins with "0x", it is assumed to
+ be hexadecimal; if it begins with "0", it is assumed to be octal;
+ otherwise it is assumed to be decimal.
+
+ Returns 0 if the conversion fails.
+
+ If \a ok is not 0: if a conversion error occurs, *\a{ok} is set to
+ false; otherwise *\a{ok} is set to true.
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 37
+
+ \note The conversion of the number is performed in the default C locale,
+ irrespective of the user's locale.
+
+ \sa number()
+*/
+long QByteArray::toLong(bool *ok, int base) const
+{
+ qlonglong v = toLongLong(ok, base);
+ if (v < LONG_MIN || v > LONG_MAX) {
+ if (ok)
+ *ok = false;
+ v = 0;
+ }
+ return long(v);
+}
+
+/*!
+ \since 4.1
+
+ Returns the byte array converted to an \c {unsigned long int} using base \a
+ base, which is 10 by default and must be between 2 and 36, or 0.
+
+ If \a base is 0, the base is determined automatically using the
+ following rules: If the byte array begins with "0x", it is assumed to
+ be hexadecimal; if it begins with "0", it is assumed to be octal;
+ otherwise it is assumed to be decimal.
+
+ Returns 0 if the conversion fails.
+
+ If \a ok is not 0: if a conversion error occurs, *\a{ok} is set to
+ false; otherwise *\a{ok} is set to true.
+
+ \note The conversion of the number is performed in the default C locale,
+ irrespective of the user's locale.
+
+ \sa number()
+*/
+ulong QByteArray::toULong(bool *ok, int base) const
+{
+ qulonglong v = toULongLong(ok, base);
+ if (v > ULONG_MAX) {
+ if (ok)
+ *ok = false;
+ v = 0;
+ }
+ return ulong(v);
+}
+
+/*!
+ Returns the byte array converted to a \c short using base \a
+ base, which is 10 by default and must be between 2 and 36, or 0.
+
+ If \a base is 0, the base is determined automatically using the
+ following rules: If the byte array begins with "0x", it is assumed to
+ be hexadecimal; if it begins with "0", it is assumed to be octal;
+ otherwise it is assumed to be decimal.
+
+ Returns 0 if the conversion fails.
+
+ If \a ok is not 0: if a conversion error occurs, *\a{ok} is set to
+ false; otherwise *\a{ok} is set to true.
+
+ \note The conversion of the number is performed in the default C locale,
+ irrespective of the user's locale.
+
+ \sa number()
+*/
+
+short QByteArray::toShort(bool *ok, int base) const
+{
+ qlonglong v = toLongLong(ok, base);
+ if (v < SHRT_MIN || v > SHRT_MAX) {
+ if (ok)
+ *ok = false;
+ v = 0;
+ }
+ return short(v);
+}
+
+/*!
+ Returns the byte array converted to an \c {unsigned short} using base \a
+ base, which is 10 by default and must be between 2 and 36, or 0.
+
+ If \a base is 0, the base is determined automatically using the
+ following rules: If the byte array begins with "0x", it is assumed to
+ be hexadecimal; if it begins with "0", it is assumed to be octal;
+ otherwise it is assumed to be decimal.
+
+ Returns 0 if the conversion fails.
+
+ If \a ok is not 0: if a conversion error occurs, *\a{ok} is set to
+ false; otherwise *\a{ok} is set to true.
+
+ \note The conversion of the number is performed in the default C locale,
+ irrespective of the user's locale.
+
+ \sa number()
+*/
+
+ushort QByteArray::toUShort(bool *ok, int base) const
+{
+ qulonglong v = toULongLong(ok, base);
+ if (v > USHRT_MAX) {
+ if (ok)
+ *ok = false;
+ v = 0;
+ }
+ return ushort(v);
+}
+
+
+/*!
+ Returns the byte array converted to a \c double value.
+
+ Returns 0.0 if the conversion fails.
+
+ If \a ok is not 0: if a conversion error occurs, *\a{ok} is set to
+ false; otherwise *\a{ok} is set to true.
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 38
+
+ \note The conversion of the number is performed in the default C locale,
+ irrespective of the user's locale.
+
+ \sa number()
+*/
+
+double QByteArray::toDouble(bool *ok) const
+{
+ return QLocalePrivate::bytearrayToDouble(nulTerminated().constData(), ok);
+}
+
+/*!
+ Returns the byte array converted to a \c float value.
+
+ Returns 0.0 if the conversion fails.
+
+ If \a ok is not 0: if a conversion error occurs, *\a{ok} is set to
+ false; otherwise *\a{ok} is set to true.
+
+ \note The conversion of the number is performed in the default C locale,
+ irrespective of the user's locale.
+
+ \sa number()
+*/
+
+float QByteArray::toFloat(bool *ok) const
+{
+ return float(toDouble(ok));
+}
+
+/*!
+ Returns a copy of the byte array, encoded as Base64.
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 39
+
+ The algorithm used to encode Base64-encoded data is defined in \l{RFC 2045}.
+
+ \sa fromBase64()
+*/
+QByteArray QByteArray::toBase64() const
+{
+ const char alphabet[] = "ABCDEFGH" "IJKLMNOP" "QRSTUVWX" "YZabcdef"
+ "ghijklmn" "opqrstuv" "wxyz0123" "456789+/";
+ const char padchar = '=';
+ int padlen = 0;
+
+ QByteArray tmp((d->size * 4) / 3 + 3, Qt::Uninitialized);
+
+ int i = 0;
+ char *out = tmp.data();
+ while (i < d->size) {
+ int chunk = 0;
+ chunk |= int(uchar(d->data[i++])) << 16;
+ if (i == d->size) {
+ padlen = 2;
+ } else {
+ chunk |= int(uchar(d->data[i++])) << 8;
+ if (i == d->size) padlen = 1;
+ else chunk |= int(uchar(d->data[i++]));
+ }
+
+ int j = (chunk & 0x00fc0000) >> 18;
+ int k = (chunk & 0x0003f000) >> 12;
+ int l = (chunk & 0x00000fc0) >> 6;
+ int m = (chunk & 0x0000003f);
+ *out++ = alphabet[j];
+ *out++ = alphabet[k];
+ if (padlen > 1) *out++ = padchar;
+ else *out++ = alphabet[l];
+ if (padlen > 0) *out++ = padchar;
+ else *out++ = alphabet[m];
+ }
+
+ tmp.truncate(out - tmp.data());
+ return tmp;
+}
+
+/*!
+ \fn QByteArray &QByteArray::setNum(int n, int base)
+
+ Sets the byte array to the printed value of \a n in base \a base (10
+ by default) and returns a reference to the byte array. The \a base can
+ be any value between 2 and 36.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 40
+
+ \note The format of the number is not localized; the default C locale
+ is used irrespective of the user's locale.
+
+ \sa number(), toInt()
+*/
+
+/*!
+ \fn QByteArray &QByteArray::setNum(uint n, int base)
+ \overload
+
+ \sa toUInt()
+*/
+
+/*!
+ \fn QByteArray &QByteArray::setNum(short n, int base)
+ \overload
+
+ \sa toShort()
+*/
+
+/*!
+ \fn QByteArray &QByteArray::setNum(ushort n, int base)
+ \overload
+
+ \sa toUShort()
+*/
+
+/*!
+ \overload
+
+ \sa toLongLong()
+*/
+
+QByteArray &QByteArray::setNum(qlonglong n, int base)
+{
+#if defined(QT_CHECK_RANGE)
+ if (base < 2 || base > 36) {
+ qWarning("QByteArray::setNum: Invalid base %d", base);
+ base = 10;
+ }
+#endif
+ QLocale locale(QLocale::C);
+ *this = locale.d()->longLongToString(n, -1, base).toLatin1();
+ return *this;
+}
+
+/*!
+ \overload
+
+ \sa toULongLong()
+*/
+
+QByteArray &QByteArray::setNum(qulonglong n, int base)
+{
+#if defined(QT_CHECK_RANGE)
+ if (base < 2 || base > 36) {
+ qWarning("QByteArray::setNum: Invalid base %d", base);
+ base = 10;
+ }
+#endif
+ QLocale locale(QLocale::C);
+ *this = locale.d()->unsLongLongToString(n, -1, base).toLatin1();
+ return *this;
+}
+
+/*!
+ \overload
+
+ Sets the byte array to the printed value of \a n, formatted in format
+ \a f with precision \a prec, and returns a reference to the
+ byte array.
+
+ The format \a f can be any of the following:
+
+ \table
+ \header \i Format \i Meaning
+ \row \i \c e \i format as [-]9.9e[+|-]999
+ \row \i \c E \i format as [-]9.9E[+|-]999
+ \row \i \c f \i format as [-]9.9
+ \row \i \c g \i use \c e or \c f format, whichever is the most concise
+ \row \i \c G \i use \c E or \c f format, whichever is the most concise
+ \endtable
+
+ With 'e', 'E', and 'f', \a prec is the number of digits after the
+ decimal point. With 'g' and 'G', \a prec is the maximum number of
+ significant digits (trailing zeroes are omitted).
+
+ \note The format of the number is not localized; the default C locale
+ is used irrespective of the user's locale.
+
+ \sa toDouble()
+*/
+
+QByteArray &QByteArray::setNum(double n, char f, int prec)
+{
+ QLocalePrivate::DoubleForm form = QLocalePrivate::DFDecimal;
+ uint flags = 0;
+
+ if (qIsUpper(f))
+ flags = QLocalePrivate::CapitalEorX;
+ f = qToLower(f);
+
+ switch (f) {
+ case 'f':
+ form = QLocalePrivate::DFDecimal;
+ break;
+ case 'e':
+ form = QLocalePrivate::DFExponent;
+ break;
+ case 'g':
+ form = QLocalePrivate::DFSignificantDigits;
+ break;
+ default:
+#if defined(QT_CHECK_RANGE)
+ qWarning("QByteArray::setNum: Invalid format char '%c'", f);
+#endif
+ break;
+ }
+
+ QLocale locale(QLocale::C);
+ *this = locale.d()->doubleToString(n, prec, form, -1, flags).toLatin1();
+ return *this;
+}
+
+/*!
+ \fn QByteArray &QByteArray::setNum(float n, char f, int prec)
+ \overload
+
+ Sets the byte array to the printed value of \a n, formatted in format
+ \a f with precision \a prec, and returns a reference to the
+ byte array.
+
+ \note The format of the number is not localized; the default C locale
+ is used irrespective of the user's locale.
+
+ \sa toFloat()
+*/
+
+/*!
+ Returns a byte array containing the string equivalent of the
+ number \a n to base \a base (10 by default). The \a base can be
+ any value between 2 and 36.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 41
+
+ \note The format of the number is not localized; the default C locale
+ is used irrespective of the user's locale.
+
+ \sa setNum(), toInt()
+*/
+QByteArray QByteArray::number(int n, int base)
+{
+ QByteArray s;
+ s.setNum(n, base);
+ return s;
+}
+
+/*!
+ \overload
+
+ \sa toUInt()
+*/
+QByteArray QByteArray::number(uint n, int base)
+{
+ QByteArray s;
+ s.setNum(n, base);
+ return s;
+}
+
+/*!
+ \overload
+
+ \sa toLongLong()
+*/
+QByteArray QByteArray::number(qlonglong n, int base)
+{
+ QByteArray s;
+ s.setNum(n, base);
+ return s;
+}
+
+/*!
+ \overload
+
+ \sa toULongLong()
+*/
+QByteArray QByteArray::number(qulonglong n, int base)
+{
+ QByteArray s;
+ s.setNum(n, base);
+ return s;
+}
+
+/*!
+ \overload
+
+ Returns a byte array that contains the printed value of \a n,
+ formatted in format \a f with precision \a prec.
+
+ Argument \a n is formatted according to the \a f format specified,
+ which is \c g by default, and can be any of the following:
+
+ \table
+ \header \i Format \i Meaning
+ \row \i \c e \i format as [-]9.9e[+|-]999
+ \row \i \c E \i format as [-]9.9E[+|-]999
+ \row \i \c f \i format as [-]9.9
+ \row \i \c g \i use \c e or \c f format, whichever is the most concise
+ \row \i \c G \i use \c E or \c f format, whichever is the most concise
+ \endtable
+
+ With 'e', 'E', and 'f', \a prec is the number of digits after the
+ decimal point. With 'g' and 'G', \a prec is the maximum number of
+ significant digits (trailing zeroes are omitted).
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 42
+
+ \note The format of the number is not localized; the default C locale
+ is used irrespective of the user's locale.
+
+ \sa toDouble()
+*/
+QByteArray QByteArray::number(double n, char f, int prec)
+{
+ QByteArray s;
+ s.setNum(n, f, prec);
+ return s;
+}
+
+/*!
+ Constructs a QByteArray that uses the first \a size bytes of the
+ \a data array. The bytes are \e not copied. The QByteArray will
+ contain the \a data pointer. The caller guarantees that \a data
+ will not be deleted or modified as long as this QByteArray and any
+ copies of it exist that have not been modified. In other words,
+ because QByteArray is an \l{implicitly shared} class and the
+ instance returned by this function contains the \a data pointer,
+ the caller must not delete \a data or modify it directly as long
+ as the returned QByteArray and any copies exist. However,
+ QByteArray does not take ownership of \a data, so the QByteArray
+ destructor will never delete the raw \a data, even when the
+ last QByteArray referring to \a data is destroyed.
+
+ A subsequent attempt to modify the contents of the returned
+ QByteArray or any copy made from it will cause it to create a deep
+ copy of the \a data array before doing the modification. This
+ ensures that the raw \a data array itself will never be modified
+ by QByteArray.
+
+ Here is an example of how to read data using a QDataStream on raw
+ data in memory without copying the raw data into a QByteArray:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 43
+
+ \warning A byte array created with fromRawData() is \e not
+ null-terminated, unless the raw data contains a 0 character at
+ position \a size. While that does not matter for QDataStream or
+ functions like indexOf(), passing the byte array to a function
+ accepting a \c{const char *} expected to be '\\0'-terminated will
+ fail.
+
+ \sa setRawData(), data(), constData()
+*/
+
+QByteArray QByteArray::fromRawData(const char *data, int size)
+{
+ Data *x = static_cast<Data *>(qMalloc(sizeof(Data)));
+ Q_CHECK_PTR(x);
+ if (data) {
+ x->data = const_cast<char *>(data);
+ } else {
+ x->data = x->array;
+ size = 0;
+ }
+ x->ref = 1;
+ x->alloc = x->size = size;
+ *x->array = '\0';
+ return QByteArray(x, 0, 0);
+}
+
+/*!
+ \since 4.7
+
+ Resets the QByteArray to use the first \a size bytes of the
+ \a data array. The bytes are \e not copied. The QByteArray will
+ contain the \a data pointer. The caller guarantees that \a data
+ will not be deleted or modified as long as this QByteArray and any
+ copies of it exist that have not been modified.
+
+ This function can be used instead of fromRawData() to re-use
+ existings QByteArray objects to save memory re-allocations.
+
+ \sa fromRawData(), data(), constData()
+*/
+QByteArray &QByteArray::setRawData(const char *data, uint size)
+{
+ if (d->ref != 1 || d->alloc) {
+ *this = fromRawData(data, size);
+ } else {
+ if (data) {
+ d->data = const_cast<char *>(data);
+ } else {
+ d->data = d->array;
+ size = 0;
+ }
+ d->alloc = d->size = size;
+ *d->array = '\0';
+ }
+ return *this;
+}
+
+/*!
+ Returns a decoded copy of the Base64 array \a base64. Input is not checked
+ for validity; invalid characters in the input are skipped, enabling the
+ decoding process to continue with subsequent characters.
+
+ For example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 44
+
+ The algorithm used to decode Base64-encoded data is defined in \l{RFC 2045}.
+
+ \sa toBase64()
+*/
+QByteArray QByteArray::fromBase64(const QByteArray &base64)
+{
+ unsigned int buf = 0;
+ int nbits = 0;
+ QByteArray tmp((base64.size() * 3) / 4, Qt::Uninitialized);
+
+ int offset = 0;
+ for (int i = 0; i < base64.size(); ++i) {
+ int ch = base64.at(i);
+ int d;
+
+ if (ch >= 'A' && ch <= 'Z')
+ d = ch - 'A';
+ else if (ch >= 'a' && ch <= 'z')
+ d = ch - 'a' + 26;
+ else if (ch >= '0' && ch <= '9')
+ d = ch - '0' + 52;
+ else if (ch == '+')
+ d = 62;
+ else if (ch == '/')
+ d = 63;
+ else
+ d = -1;
+
+ if (d != -1) {
+ buf = (buf << 6) | d;
+ nbits += 6;
+ if (nbits >= 8) {
+ nbits -= 8;
+ tmp[offset++] = buf >> nbits;
+ buf &= (1 << nbits) - 1;
+ }
+ }
+ }
+
+ tmp.truncate(offset);
+ return tmp;
+}
+
+/*!
+ Returns a decoded copy of the hex encoded array \a hexEncoded. Input is not checked
+ for validity; invalid characters in the input are skipped, enabling the
+ decoding process to continue with subsequent characters.
+
+ For example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 45
+
+ \sa toHex()
+*/
+QByteArray QByteArray::fromHex(const QByteArray &hexEncoded)
+{
+ QByteArray res((hexEncoded.size() + 1)/ 2, Qt::Uninitialized);
+ uchar *result = (uchar *)res.data() + res.size();
+
+ bool odd_digit = true;
+ for (int i = hexEncoded.size() - 1; i >= 0; --i) {
+ int ch = hexEncoded.at(i);
+ int tmp;
+ if (ch >= '0' && ch <= '9')
+ tmp = ch - '0';
+ else if (ch >= 'a' && ch <= 'f')
+ tmp = ch - 'a' + 10;
+ else if (ch >= 'A' && ch <= 'F')
+ tmp = ch - 'A' + 10;
+ else
+ continue;
+ if (odd_digit) {
+ --result;
+ *result = tmp;
+ odd_digit = false;
+ } else {
+ *result |= tmp << 4;
+ odd_digit = true;
+ }
+ }
+
+ res.remove(0, result - (const uchar *)res.constData());
+ return res;
+}
+
+/*!
+ Returns a hex encoded copy of the byte array. The hex encoding uses the numbers 0-9 and
+ the letters a-f.
+
+ \sa fromHex()
+*/
+QByteArray QByteArray::toHex() const
+{
+ QByteArray hex(d->size * 2, Qt::Uninitialized);
+ char *hexData = hex.data();
+ const uchar *data = (const uchar *)d->data;
+ for (int i = 0; i < d->size; ++i) {
+ int j = (data[i] >> 4) & 0xf;
+ if (j <= 9)
+ hexData[i*2] = (j + '0');
+ else
+ hexData[i*2] = (j + 'a' - 10);
+ j = data[i] & 0xf;
+ if (j <= 9)
+ hexData[i*2+1] = (j + '0');
+ else
+ hexData[i*2+1] = (j + 'a' - 10);
+ }
+ return hex;
+}
+
+static void q_fromPercentEncoding(QByteArray *ba, char percent)
+{
+ if (ba->isEmpty())
+ return;
+
+ char *data = ba->data();
+ const char *inputPtr = data;
+
+ int i = 0;
+ int len = ba->count();
+ int outlen = 0;
+ int a, b;
+ char c;
+ while (i < len) {
+ c = inputPtr[i];
+ if (c == percent && i + 2 < len) {
+ a = inputPtr[++i];
+ b = inputPtr[++i];
+
+ if (a >= '0' && a <= '9') a -= '0';
+ else if (a >= 'a' && a <= 'f') a = a - 'a' + 10;
+ else if (a >= 'A' && a <= 'F') a = a - 'A' + 10;
+
+ if (b >= '0' && b <= '9') b -= '0';
+ else if (b >= 'a' && b <= 'f') b = b - 'a' + 10;
+ else if (b >= 'A' && b <= 'F') b = b - 'A' + 10;
+
+ *data++ = (char)((a << 4) | b);
+ } else {
+ *data++ = c;
+ }
+
+ ++i;
+ ++outlen;
+ }
+
+ if (outlen != len)
+ ba->truncate(outlen);
+}
+
+void q_fromPercentEncoding(QByteArray *ba)
+{
+ q_fromPercentEncoding(ba, '%');
+}
+
+/*!
+ \since 4.4
+
+ Returns a decoded copy of the URI/URL-style percent-encoded \a input.
+ The \a percent parameter allows you to replace the '%' character for
+ another (for instance, '_' or '=').
+
+ For example:
+ \code
+ QByteArray text = QByteArray::fromPercentEncoding("Qt%20is%20great%33");
+ text.data(); // returns "Qt is great!"
+ \endcode
+
+ \sa toPercentEncoding(), QUrl::fromPercentEncoding()
+*/
+QByteArray QByteArray::fromPercentEncoding(const QByteArray &input, char percent)
+{
+ if (input.isNull())
+ return QByteArray(); // preserve null
+ if (input.isEmpty())
+ return QByteArray(input.data(), 0);
+
+ QByteArray tmp = input;
+ q_fromPercentEncoding(&tmp, percent);
+ return tmp;
+}
+
+static inline bool q_strchr(const char str[], char chr)
+{
+ if (!str) return false;
+
+ const char *ptr = str;
+ char c;
+ while ((c = *ptr++))
+ if (c == chr)
+ return true;
+ return false;
+}
+
+static inline char toHexHelper(char c)
+{
+ static const char hexnumbers[] = "0123456789ABCDEF";
+ return hexnumbers[c & 0xf];
+}
+
+static void q_toPercentEncoding(QByteArray *ba, const char *dontEncode, const char *alsoEncode, char percent)
+{
+ if (ba->isEmpty())
+ return;
+
+ QByteArray input = *ba;
+ int len = input.count();
+ const char *inputData = input.constData();
+ char *output = 0;
+ int length = 0;
+
+ for (int i = 0; i < len; ++i) {
+ unsigned char c = *inputData++;
+ if (((c >= 0x61 && c <= 0x7A) // ALPHA
+ || (c >= 0x41 && c <= 0x5A) // ALPHA
+ || (c >= 0x30 && c <= 0x39) // DIGIT
+ || c == 0x2D // -
+ || c == 0x2E // .
+ || c == 0x5F // _
+ || c == 0x7E // ~
+ || q_strchr(dontEncode, c))
+ && !q_strchr(alsoEncode, c)) {
+ if (output)
+ output[length] = c;
+ ++length;
+ } else {
+ if (!output) {
+ // detach now
+ ba->resize(len*3); // worst case
+ output = ba->data();
+ }
+ output[length++] = percent;
+ output[length++] = toHexHelper((c & 0xf0) >> 4);
+ output[length++] = toHexHelper(c & 0xf);
+ }
+ }
+ if (output)
+ ba->truncate(length);
+}
+
+void q_toPercentEncoding(QByteArray *ba, const char *exclude, const char *include)
+{
+ q_toPercentEncoding(ba, exclude, include, '%');
+}
+
+void q_normalizePercentEncoding(QByteArray *ba, const char *exclude)
+{
+ q_fromPercentEncoding(ba, '%');
+ q_toPercentEncoding(ba, exclude, 0, '%');
+}
+
+/*!
+ \since 4.4
+
+ Returns a URI/URL-style percent-encoded copy of this byte array. The
+ \a percent parameter allows you to override the default '%'
+ character for another.
+
+ By default, this function will encode all characters that are not
+ one of the following:
+
+ ALPHA ("a" to "z" and "A" to "Z") / DIGIT (0 to 9) / "-" / "." / "_" / "~"
+
+ To prevent characters from being encoded pass them to \a
+ exclude. To force characters to be encoded pass them to \a
+ include. The \a percent character is always encoded.
+
+ Example:
+
+ \code
+ QByteArray text = "{a fishy string?}";
+ QByteArray ba = text.toPercentEncoding("{}", "s");
+ qDebug(ba.constData());
+ // prints "{a fi%73hy %73tring%3F}"
+ \endcode
+
+ The hex encoding uses the numbers 0-9 and the uppercase letters A-F.
+
+ \sa fromPercentEncoding(), QUrl::toPercentEncoding()
+*/
+QByteArray QByteArray::toPercentEncoding(const QByteArray &exclude, const QByteArray &include,
+ char percent) const
+{
+ if (isNull())
+ return QByteArray(); // preserve null
+ if (isEmpty())
+ return QByteArray(data(), 0);
+
+ QByteArray include2 = include;
+ if (percent != '%') // the default
+ if ((percent >= 0x61 && percent <= 0x7A) // ALPHA
+ || (percent >= 0x41 && percent <= 0x5A) // ALPHA
+ || (percent >= 0x30 && percent <= 0x39) // DIGIT
+ || percent == 0x2D // -
+ || percent == 0x2E // .
+ || percent == 0x5F // _
+ || percent == 0x7E) // ~
+ include2 += percent;
+
+ QByteArray result = *this;
+ q_toPercentEncoding(&result, exclude.nulTerminated().constData(), include2.nulTerminated().constData(), percent);
+
+ return result;
+}
+
+/*! \typedef QByteArray::ConstIterator
+ \internal
+*/
+
+/*! \typedef QByteArray::Iterator
+ \internal
+*/
+
+/*! \typedef QByteArray::const_iterator
+ \internal
+*/
+
+/*! \typedef QByteArray::iterator
+ \internal
+*/
+
+/*! \typedef QByteArray::const_reference
+ \internal
+*/
+
+/*! \typedef QByteArray::reference
+ \internal
+*/
+
+/*! \typedef QByteArray::value_type
+ \internal
+ */
+
+/*!
+ \fn QByteArray::QByteArray(int size)
+
+ Use QByteArray(int, char) instead.
+*/
+
+
+/*!
+ \fn QByteArray QByteArray::leftJustify(uint width, char fill, bool truncate) const
+
+ Use leftJustified() instead.
+*/
+
+/*!
+ \fn QByteArray QByteArray::rightJustify(uint width, char fill, bool truncate) const
+
+ Use rightJustified() instead.
+*/
+
+/*!
+ \fn QByteArray& QByteArray::duplicate(const QByteArray& a)
+
+ \oldcode
+ QByteArray bdata;
+ bdata.duplicate(original);
+ \newcode
+ QByteArray bdata;
+ bdata = original;
+ \endcode
+
+ \note QByteArray uses implicit sharing so if you modify a copy, only the
+ copy is changed.
+*/
+
+/*!
+ \fn QByteArray& QByteArray::duplicate(const char *a, uint n)
+
+ \overload
+
+ \oldcode
+ QByteArray bdata;
+ bdata.duplicate(ptr, size);
+ \newcode
+ QByteArray bdata;
+ bdata = QByteArray(ptr, size);
+ \endcode
+
+ \note QByteArray uses implicit sharing so if you modify a copy, only the
+ copy is changed.
+*/
+
+/*!
+ \fn void QByteArray::resetRawData(const char *data, uint n)
+
+ Use clear() instead.
+*/
+
+/*!
+ \fn QByteArray QByteArray::lower() const
+
+ Use toLower() instead.
+*/
+
+/*!
+ \fn QByteArray QByteArray::upper() const
+
+ Use toUpper() instead.
+*/
+
+/*!
+ \fn QByteArray QByteArray::stripWhiteSpace() const
+
+ Use trimmed() instead.
+*/
+
+/*!
+ \fn QByteArray QByteArray::simplifyWhiteSpace() const
+
+ Use simplified() instead.
+*/
+
+/*!
+ \fn int QByteArray::find(char c, int from = 0) const
+
+ Use indexOf() instead.
+*/
+
+/*!
+ \fn int QByteArray::find(const char *c, int from = 0) const
+
+ Use indexOf() instead.
+*/
+
+/*!
+ \fn int QByteArray::find(const QByteArray &ba, int from = 0) const
+
+ Use indexOf() instead.
+*/
+
+/*!
+ \fn int QByteArray::findRev(char c, int from = -1) const
+
+ Use lastIndexOf() instead.
+*/
+
+/*!
+ \fn int QByteArray::findRev(const char *c, int from = -1) const
+
+ Use lastIndexOf() instead.
+*/
+
+/*!
+ \fn int QByteArray::findRev(const QByteArray &ba, int from = -1) const
+
+ Use lastIndexOf() instead.
+*/
+
+/*!
+ \fn int QByteArray::find(const QString &s, int from = 0) const
+
+ Use indexOf() instead.
+*/
+
+/*!
+ \fn int QByteArray::findRev(const QString &s, int from = -1) const
+
+ Use lastIndexOf() instead.
+*/
+
+/*!
+ \fn DataPtr &QByteArray::data_ptr()
+ \internal
+*/
+
+/*!
+ \typedef QByteArray::DataPtr
+ \internal
+*/
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qbytearray.h b/src/corelib/tools/qbytearray.h
new file mode 100644
index 0000000000..0627b4e568
--- /dev/null
+++ b/src/corelib/tools/qbytearray.h
@@ -0,0 +1,622 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBYTEARRAY_H
+#define QBYTEARRAY_H
+
+#include <QtCore/qatomic.h>
+#include <QtCore/qnamespace.h>
+
+#include <string.h>
+#include <stdarg.h>
+
+#ifdef truncate
+#error qbytearray.h must be included before any header file that defines truncate
+#endif
+
+#if defined(Q_CC_GNU) && (__GNUC__ == 4 && __GNUC_MINOR__ == 0)
+//There is a bug in GCC 4.0 that tries to instantiate template of annonymous enum
+# ifdef QT_USE_FAST_OPERATOR_PLUS
+# undef QT_USE_FAST_OPERATOR_PLUS
+# endif
+# ifdef QT_USE_FAST_CONCATENATION
+# undef QT_USE_FAST_CONCATENATION
+# endif
+#endif
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+/*****************************************************************************
+ Safe and portable C string functions; extensions to standard string.h
+ *****************************************************************************/
+
+Q_CORE_EXPORT char *qstrdup(const char *);
+
+inline uint qstrlen(const char *str)
+{ return str ? uint(strlen(str)) : 0; }
+
+inline uint qstrnlen(const char *str, uint maxlen)
+{
+ uint length = 0;
+ if (str) {
+ while (length < maxlen && *str++)
+ length++;
+ }
+ return length;
+}
+
+Q_CORE_EXPORT char *qstrcpy(char *dst, const char *src);
+Q_CORE_EXPORT char *qstrncpy(char *dst, const char *src, uint len);
+
+Q_CORE_EXPORT int qstrcmp(const char *str1, const char *str2);
+Q_CORE_EXPORT int qstrcmp(const QByteArray &str1, const QByteArray &str2);
+Q_CORE_EXPORT int qstrcmp(const QByteArray &str1, const char *str2);
+static inline int qstrcmp(const char *str1, const QByteArray &str2)
+{ return -qstrcmp(str2, str1); }
+
+inline int qstrncmp(const char *str1, const char *str2, uint len)
+{
+ return (str1 && str2) ? strncmp(str1, str2, len)
+ : (str1 ? 1 : (str2 ? -1 : 0));
+}
+Q_CORE_EXPORT int qstricmp(const char *, const char *);
+Q_CORE_EXPORT int qstrnicmp(const char *, const char *, uint len);
+
+// implemented in qvsnprintf.cpp
+Q_CORE_EXPORT int qvsnprintf(char *str, size_t n, const char *fmt, va_list ap);
+Q_CORE_EXPORT int qsnprintf(char *str, size_t n, const char *fmt, ...);
+
+#ifdef QT3_SUPPORT
+inline QT3_SUPPORT void *qmemmove(void *dst, const void *src, uint len)
+{ return memmove(dst, src, len); }
+inline QT3_SUPPORT uint cstrlen(const char *str)
+{ return uint(strlen(str)); }
+inline QT3_SUPPORT char *cstrcpy(char *dst, const char *src)
+{ return qstrcpy(dst,src); }
+inline QT3_SUPPORT int cstrcmp(const char *str1, const char *str2)
+{ return strcmp(str1,str2); }
+inline QT3_SUPPORT int cstrncmp(const char *str1, const char *str2, uint len)
+{ return strncmp(str1,str2,len); }
+#endif
+
+// qChecksum: Internet checksum
+
+Q_CORE_EXPORT quint16 qChecksum(const char *s, uint len);
+
+class QByteRef;
+class QString;
+class QDataStream;
+template <typename T> class QList;
+
+class Q_CORE_EXPORT QByteArray
+{
+private:
+ struct Data {
+ QBasicAtomicInt ref;
+ int alloc, size;
+ // ### Qt 5.0: We need to add the missing capacity bit
+ // (like other tool classes have), to maintain the
+ // reserved memory on resize.
+ char *data;
+ char array[1];
+ };
+
+public:
+ inline QByteArray();
+ QByteArray(const char *);
+ QByteArray(const char *, int size);
+ QByteArray(int size, char c);
+ QByteArray(int size, Qt::Initialization);
+ inline QByteArray(const QByteArray &);
+ inline ~QByteArray();
+
+ QByteArray &operator=(const QByteArray &);
+ QByteArray &operator=(const char *str);
+#ifdef Q_COMPILER_RVALUE_REFS
+ inline QByteArray &operator=(QByteArray &&other)
+ { qSwap(d, other.d); return *this; }
+#endif
+
+ inline void swap(QByteArray &other) { qSwap(d, other.d); }
+
+ inline int size() const;
+ bool isEmpty() const;
+ void resize(int size);
+
+ QByteArray &fill(char c, int size = -1);
+
+ int capacity() const;
+ void reserve(int size);
+ void squeeze();
+
+#ifndef QT_NO_CAST_FROM_BYTEARRAY
+ operator const char *() const;
+ operator const void *() const;
+#endif
+ char *data();
+ const char *data() const;
+ inline const char *constData() const;
+ inline void detach();
+ bool isDetached() const;
+ inline bool isSharedWith(const QByteArray &other) const { return d == other.d; }
+ void clear();
+
+#ifdef Q_COMPILER_MANGLES_RETURN_TYPE
+ const char at(int i) const;
+ const char operator[](int i) const;
+ const char operator[](uint i) const;
+#else
+ char at(int i) const;
+ char operator[](int i) const;
+ char operator[](uint i) const;
+#endif
+ QByteRef operator[](int i);
+ QByteRef operator[](uint i);
+
+ int indexOf(char c, int from = 0) const;
+ int indexOf(const char *c, int from = 0) const;
+ int indexOf(const QByteArray &a, int from = 0) const;
+ int lastIndexOf(char c, int from = -1) const;
+ int lastIndexOf(const char *c, int from = -1) const;
+ int lastIndexOf(const QByteArray &a, int from = -1) const;
+
+ QBool contains(char c) const;
+ QBool contains(const char *a) const;
+ QBool contains(const QByteArray &a) const;
+ int count(char c) const;
+ int count(const char *a) const;
+ int count(const QByteArray &a) const;
+
+ QByteArray left(int len) const;
+ QByteArray right(int len) const;
+ QByteArray mid(int index, int len = -1) const;
+
+ bool startsWith(const QByteArray &a) const;
+ bool startsWith(char c) const;
+ bool startsWith(const char *c) const;
+
+ bool endsWith(const QByteArray &a) const;
+ bool endsWith(char c) const;
+ bool endsWith(const char *c) const;
+
+ void truncate(int pos);
+ void chop(int n);
+
+ QByteArray toLower() const;
+ QByteArray toUpper() const;
+
+ QByteArray trimmed() const;
+ QByteArray simplified() const;
+ QByteArray leftJustified(int width, char fill = ' ', bool truncate = false) const;
+ QByteArray rightJustified(int width, char fill = ' ', bool truncate = false) const;
+
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT QByteArray leftJustify(uint width, char aFill = ' ', bool aTruncate = false) const
+ { return leftJustified(int(width), aFill, aTruncate); }
+ inline QT3_SUPPORT QByteArray rightJustify(uint width, char aFill = ' ', bool aTruncate = false) const
+ { return rightJustified(int(width), aFill, aTruncate); }
+#endif
+
+ QByteArray &prepend(char c);
+ QByteArray &prepend(const char *s);
+ QByteArray &prepend(const char *s, int len);
+ QByteArray &prepend(const QByteArray &a);
+ QByteArray &append(char c);
+ QByteArray &append(const char *s);
+ QByteArray &append(const char *s, int len);
+ QByteArray &append(const QByteArray &a);
+ QByteArray &insert(int i, char c);
+ QByteArray &insert(int i, const char *s);
+ QByteArray &insert(int i, const char *s, int len);
+ QByteArray &insert(int i, const QByteArray &a);
+ QByteArray &remove(int index, int len);
+ QByteArray &replace(int index, int len, const char *s);
+ QByteArray &replace(int index, int len, const char *s, int alen);
+ QByteArray &replace(int index, int len, const QByteArray &s);
+ QByteArray &replace(char before, const char *after);
+ QByteArray &replace(char before, const QByteArray &after);
+ QByteArray &replace(const char *before, const char *after);
+ QByteArray &replace(const char *before, int bsize, const char *after, int asize);
+ QByteArray &replace(const QByteArray &before, const QByteArray &after);
+ QByteArray &replace(const QByteArray &before, const char *after);
+ QByteArray &replace(const char *before, const QByteArray &after);
+ QByteArray &replace(char before, char after);
+ QByteArray &operator+=(char c);
+ QByteArray &operator+=(const char *s);
+ QByteArray &operator+=(const QByteArray &a);
+
+ QList<QByteArray> split(char sep) const;
+
+ QByteArray repeated(int times) const;
+
+#ifndef QT_NO_CAST_TO_ASCII
+ QT_ASCII_CAST_WARN QByteArray &append(const QString &s);
+ QT_ASCII_CAST_WARN QByteArray &insert(int i, const QString &s);
+ QT_ASCII_CAST_WARN QByteArray &replace(const QString &before, const char *after);
+ QT_ASCII_CAST_WARN QByteArray &replace(char c, const QString &after);
+ QT_ASCII_CAST_WARN QByteArray &replace(const QString &before, const QByteArray &after);
+
+ QT_ASCII_CAST_WARN QByteArray &operator+=(const QString &s);
+ QT_ASCII_CAST_WARN int indexOf(const QString &s, int from = 0) const;
+ QT_ASCII_CAST_WARN int lastIndexOf(const QString &s, int from = -1) const;
+#endif
+#ifndef QT_NO_CAST_FROM_ASCII
+ inline QT_ASCII_CAST_WARN bool operator==(const QString &s2) const;
+ inline QT_ASCII_CAST_WARN bool operator!=(const QString &s2) const;
+ inline QT_ASCII_CAST_WARN bool operator<(const QString &s2) const;
+ inline QT_ASCII_CAST_WARN bool operator>(const QString &s2) const;
+ inline QT_ASCII_CAST_WARN bool operator<=(const QString &s2) const;
+ inline QT_ASCII_CAST_WARN bool operator>=(const QString &s2) const;
+#endif
+
+ short toShort(bool *ok = 0, int base = 10) const;
+ ushort toUShort(bool *ok = 0, int base = 10) const;
+ int toInt(bool *ok = 0, int base = 10) const;
+ uint toUInt(bool *ok = 0, int base = 10) const;
+ long toLong(bool *ok = 0, int base = 10) const;
+ ulong toULong(bool *ok = 0, int base = 10) const;
+ qlonglong toLongLong(bool *ok = 0, int base = 10) const;
+ qulonglong toULongLong(bool *ok = 0, int base = 10) const;
+ float toFloat(bool *ok = 0) const;
+ double toDouble(bool *ok = 0) const;
+ QByteArray toBase64() const;
+ QByteArray toHex() const;
+ QByteArray toPercentEncoding(const QByteArray &exclude = QByteArray(),
+ const QByteArray &include = QByteArray(),
+ char percent = '%') const;
+
+ QByteArray &setNum(short, int base = 10);
+ QByteArray &setNum(ushort, int base = 10);
+ QByteArray &setNum(int, int base = 10);
+ QByteArray &setNum(uint, int base = 10);
+ QByteArray &setNum(qlonglong, int base = 10);
+ QByteArray &setNum(qulonglong, int base = 10);
+ QByteArray &setNum(float, char f = 'g', int prec = 6);
+ QByteArray &setNum(double, char f = 'g', int prec = 6);
+ QByteArray &setRawData(const char *a, uint n); // ### Qt 5: use an int
+
+ static QByteArray number(int, int base = 10);
+ static QByteArray number(uint, int base = 10);
+ static QByteArray number(qlonglong, int base = 10);
+ static QByteArray number(qulonglong, int base = 10);
+ static QByteArray number(double, char f = 'g', int prec = 6);
+ static QByteArray fromRawData(const char *, int size);
+ static QByteArray fromBase64(const QByteArray &base64);
+ static QByteArray fromHex(const QByteArray &hexEncoded);
+ static QByteArray fromPercentEncoding(const QByteArray &pctEncoded, char percent = '%');
+
+
+ typedef char *iterator;
+ typedef const char *const_iterator;
+ typedef iterator Iterator;
+ typedef const_iterator ConstIterator;
+ iterator begin();
+ const_iterator begin() const;
+ const_iterator constBegin() const;
+ iterator end();
+ const_iterator end() const;
+ const_iterator constEnd() const;
+
+ // stl compatibility
+ typedef const char & const_reference;
+ typedef char & reference;
+ typedef char value_type;
+ void push_back(char c);
+ void push_back(const char *c);
+ void push_back(const QByteArray &a);
+ void push_front(char c);
+ void push_front(const char *c);
+ void push_front(const QByteArray &a);
+
+ inline int count() const { return d->size; }
+ int length() const { return d->size; }
+ bool isNull() const;
+
+ // compatibility
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT_CONSTRUCTOR QByteArray(int size);
+ inline QT3_SUPPORT QByteArray& duplicate(const QByteArray& a) { *this = a; return *this; }
+ inline QT3_SUPPORT QByteArray& duplicate(const char *a, uint n)
+ { *this = QByteArray(a, n); return *this; }
+ inline QT3_SUPPORT void resetRawData(const char *, uint) { clear(); }
+ inline QT3_SUPPORT QByteArray lower() const { return toLower(); }
+ inline QT3_SUPPORT QByteArray upper() const { return toUpper(); }
+ inline QT3_SUPPORT QByteArray stripWhiteSpace() const { return trimmed(); }
+ inline QT3_SUPPORT QByteArray simplifyWhiteSpace() const { return simplified(); }
+ inline QT3_SUPPORT int find(char c, int from = 0) const { return indexOf(c, from); }
+ inline QT3_SUPPORT int find(const char *c, int from = 0) const { return indexOf(c, from); }
+ inline QT3_SUPPORT int find(const QByteArray &ba, int from = 0) const { return indexOf(ba, from); }
+ inline QT3_SUPPORT int findRev(char c, int from = -1) const { return lastIndexOf(c, from); }
+ inline QT3_SUPPORT int findRev(const char *c, int from = -1) const { return lastIndexOf(c, from); }
+ inline QT3_SUPPORT int findRev(const QByteArray &ba, int from = -1) const { return lastIndexOf(ba, from); }
+#ifndef QT_NO_CAST_TO_ASCII
+ QT3_SUPPORT int find(const QString &s, int from = 0) const;
+ QT3_SUPPORT int findRev(const QString &s, int from = -1) const;
+#endif
+#endif
+
+private:
+ operator QNoImplicitBoolCast() const;
+ static Data shared_null;
+ static Data shared_empty;
+ Data *d;
+ QByteArray(Data *dd, int /*dummy*/, int /*dummy*/) : d(dd) {}
+ void realloc(int alloc);
+ void expand(int i);
+ QByteArray nulTerminated() const;
+
+ friend class QByteRef;
+ friend class QString;
+ friend Q_CORE_EXPORT QByteArray qUncompress(const uchar *data, int nbytes);
+public:
+ typedef Data * DataPtr;
+ inline DataPtr &data_ptr() { return d; }
+};
+
+inline QByteArray::QByteArray(): d(&shared_null) { d->ref.ref(); }
+inline QByteArray::~QByteArray() { if (!d->ref.deref()) qFree(d); }
+inline int QByteArray::size() const
+{ return d->size; }
+
+#ifdef Q_COMPILER_MANGLES_RETURN_TYPE
+inline const char QByteArray::at(int i) const
+{ Q_ASSERT(i >= 0 && i < size()); return d->data[i]; }
+inline const char QByteArray::operator[](int i) const
+{ Q_ASSERT(i >= 0 && i < size()); return d->data[i]; }
+inline const char QByteArray::operator[](uint i) const
+{ Q_ASSERT(i < uint(size())); return d->data[i]; }
+#else
+inline char QByteArray::at(int i) const
+{ Q_ASSERT(i >= 0 && i < size()); return d->data[i]; }
+inline char QByteArray::operator[](int i) const
+{ Q_ASSERT(i >= 0 && i < size()); return d->data[i]; }
+inline char QByteArray::operator[](uint i) const
+{ Q_ASSERT(i < uint(size())); return d->data[i]; }
+#endif
+
+inline bool QByteArray::isEmpty() const
+{ return d->size == 0; }
+#ifndef QT_NO_CAST_FROM_BYTEARRAY
+inline QByteArray::operator const char *() const
+{ return d->data; }
+inline QByteArray::operator const void *() const
+{ return d->data; }
+#endif
+inline char *QByteArray::data()
+{ detach(); return d->data; }
+inline const char *QByteArray::data() const
+{ return d->data; }
+inline const char *QByteArray::constData() const
+{ return d->data; }
+inline void QByteArray::detach()
+{ if (d->ref != 1 || d->data != d->array) realloc(d->size); }
+inline bool QByteArray::isDetached() const
+{ return d->ref == 1; }
+inline QByteArray::QByteArray(const QByteArray &a) : d(a.d)
+{ d->ref.ref(); }
+#ifdef QT3_SUPPORT
+inline QByteArray::QByteArray(int aSize) : d(&shared_null)
+{ d->ref.ref(); if (aSize > 0) fill('\0', aSize); }
+#endif
+
+inline int QByteArray::capacity() const
+{ return d->alloc; }
+
+inline void QByteArray::reserve(int asize)
+{ if (d->ref != 1 || asize > d->alloc) realloc(asize); }
+
+inline void QByteArray::squeeze()
+{ if (d->size < d->alloc) realloc(d->size); }
+
+class Q_CORE_EXPORT QByteRef {
+ QByteArray &a;
+ int i;
+ inline QByteRef(QByteArray &array, int idx)
+ : a(array),i(idx) {}
+ friend class QByteArray;
+public:
+#ifdef Q_COMPILER_MANGLES_RETURN_TYPE
+ inline operator const char() const
+ { return i < a.d->size ? a.d->data[i] : char(0); }
+#else
+ inline operator char() const
+ { return i < a.d->size ? a.d->data[i] : char(0); }
+#endif
+ inline QByteRef &operator=(char c)
+ { if (i >= a.d->size) a.expand(i); else a.detach();
+ a.d->data[i] = c; return *this; }
+ inline QByteRef &operator=(const QByteRef &c)
+ { if (i >= a.d->size) a.expand(i); else a.detach();
+ a.d->data[i] = c.a.d->data[c.i]; return *this; }
+ inline bool operator==(char c) const
+ { return a.d->data[i] == c; }
+ inline bool operator!=(char c) const
+ { return a.d->data[i] != c; }
+ inline bool operator>(char c) const
+ { return a.d->data[i] > c; }
+ inline bool operator>=(char c) const
+ { return a.d->data[i] >= c; }
+ inline bool operator<(char c) const
+ { return a.d->data[i] < c; }
+ inline bool operator<=(char c) const
+ { return a.d->data[i] <= c; }
+};
+
+inline QByteRef QByteArray::operator[](int i)
+{ Q_ASSERT(i >= 0); return QByteRef(*this, i); }
+inline QByteRef QByteArray::operator[](uint i)
+{ return QByteRef(*this, i); }
+inline QByteArray::iterator QByteArray::begin()
+{ detach(); return d->data; }
+inline QByteArray::const_iterator QByteArray::begin() const
+{ return d->data; }
+inline QByteArray::const_iterator QByteArray::constBegin() const
+{ return d->data; }
+inline QByteArray::iterator QByteArray::end()
+{ detach(); return d->data + d->size; }
+inline QByteArray::const_iterator QByteArray::end() const
+{ return d->data + d->size; }
+inline QByteArray::const_iterator QByteArray::constEnd() const
+{ return d->data + d->size; }
+inline QByteArray &QByteArray::operator+=(char c)
+{ return append(c); }
+inline QByteArray &QByteArray::operator+=(const char *s)
+{ return append(s); }
+inline QByteArray &QByteArray::operator+=(const QByteArray &a)
+{ return append(a); }
+inline void QByteArray::push_back(char c)
+{ append(c); }
+inline void QByteArray::push_back(const char *c)
+{ append(c); }
+inline void QByteArray::push_back(const QByteArray &a)
+{ append(a); }
+inline void QByteArray::push_front(char c)
+{ prepend(c); }
+inline void QByteArray::push_front(const char *c)
+{ prepend(c); }
+inline void QByteArray::push_front(const QByteArray &a)
+{ prepend(a); }
+inline QBool QByteArray::contains(const QByteArray &a) const
+{ return QBool(indexOf(a) != -1); }
+inline QBool QByteArray::contains(char c) const
+{ return QBool(indexOf(c) != -1); }
+inline bool operator==(const QByteArray &a1, const QByteArray &a2)
+{ return (a1.size() == a2.size()) && (memcmp(a1.constData(), a2.constData(), a1.size())==0); }
+inline bool operator==(const QByteArray &a1, const char *a2)
+{ return a2 ? qstrcmp(a1,a2) == 0 : a1.isEmpty(); }
+inline bool operator==(const char *a1, const QByteArray &a2)
+{ return a1 ? qstrcmp(a1,a2) == 0 : a2.isEmpty(); }
+inline bool operator!=(const QByteArray &a1, const QByteArray &a2)
+{ return !(a1==a2); }
+inline bool operator!=(const QByteArray &a1, const char *a2)
+{ return a2 ? qstrcmp(a1,a2) != 0 : !a1.isEmpty(); }
+inline bool operator!=(const char *a1, const QByteArray &a2)
+{ return a1 ? qstrcmp(a1,a2) != 0 : !a2.isEmpty(); }
+inline bool operator<(const QByteArray &a1, const QByteArray &a2)
+{ return qstrcmp(a1, a2) < 0; }
+ inline bool operator<(const QByteArray &a1, const char *a2)
+{ return qstrcmp(a1, a2) < 0; }
+inline bool operator<(const char *a1, const QByteArray &a2)
+{ return qstrcmp(a1, a2) < 0; }
+inline bool operator<=(const QByteArray &a1, const QByteArray &a2)
+{ return qstrcmp(a1, a2) <= 0; }
+inline bool operator<=(const QByteArray &a1, const char *a2)
+{ return qstrcmp(a1, a2) <= 0; }
+inline bool operator<=(const char *a1, const QByteArray &a2)
+{ return qstrcmp(a1, a2) <= 0; }
+inline bool operator>(const QByteArray &a1, const QByteArray &a2)
+{ return qstrcmp(a1, a2) > 0; }
+inline bool operator>(const QByteArray &a1, const char *a2)
+{ return qstrcmp(a1, a2) > 0; }
+inline bool operator>(const char *a1, const QByteArray &a2)
+{ return qstrcmp(a1, a2) > 0; }
+inline bool operator>=(const QByteArray &a1, const QByteArray &a2)
+{ return qstrcmp(a1, a2) >= 0; }
+inline bool operator>=(const QByteArray &a1, const char *a2)
+{ return qstrcmp(a1, a2) >= 0; }
+inline bool operator>=(const char *a1, const QByteArray &a2)
+{ return qstrcmp(a1, a2) >= 0; }
+#ifndef QT_USE_FAST_OPERATOR_PLUS
+# ifndef QT_USE_FAST_CONCATENATION
+inline const QByteArray operator+(const QByteArray &a1, const QByteArray &a2)
+{ return QByteArray(a1) += a2; }
+inline const QByteArray operator+(const QByteArray &a1, const char *a2)
+{ return QByteArray(a1) += a2; }
+inline const QByteArray operator+(const QByteArray &a1, char a2)
+{ return QByteArray(a1) += a2; }
+inline const QByteArray operator+(const char *a1, const QByteArray &a2)
+{ return QByteArray(a1) += a2; }
+inline const QByteArray operator+(char a1, const QByteArray &a2)
+{ return QByteArray(&a1, 1) += a2; }
+# endif // QT_USE_FAST_CONCATENATION
+#endif // QT_USE_FAST_OPERATOR_PLUS
+inline QBool QByteArray::contains(const char *c) const
+{ return QBool(indexOf(c) != -1); }
+inline QByteArray &QByteArray::replace(char before, const char *c)
+{ return replace(&before, 1, c, qstrlen(c)); }
+inline QByteArray &QByteArray::replace(const QByteArray &before, const char *c)
+{ return replace(before.constData(), before.size(), c, qstrlen(c)); }
+inline QByteArray &QByteArray::replace(const char *before, const char *after)
+{ return replace(before, qstrlen(before), after, qstrlen(after)); }
+
+inline QByteArray &QByteArray::setNum(short n, int base)
+{ return setNum(qlonglong(n), base); }
+inline QByteArray &QByteArray::setNum(ushort n, int base)
+{ return setNum(qulonglong(n), base); }
+inline QByteArray &QByteArray::setNum(int n, int base)
+{ return setNum(qlonglong(n), base); }
+inline QByteArray &QByteArray::setNum(uint n, int base)
+{ return setNum(qulonglong(n), base); }
+inline QByteArray &QByteArray::setNum(float n, char f, int prec)
+{ return setNum(double(n),f,prec); }
+
+
+#if !defined(QT_NO_DATASTREAM) || (defined(QT_BOOTSTRAPPED) && !defined(QT_BUILD_QMAKE))
+Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QByteArray &);
+Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QByteArray &);
+#endif
+
+#ifndef QT_NO_COMPRESS
+Q_CORE_EXPORT QByteArray qCompress(const uchar* data, int nbytes, int compressionLevel = -1);
+Q_CORE_EXPORT QByteArray qUncompress(const uchar* data, int nbytes);
+inline QByteArray qCompress(const QByteArray& data, int compressionLevel = -1)
+{ return qCompress(reinterpret_cast<const uchar *>(data.constData()), data.size(), compressionLevel); }
+inline QByteArray qUncompress(const QByteArray& data)
+{ return qUncompress(reinterpret_cast<const uchar*>(data.constData()), data.size()); }
+#endif
+
+Q_DECLARE_TYPEINFO(QByteArray, Q_MOVABLE_TYPE);
+Q_DECLARE_SHARED(QByteArray)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#ifdef QT_USE_FAST_CONCATENATION
+#include <QtCore/qstring.h>
+#endif
+
+#endif // QBYTEARRAY_H
diff --git a/src/corelib/tools/qbytearraymatcher.cpp b/src/corelib/tools/qbytearraymatcher.cpp
new file mode 100644
index 0000000000..bc99760ddc
--- /dev/null
+++ b/src/corelib/tools/qbytearraymatcher.cpp
@@ -0,0 +1,324 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qbytearraymatcher.h"
+
+#include <limits.h>
+
+QT_BEGIN_NAMESPACE
+
+static inline void bm_init_skiptable(const uchar *cc, int len, uchar *skiptable)
+{
+ int l = qMin(len, 255);
+ memset(skiptable, l, 256*sizeof(uchar));
+ cc += len - l;
+ while (l--)
+ skiptable[*cc++] = l;
+}
+
+static inline int bm_find(const uchar *cc, int l, int index, const uchar *puc, uint pl,
+ const uchar *skiptable)
+{
+ if (pl == 0)
+ return index > l ? -1 : index;
+ const uint pl_minus_one = pl - 1;
+
+ register const uchar *current = cc + index + pl_minus_one;
+ const uchar *end = cc + l;
+ while (current < end) {
+ uint skip = skiptable[*current];
+ if (!skip) {
+ // possible match
+ while (skip < pl) {
+ if (*(current - skip) != puc[pl_minus_one - skip])
+ break;
+ skip++;
+ }
+ if (skip > pl_minus_one) // we have a match
+ return (current - cc) - skip + 1;
+
+ // in case we don't have a match we are a bit inefficient as we only skip by one
+ // when we have the non matching char in the string.
+ if (skiptable[*(current - skip)] == pl)
+ skip = pl - skip;
+ else
+ skip = 1;
+ }
+ if (current > end - skip)
+ break;
+ current += skip;
+ }
+ return -1; // not found
+}
+
+/*! \class QByteArrayMatcher
+ \brief The QByteArrayMatcher class holds a sequence of bytes that
+ can be quickly matched in a byte array.
+
+ \ingroup tools
+ \ingroup string-processing
+
+ This class is useful when you have a sequence of bytes that you
+ want to repeatedly match against some byte arrays (perhaps in a
+ loop), or when you want to search for the same sequence of bytes
+ multiple times in the same byte array. Using a matcher object and
+ indexIn() is faster than matching a plain QByteArray with
+ QByteArray::indexOf() if repeated matching takes place. This
+ class offers no benefit if you are doing one-off byte array
+ matches.
+
+ Create the QByteArrayMatcher with the QByteArray you want to
+ search for. Then call indexIn() on the QByteArray that you want to
+ search.
+
+ \sa QByteArray, QStringMatcher
+*/
+
+/*!
+ Constructs an empty byte array matcher that won't match anything.
+ Call setPattern() to give it a pattern to match.
+*/
+QByteArrayMatcher::QByteArrayMatcher()
+ : d(0)
+{
+ p.p = 0;
+ p.l = 0;
+ qMemSet(p.q_skiptable, 0, sizeof(p.q_skiptable));
+}
+
+/*!
+ Constructs a byte array matcher from \a pattern. \a pattern
+ has the given \a length. \a pattern must remain in scope, but
+ the destructor does not delete \a pattern.
+ */
+QByteArrayMatcher::QByteArrayMatcher(const char *pattern, int length)
+ : d(0)
+{
+ p.p = reinterpret_cast<const uchar *>(pattern);
+ p.l = length;
+ bm_init_skiptable(p.p, p.l, p.q_skiptable);
+}
+
+/*!
+ Constructs a byte array matcher that will search for \a pattern.
+ Call indexIn() to perform a search.
+*/
+QByteArrayMatcher::QByteArrayMatcher(const QByteArray &pattern)
+ : d(0), q_pattern(pattern)
+{
+ p.p = reinterpret_cast<const uchar *>(pattern.constData());
+ p.l = pattern.size();
+ bm_init_skiptable(p.p, p.l, p.q_skiptable);
+}
+
+/*!
+ Copies the \a other byte array matcher to this byte array matcher.
+*/
+QByteArrayMatcher::QByteArrayMatcher(const QByteArrayMatcher &other)
+ : d(0)
+{
+ operator=(other);
+}
+
+/*!
+ Destroys the byte array matcher.
+*/
+QByteArrayMatcher::~QByteArrayMatcher()
+{
+}
+
+/*!
+ Assigns the \a other byte array matcher to this byte array matcher.
+*/
+QByteArrayMatcher &QByteArrayMatcher::operator=(const QByteArrayMatcher &other)
+{
+ q_pattern = other.q_pattern;
+ memcpy(&p, &other.p, sizeof(p));
+ return *this;
+}
+
+/*!
+ Sets the byte array that this byte array matcher will search for
+ to \a pattern.
+
+ \sa pattern(), indexIn()
+*/
+void QByteArrayMatcher::setPattern(const QByteArray &pattern)
+{
+ q_pattern = pattern;
+ p.p = reinterpret_cast<const uchar *>(pattern.constData());
+ p.l = pattern.size();
+ bm_init_skiptable(p.p, p.l, p.q_skiptable);
+}
+
+/*!
+ Searches the byte array \a ba, from byte position \a from (default
+ 0, i.e. from the first byte), for the byte array pattern() that
+ was set in the constructor or in the most recent call to
+ setPattern(). Returns the position where the pattern() matched in
+ \a ba, or -1 if no match was found.
+*/
+int QByteArrayMatcher::indexIn(const QByteArray &ba, int from) const
+{
+ if (from < 0)
+ from = 0;
+ return bm_find(reinterpret_cast<const uchar *>(ba.constData()), ba.size(), from,
+ p.p, p.l, p.q_skiptable);
+}
+
+/*!
+ Searches the char string \a str, which has length \a len, from
+ byte position \a from (default 0, i.e. from the first byte), for
+ the byte array pattern() that was set in the constructor or in the
+ most recent call to setPattern(). Returns the position where the
+ pattern() matched in \a str, or -1 if no match was found.
+*/
+int QByteArrayMatcher::indexIn(const char *str, int len, int from) const
+{
+ if (from < 0)
+ from = 0;
+ return bm_find(reinterpret_cast<const uchar *>(str), len, from,
+ p.p, p.l, p.q_skiptable);
+}
+
+/*!
+ \fn QByteArray QByteArrayMatcher::pattern() const
+
+ Returns the byte array pattern that this byte array matcher will
+ search for.
+
+ \sa setPattern()
+*/
+
+
+static int findChar(const char *str, int len, char ch, int from)
+{
+ const uchar *s = (const uchar *)str;
+ uchar c = (uchar)ch;
+ if (from < 0)
+ from = qMax(from + len, 0);
+ if (from < len) {
+ const uchar *n = s + from - 1;
+ const uchar *e = s + len;
+ while (++n != e)
+ if (*n == c)
+ return n - s;
+ }
+ return -1;
+}
+
+/*! \internal
+ */
+static int qFindByteArrayBoyerMoore(
+ const char *haystack, int haystackLen, int haystackOffset,
+ const char *needle, int needleLen)
+{
+ uchar skiptable[256];
+ bm_init_skiptable((const uchar *)needle, needleLen, skiptable);
+ if (haystackOffset < 0)
+ haystackOffset = 0;
+ return bm_find((const uchar *)haystack, haystackLen, haystackOffset,
+ (const uchar *)needle, needleLen, skiptable);
+}
+
+#define REHASH(a) \
+ if (sl_minus_1 < sizeof(uint) * CHAR_BIT) \
+ hashHaystack -= (a) << sl_minus_1; \
+ hashHaystack <<= 1
+
+/*! \internal
+ */
+int qFindByteArray(
+ const char *haystack0, int haystackLen, int from,
+ const char *needle, int needleLen)
+{
+ const int l = haystackLen;
+ const int sl = needleLen;
+ if (from < 0)
+ from += l;
+ if (uint(sl + from) > (uint)l)
+ return -1;
+ if (!sl)
+ return from;
+ if (!l)
+ return -1;
+
+ if (sl == 1)
+ return findChar(haystack0, haystackLen, needle[0], from);
+
+ /*
+ We use the Boyer-Moore algorithm in cases where the overhead
+ for the skip table should pay off, otherwise we use a simple
+ hash function.
+ */
+ if (l > 500 && sl > 5)
+ return qFindByteArrayBoyerMoore(haystack0, haystackLen, from,
+ needle, needleLen);
+
+ /*
+ We use some hashing for efficiency's sake. Instead of
+ comparing strings, we compare the hash value of str with that
+ of a part of this QString. Only if that matches, we call memcmp().
+ */
+ const char *haystack = haystack0 + from;
+ const char *end = haystack0 + (l - sl);
+ const uint sl_minus_1 = sl - 1;
+ uint hashNeedle = 0, hashHaystack = 0;
+ int idx;
+ for (idx = 0; idx < sl; ++idx) {
+ hashNeedle = ((hashNeedle<<1) + needle[idx]);
+ hashHaystack = ((hashHaystack<<1) + haystack[idx]);
+ }
+ hashHaystack -= *(haystack + sl_minus_1);
+
+ while (haystack <= end) {
+ hashHaystack += *(haystack + sl_minus_1);
+ if (hashHaystack == hashNeedle && *needle == *haystack
+ && memcmp(needle, haystack, sl) == 0)
+ return haystack - haystack0;
+
+ REHASH(*haystack);
+ ++haystack;
+ }
+ return -1;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qbytearraymatcher.h b/src/corelib/tools/qbytearraymatcher.h
new file mode 100644
index 0000000000..444089a00a
--- /dev/null
+++ b/src/corelib/tools/qbytearraymatcher.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBYTEARRAYMATCHER_H
+#define QBYTEARRAYMATCHER_H
+
+#include <QtCore/qbytearray.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QByteArrayMatcherPrivate;
+
+class Q_CORE_EXPORT QByteArrayMatcher
+{
+public:
+ QByteArrayMatcher();
+ explicit QByteArrayMatcher(const QByteArray &pattern);
+ explicit QByteArrayMatcher(const char *pattern, int length);
+ QByteArrayMatcher(const QByteArrayMatcher &other);
+ ~QByteArrayMatcher();
+
+ QByteArrayMatcher &operator=(const QByteArrayMatcher &other);
+
+ void setPattern(const QByteArray &pattern);
+
+ int indexIn(const QByteArray &ba, int from = 0) const;
+ int indexIn(const char *str, int len, int from = 0) const;
+ inline QByteArray pattern() const
+ {
+ if (q_pattern.isNull())
+ return QByteArray(reinterpret_cast<const char*>(p.p), p.l);
+ return q_pattern;
+ }
+
+private:
+ QByteArrayMatcherPrivate *d;
+ QByteArray q_pattern;
+#ifdef Q_CC_RVCT
+// explicitly allow anonymous unions for RVCT to prevent compiler warnings
+# pragma push
+# pragma anon_unions
+#endif
+ struct Data {
+ uchar q_skiptable[256];
+ const uchar *p;
+ int l;
+ };
+ union {
+ uint dummy[256];
+ Data p;
+ };
+#ifdef Q_CC_RVCT
+# pragma pop
+#endif
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QBYTEARRAYMATCHER_H
diff --git a/src/corelib/tools/qbytedata_p.h b/src/corelib/tools/qbytedata_p.h
new file mode 100644
index 0000000000..45c576d2e9
--- /dev/null
+++ b/src/corelib/tools/qbytedata_p.h
@@ -0,0 +1,220 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBYTEDATA_H
+#define QBYTEDATA_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 <qbytearray.h>
+
+QT_BEGIN_NAMESPACE
+
+// this class handles a list of QByteArrays. It is a variant of QRingBuffer
+// that avoid malloc/realloc/memcpy.
+class QByteDataBuffer
+{
+private:
+ QList<QByteArray> buffers;
+ qint64 bufferCompleteSize;
+public:
+ QByteDataBuffer() : bufferCompleteSize(0)
+ {
+ }
+
+ ~QByteDataBuffer()
+ {
+ clear();
+ }
+
+ inline void append(QByteDataBuffer& other)
+ {
+ if (other.isEmpty())
+ return;
+
+ buffers.append(other.buffers);
+ bufferCompleteSize += other.byteAmount();
+ }
+
+
+ inline void append(const QByteArray& bd)
+ {
+ if (bd.isEmpty())
+ return;
+
+ buffers.append(bd);
+ bufferCompleteSize += bd.size();
+ }
+
+ inline void prepend(QByteArray& bd)
+ {
+ if (bd.isEmpty())
+ return;
+
+ buffers.prepend(bd);
+ bufferCompleteSize += bd.size();
+ }
+
+ // return the first QByteData. User of this function has to qFree() its .data!
+ // preferably use this function to read data.
+ inline QByteArray read()
+ {
+ bufferCompleteSize -= buffers.first().size();
+ return buffers.takeFirst();
+ }
+
+ // return everything. User of this function has to qFree() its .data!
+ // avoid to use this, it might malloc and memcpy.
+ inline QByteArray readAll()
+ {
+ return read(byteAmount());
+ }
+
+ // return amount. User of this function has to qFree() its .data!
+ // avoid to use this, it might malloc and memcpy.
+ inline QByteArray read(qint64 amount)
+ {
+ amount = qMin(byteAmount(), amount);
+ QByteArray byteData;
+ byteData.resize(amount);
+ read(byteData.data(), byteData.size());
+ return byteData;
+ }
+
+ // return amount bytes. User of this function has to qFree() its .data!
+ // avoid to use this, it will memcpy.
+ qint64 read(char* dst, qint64 amount)
+ {
+ amount = qMin(amount, byteAmount());
+ qint64 originalAmount = amount;
+ char *writeDst = dst;
+
+ while (amount > 0) {
+ QByteArray first = buffers.takeFirst();
+ if (amount >= first.size()) {
+ // take it completely
+ bufferCompleteSize -= first.size();
+ amount -= first.size();
+ memcpy(writeDst, first.constData(), first.size());
+ writeDst += first.size();
+ first.clear();
+ } else {
+ // take a part of it & it is the last one to take
+ bufferCompleteSize -= amount;
+ memcpy(writeDst, first.constData(), amount);
+
+ qint64 newFirstSize = first.size() - amount;
+ QByteArray newFirstData;
+ newFirstData.resize(newFirstSize);
+ memcpy(newFirstData.data(), first.constData() + amount, newFirstSize);
+ buffers.prepend(newFirstData);
+
+ amount = 0;
+ first.clear();
+ }
+ }
+
+ return originalAmount;
+ }
+
+ inline char getChar()
+ {
+ char c;
+ read(&c, 1);
+ return c;
+ }
+
+ inline void clear()
+ {
+ buffers.clear();
+ bufferCompleteSize = 0;
+ }
+
+ // The byte count of all QByteArrays
+ inline qint64 byteAmount() const
+ {
+ return bufferCompleteSize;
+ }
+
+ // the number of QByteArrays
+ inline qint64 bufferCount() const
+ {
+ return buffers.length();
+ }
+
+ inline bool isEmpty() const
+ {
+ return byteAmount() == 0;
+ }
+
+ inline qint64 sizeNextBlock() const
+ {
+ if(buffers.isEmpty())
+ return 0;
+ else
+ return buffers.first().size();
+ }
+
+ inline QByteArray& operator[](int i)
+ {
+ return buffers[i];
+ }
+
+ inline bool canReadLine() const {
+ for (int i = 0; i < buffers.length(); i++)
+ if (buffers.at(i).contains('\n'))
+ return true;
+ return false;
+ }
+};
+
+QT_END_NAMESPACE
+
+#endif // QBYTEDATA_H
diff --git a/src/corelib/tools/qcache.h b/src/corelib/tools/qcache.h
new file mode 100644
index 0000000000..7f6b86919f
--- /dev/null
+++ b/src/corelib/tools/qcache.h
@@ -0,0 +1,217 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCACHE_H
+#define QCACHE_H
+
+#include <QtCore/qhash.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+template <class Key, class T>
+class QCache
+{
+ struct Node {
+ inline Node() : keyPtr(0) {}
+ inline Node(T *data, int cost)
+ : keyPtr(0), t(data), c(cost), p(0), n(0) {}
+ const Key *keyPtr; T *t; int c; Node *p,*n;
+ };
+ Node *f, *l;
+ QHash<Key, Node> hash;
+ void *unused; // ### Qt5: remove
+ int mx, total;
+
+ inline void unlink(Node &n) {
+ if (n.p) n.p->n = n.n;
+ if (n.n) n.n->p = n.p;
+ if (l == &n) l = n.p;
+ if (f == &n) f = n.n;
+ total -= n.c;
+ T *obj = n.t;
+ hash.remove(*n.keyPtr);
+ delete obj;
+ }
+ inline T *relink(const Key &key) {
+ typename QHash<Key, Node>::iterator i = hash.find(key);
+ if (typename QHash<Key, Node>::const_iterator(i) == hash.constEnd())
+ return 0;
+
+ Node &n = *i;
+ if (f != &n) {
+ if (n.p) n.p->n = n.n;
+ if (n.n) n.n->p = n.p;
+ if (l == &n) l = n.p;
+ n.p = 0;
+ n.n = f;
+ f->p = &n;
+ f = &n;
+ }
+ return n.t;
+ }
+
+ Q_DISABLE_COPY(QCache)
+
+public:
+ inline explicit QCache(int maxCost = 100);
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT_CONSTRUCTOR QCache(int maxCost, int /* dummy */)
+ : f(0), l(0), mx(maxCost), total(0) {}
+#endif
+ inline ~QCache() { clear(); }
+
+ inline int maxCost() const { return mx; }
+ void setMaxCost(int m);
+ inline int totalCost() const { return total; }
+
+ inline int size() const { return hash.size(); }
+ inline int count() const { return hash.size(); }
+ inline bool isEmpty() const { return hash.isEmpty(); }
+ inline QList<Key> keys() const { return hash.keys(); }
+
+ void clear();
+
+ bool insert(const Key &key, T *object, int cost = 1);
+ T *object(const Key &key) const;
+ inline bool contains(const Key &key) const { return hash.contains(key); }
+ T *operator[](const Key &key) const;
+
+ bool remove(const Key &key);
+ T *take(const Key &key);
+
+private:
+ void trim(int m);
+
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT T *find(const Key &key) const { return object(key); }
+#endif
+
+};
+
+template <class Key, class T>
+inline QCache<Key, T>::QCache(int amaxCost)
+ : f(0), l(0), unused(0), mx(amaxCost), total(0) {}
+
+template <class Key, class T>
+inline void QCache<Key,T>::clear()
+{ while (f) { delete f->t; f = f->n; }
+ hash.clear(); l = 0; total = 0; }
+
+template <class Key, class T>
+inline void QCache<Key,T>::setMaxCost(int m)
+{ mx = m; trim(mx); }
+
+template <class Key, class T>
+inline T *QCache<Key,T>::object(const Key &key) const
+{ return const_cast<QCache<Key,T>*>(this)->relink(key); }
+
+template <class Key, class T>
+inline T *QCache<Key,T>::operator[](const Key &key) const
+{ return object(key); }
+
+template <class Key, class T>
+inline bool QCache<Key,T>::remove(const Key &key)
+{
+ typename QHash<Key, Node>::iterator i = hash.find(key);
+ if (typename QHash<Key, Node>::const_iterator(i) == hash.constEnd()) {
+ return false;
+ } else {
+ unlink(*i);
+ return true;
+ }
+}
+
+template <class Key, class T>
+inline T *QCache<Key,T>::take(const Key &key)
+{
+ typename QHash<Key, Node>::iterator i = hash.find(key);
+ if (i == hash.end())
+ return 0;
+
+ Node &n = *i;
+ T *t = n.t;
+ n.t = 0;
+ unlink(n);
+ return t;
+}
+
+template <class Key, class T>
+bool QCache<Key,T>::insert(const Key &akey, T *aobject, int acost)
+{
+ remove(akey);
+ if (acost > mx) {
+ delete aobject;
+ return false;
+ }
+ trim(mx - acost);
+ Node sn(aobject, acost);
+ typename QHash<Key, Node>::iterator i = hash.insert(akey, sn);
+ total += acost;
+ Node *n = &i.value();
+ n->keyPtr = &i.key();
+ if (f) f->p = n;
+ n->n = f;
+ f = n;
+ if (!l) l = f;
+ return true;
+}
+
+template <class Key, class T>
+void QCache<Key,T>::trim(int m)
+{
+ Node *n = l;
+ while (n && total > m) {
+ Node *u = n;
+ n = n->p;
+ if (qIsDetached(*u->t))
+ unlink(*u);
+ }
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QCACHE_H
diff --git a/src/corelib/tools/qcache.qdoc b/src/corelib/tools/qcache.qdoc
new file mode 100644
index 0000000000..9e12c92c1c
--- /dev/null
+++ b/src/corelib/tools/qcache.qdoc
@@ -0,0 +1,230 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Free Documentation License
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of this
+** file.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QCache
+ \brief The QCache class is a template class that provides a cache.
+
+ \ingroup tools
+ \ingroup shared
+
+ \reentrant
+
+ QCache\<Key, T\> defines a cache that stores objects of type T
+ associated with keys of type Key. For example, here's the
+ definition of a cache that stores objects of type Employee
+ associated with an integer key:
+
+ \snippet doc/src/snippets/code/doc_src_qcache.cpp 0
+
+ Here's how to insert an object in the cache:
+
+ \snippet doc/src/snippets/code/doc_src_qcache.cpp 1
+
+ The advantage of using QCache over some other key-based data
+ structure (such as QMap or QHash) is that QCache automatically
+ takes ownership of the objects that are inserted into the cache and
+ deletes them to make room for new objects, if necessary. When
+ inserting an object into the cache, you can specify a \e{cost},
+ which should bear some approximate relationship to the amount of
+ memory taken by the object. When the sum of all objects' costs
+ (totalCost()) exceeds the cache's limit (maxCost()), QCache starts
+ deleting objects in the cache to keep under the limit, starting with
+ less recently accessed objects.
+
+ By default, QCache's maxCost() is 100. You can specify a
+ different value in the QCache constructor:
+
+ \snippet doc/src/snippets/code/doc_src_qcache.cpp 2
+
+ Each time you call insert(), you can specify a cost as third
+ argument (after the key and a pointer to the object to insert).
+ After the call, the inserted object is owned by the QCache, which
+ may delete it at any time to make room for other objects.
+
+ To look up objects in the cache, use object() or
+ operator[](). This function looks up an object by its key, and
+ returns either a pointer to the cached object (which is owned by
+ the cache) or 0.
+
+ If you want to remove an object from the cache for a particular key,
+ call remove(). This will also delete the object. If you want to
+ remove an object from the cache without the QCache deleting it, use
+ take().
+
+ \sa QPixmapCache, QHash, QMap
+*/
+
+/*! \fn QCache::QCache(int maxCost = 100)
+
+ Constructs a cache whose contents will never have a total cost
+ greater than \a maxCost.
+*/
+
+/*! \fn QCache::~QCache()
+
+ Destroys the cache. Deletes all the objects in the cache.
+*/
+
+/*! \fn int QCache::maxCost() const
+
+ Returns the maximum allowed total cost of the cache.
+
+ \sa setMaxCost(), totalCost()
+*/
+
+/*! \fn void QCache::setMaxCost(int cost)
+
+ Sets the maximum allowed total cost of the cache to \a cost. If
+ the current total cost is greater than \a cost, some objects are
+ deleted immediately.
+
+ \sa maxCost(), totalCost()
+*/
+
+/*! \fn int QCache::totalCost() const
+
+ Returns the total cost of the objects in the cache.
+
+ This value is normally below maxCost(), but QCache makes an
+ exception for Qt's \l{implicitly shared} classes. If a cached
+ object shares its internal data with another instance, QCache may
+ keep the object lying around, possibly contributing to making
+ totalCost() larger than maxCost().
+
+ \sa setMaxCost()
+*/
+
+/*! \fn int QCache::size() const
+
+ Returns the number of objects in the cache.
+
+ \sa isEmpty()
+*/
+
+/*! \fn int QCache::count() const
+
+ Same as size().
+*/
+
+/*! \fn bool QCache::isEmpty() const
+
+ Returns true if the cache contains no objects; otherwise
+ returns false.
+
+ \sa size()
+*/
+
+/*! \fn QList<Key> QCache::keys() const
+
+ Returns a list of the keys in the cache.
+*/
+
+/*! \fn void QCache::clear();
+
+ Deletes all the objects in the cache.
+
+ \sa remove(), take()
+*/
+
+
+/*! \fn bool QCache::insert(const Key &key, T *object, int cost = 1)
+
+ Inserts \a object into the cache with key \a key and
+ associated cost \a cost. Any object with the same key already in
+ the cache will be removed.
+
+ After this call, \a object is owned by the QCache and may be
+ deleted at any time. In particular, if \a cost is greater than
+ maxCost(), the object will be deleted immediately.
+
+ The function returns true if the object was inserted into the
+ cache; otherwise it returns false.
+
+ \sa take(), remove()
+*/
+
+/*! \fn T *QCache::object(const Key &key) const
+
+ Returns the object associated with key \a key, or 0 if the key does
+ not exist in the cache.
+
+ \warning The returned object is owned by QCache and may be
+ deleted at any time.
+
+ \sa take(), remove()
+*/
+
+/*! \fn bool QCache::contains(const Key &key) const
+
+ Returns true if the cache contains an object associated with key \a
+ key; otherwise returns false.
+
+ \sa take(), remove()
+*/
+
+/*! \fn T *QCache::operator[](const Key &key) const
+
+ Returns the object associated with key \a key, or 0 if the key does
+ not exist in the cache.
+
+ This is the same as object().
+
+ \warning The returned object is owned by QCache and may be
+ deleted at any time.
+*/
+
+/*! \fn bool QCache::remove(const Key &key)
+
+ Deletes the object associated with key \a key. Returns true if the
+ object was found in the cache; otherwise returns false.
+
+ \sa take(), clear()
+*/
+
+/*! \fn T *QCache::take(const Key &key)
+
+ Takes the object associated with key \a key out of the cache
+ without deleting it. Returns a pointer to the object taken out, or
+ 0 if the key does not exist in the cache.
+
+ The ownership of the returned object is passed to the caller.
+
+ \sa remove()
+*/
+
+/*!
+ \fn QCache::QCache(int maxCost, int dummy)
+
+ Use QCache(int) instead.
+*/
+
+/*!
+ \fn T *QCache::find(const Key &key) const
+
+ Use object() instead.
+*/
diff --git a/src/corelib/tools/qchar.cpp b/src/corelib/tools/qchar.cpp
new file mode 100644
index 0000000000..a9030074b3
--- /dev/null
+++ b/src/corelib/tools/qchar.cpp
@@ -0,0 +1,1654 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// Don't define it while compiling this module, or USERS of Qt will
+// not be able to link.
+#ifdef QT_NO_CAST_FROM_ASCII
+# undef QT_NO_CAST_FROM_ASCII
+#endif
+#ifdef QT_NO_CAST_TO_ASCII
+# undef QT_NO_CAST_TO_ASCII
+#endif
+#include "qchar.h"
+
+#include "qdatastream.h"
+#include "qtextcodec.h"
+
+#include "qunicodetables_p.h"
+#include "qunicodetables.cpp"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_CODEC_FOR_C_STRINGS
+# ifdef QT_NO_TEXTCODEC
+# define QT_NO_CODEC_FOR_C_STRINGS
+# endif
+#endif
+
+#define FLAG(x) (1 << (x))
+
+/*!
+ \class QLatin1Char
+ \brief The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
+
+ \ingroup string-processing
+
+ This class is only useful to avoid the codec for C strings business
+ in the QChar(ch) constructor. You can avoid it by writing
+ QChar(ch, 0).
+
+ \sa QChar, QLatin1String, QString
+*/
+
+/*!
+ \fn const char QLatin1Char::toLatin1() const
+
+ Converts a Latin-1 character to an 8-bit ASCII representation of
+ the character.
+*/
+
+/*!
+ \fn const ushort QLatin1Char::unicode() const
+
+ Converts a Latin-1 character to an 16-bit-encoded Unicode representation
+ of the character.
+*/
+
+/*!
+ \fn QLatin1Char::QLatin1Char(char c)
+
+ Constructs a Latin-1 character for \a c. This constructor should be
+ used when the encoding of the input character is known to be Latin-1.
+*/
+
+/*!
+ \class QChar
+ \brief The QChar class provides a 16-bit Unicode character.
+
+ \ingroup string-processing
+ \reentrant
+
+ In Qt, Unicode characters are 16-bit entities without any markup
+ or structure. This class represents such an entity. It is
+ lightweight, so it can be used everywhere. Most compilers treat
+ it like a \c{unsigned short}.
+
+ QChar provides a full complement of testing/classification
+ functions, converting to and from other formats, converting from
+ composed to decomposed Unicode, and trying to compare and
+ case-convert if you ask it to.
+
+ The classification functions include functions like those in the
+ standard C++ header \<cctype\> (formerly \<ctype.h\>), but
+ operating on the full range of Unicode characters. They all
+ return true if the character is a certain type of character;
+ otherwise they return false. These classification functions are
+ isNull() (returns true if the character is '\\0'), isPrint()
+ (true if the character is any sort of printable character,
+ including whitespace), isPunct() (any sort of punctation),
+ isMark() (Unicode Mark), isLetter() (a letter), isNumber() (any
+ sort of numeric character, not just 0-9), isLetterOrNumber(), and
+ isDigit() (decimal digits). All of these are wrappers around
+ category() which return the Unicode-defined category of each
+ character.
+
+ QChar also provides direction(), which indicates the "natural"
+ writing direction of this character. The joining() function
+ indicates how the character joins with its neighbors (needed
+ mostly for Arabic) and finally hasMirrored(), which indicates
+ whether the character needs to be mirrored when it is printed in
+ its "unnatural" writing direction.
+
+ Composed Unicode characters (like \aring) can be converted to
+ decomposed Unicode ("a" followed by "ring above") by using
+ decomposition().
+
+ In Unicode, comparison is not necessarily possible and case
+ conversion is very difficult at best. Unicode, covering the
+ "entire" world, also includes most of the world's case and
+ sorting problems. operator==() and friends will do comparison
+ based purely on the numeric Unicode value (code point) of the
+ characters, and toUpper() and toLower() will do case changes when
+ the character has a well-defined uppercase/lowercase equivalent.
+ For locale-dependent comparisons, use
+ QString::localeAwareCompare().
+
+ The conversion functions include unicode() (to a scalar),
+ toLatin1() (to scalar, but converts all non-Latin-1 characters to
+ 0), row() (gives the Unicode row), cell() (gives the Unicode
+ cell), digitValue() (gives the integer value of any of the
+ numerous digit characters), and a host of constructors.
+
+ QChar provides constructors and cast operators that make it easy
+ to convert to and from traditional 8-bit \c{char}s. If you
+ defined \c QT_NO_CAST_FROM_ASCII and \c QT_NO_CAST_TO_ASCII, as
+ explained in the QString documentation, you will need to
+ explicitly call fromAscii() or fromLatin1(), or use QLatin1Char,
+ to construct a QChar from an 8-bit \c char, and you will need to
+ call toAscii() or toLatin1() to get the 8-bit value back.
+
+ \sa QString, Unicode, QLatin1Char
+*/
+
+/*!
+ \enum QChar::UnicodeVersion
+
+ Specifies which version of the \l{http://www.unicode.org/}{Unicode standard}
+ introduced a certain character.
+
+ \value Unicode_1_1 Version 1.1
+ \value Unicode_2_0 Version 2.0
+ \value Unicode_2_1_2 Version 2.1.2
+ \value Unicode_3_0 Version 3.0
+ \value Unicode_3_1 Version 3.1
+ \value Unicode_3_2 Version 3.2
+ \value Unicode_4_0 Version 4.0
+ \value Unicode_4_1 Version 4.1
+ \value Unicode_5_0 Version 5.0
+ \value Unicode_Unassigned The value is not assigned to any character
+ in version 5.0 of Unicode.
+
+ \sa unicodeVersion()
+*/
+
+/*!
+ \enum QChar::Category
+
+ This enum maps the Unicode character categories.
+
+ The following characters are normative in Unicode:
+
+ \value Mark_NonSpacing Unicode class name Mn
+
+ \value Mark_SpacingCombining Unicode class name Mc
+
+ \value Mark_Enclosing Unicode class name Me
+
+ \value Number_DecimalDigit Unicode class name Nd
+
+ \value Number_Letter Unicode class name Nl
+
+ \value Number_Other Unicode class name No
+
+ \value Separator_Space Unicode class name Zs
+
+ \value Separator_Line Unicode class name Zl
+
+ \value Separator_Paragraph Unicode class name Zp
+
+ \value Other_Control Unicode class name Cc
+
+ \value Other_Format Unicode class name Cf
+
+ \value Other_Surrogate Unicode class name Cs
+
+ \value Other_PrivateUse Unicode class name Co
+
+ \value Other_NotAssigned Unicode class name Cn
+
+
+ The following categories are informative in Unicode:
+
+ \value Letter_Uppercase Unicode class name Lu
+
+ \value Letter_Lowercase Unicode class name Ll
+
+ \value Letter_Titlecase Unicode class name Lt
+
+ \value Letter_Modifier Unicode class name Lm
+
+ \value Letter_Other Unicode class name Lo
+
+ \value Punctuation_Connector Unicode class name Pc
+
+ \value Punctuation_Dash Unicode class name Pd
+
+ \value Punctuation_Open Unicode class name Ps
+
+ \value Punctuation_Close Unicode class name Pe
+
+ \value Punctuation_InitialQuote Unicode class name Pi
+
+ \value Punctuation_FinalQuote Unicode class name Pf
+
+ \value Punctuation_Other Unicode class name Po
+
+ \value Symbol_Math Unicode class name Sm
+
+ \value Symbol_Currency Unicode class name Sc
+
+ \value Symbol_Modifier Unicode class name Sk
+
+ \value Symbol_Other Unicode class name So
+
+ \value NoCategory Qt cannot find an appropriate category for the character.
+
+ \omitvalue Punctuation_Dask
+
+ \sa category()
+*/
+
+/*!
+ \enum QChar::Direction
+
+ This enum type defines the Unicode direction attributes. See the
+ \l{http://www.unicode.org/}{Unicode Standard} for a description
+ of the values.
+
+ In order to conform to C/C++ naming conventions "Dir" is prepended
+ to the codes used in the Unicode Standard.
+
+ \value DirAL
+ \value DirAN
+ \value DirB
+ \value DirBN
+ \value DirCS
+ \value DirEN
+ \value DirES
+ \value DirET
+ \value DirL
+ \value DirLRE
+ \value DirLRO
+ \value DirNSM
+ \value DirON
+ \value DirPDF
+ \value DirR
+ \value DirRLE
+ \value DirRLO
+ \value DirS
+ \value DirWS
+
+ \sa direction()
+*/
+
+/*!
+ \enum QChar::Decomposition
+
+ This enum type defines the Unicode decomposition attributes. See
+ the \l{http://www.unicode.org/}{Unicode Standard} for a
+ description of the values.
+
+ \value NoDecomposition
+ \value Canonical
+ \value Circle
+ \value Compat
+ \value Final
+ \value Font
+ \value Fraction
+ \value Initial
+ \value Isolated
+ \value Medial
+ \value Narrow
+ \value NoBreak
+ \value Small
+ \value Square
+ \value Sub
+ \value Super
+ \value Vertical
+ \value Wide
+
+ \omitvalue Single
+
+ \sa decomposition()
+*/
+
+/*!
+ \enum QChar::Joining
+
+ This enum type defines the Unicode joining attributes. See the
+ \l{http://www.unicode.org/}{Unicode Standard} for a description
+ of the values.
+
+ \value Center
+ \value Dual
+ \value OtherJoining
+ \value Right
+
+ \sa joining()
+*/
+
+/*!
+ \enum QChar::CombiningClass
+
+ \internal
+
+ This enum type defines names for some of the Unicode combining
+ classes. See the \l{http://www.unicode.org/}{Unicode Standard}
+ for a description of the values.
+
+ \value Combining_Above
+ \value Combining_AboveAttached
+ \value Combining_AboveLeft
+ \value Combining_AboveLeftAttached
+ \value Combining_AboveRight
+ \value Combining_AboveRightAttached
+ \value Combining_Below
+ \value Combining_BelowAttached
+ \value Combining_BelowLeft
+ \value Combining_BelowLeftAttached
+ \value Combining_BelowRight
+ \value Combining_BelowRightAttached
+ \value Combining_DoubleAbove
+ \value Combining_DoubleBelow
+ \value Combining_IotaSubscript
+ \value Combining_Left
+ \value Combining_LeftAttached
+ \value Combining_Right
+ \value Combining_RightAttached
+*/
+
+/*!
+ \enum QChar::SpecialCharacter
+
+ \value Null A QChar with this value isNull().
+ \value Nbsp Non-breaking space.
+ \value ReplacementCharacter The character shown when a font has no glyph
+ for a certain codepoint. A special question mark character is often
+ used. Codecs use this codepoint when input data cannot be
+ represented in Unicode.
+ \value ObjectReplacementCharacter Used to represent an object such as an
+ image when such objects cannot be presented.
+ \value ByteOrderMark
+ \value ByteOrderSwapped
+ \value ParagraphSeparator
+ \value LineSeparator
+
+ \omitvalue null
+ \omitvalue replacement
+ \omitvalue byteOrderMark
+ \omitvalue byteOrderSwapped
+ \omitvalue nbsp
+*/
+
+/*!
+ \fn void QChar::setCell(uchar cell)
+ \internal
+*/
+
+/*!
+ \fn void QChar::setRow(uchar row)
+ \internal
+*/
+
+/*!
+ \fn QChar::QChar()
+
+ Constructs a null QChar ('\\0').
+
+ \sa isNull()
+*/
+
+/*!
+ \fn QChar::QChar(QLatin1Char ch)
+
+ Constructs a QChar corresponding to ASCII/Latin-1 character \a ch.
+*/
+
+/*!
+ \fn QChar::QChar(SpecialCharacter ch)
+
+ Constructs a QChar for the predefined character value \a ch.
+*/
+
+/*!
+ Constructs a QChar corresponding to ASCII/Latin-1 character \a
+ ch.
+*/
+QChar::QChar(char ch)
+{
+#ifndef QT_NO_CODEC_FOR_C_STRINGS
+ if (QTextCodec::codecForCStrings())
+ // #####
+ ucs = QTextCodec::codecForCStrings()->toUnicode(&ch, 1).at(0).unicode();
+ else
+#endif
+ ucs = uchar(ch);
+}
+
+/*!
+ Constructs a QChar corresponding to ASCII/Latin-1 character \a ch.
+*/
+QChar::QChar(uchar ch)
+{
+#ifndef QT_NO_CODEC_FOR_C_STRINGS
+ if (QTextCodec::codecForCStrings()) {
+ // #####
+ char c = char(ch);
+ ucs = QTextCodec::codecForCStrings()->toUnicode(&c, 1).at(0).unicode();
+ } else
+#endif
+ ucs = ch;
+}
+
+/*!
+ \fn QChar::QChar(uchar cell, uchar row)
+
+ Constructs a QChar for Unicode cell \a cell in row \a row.
+
+ \sa cell(), row()
+*/
+
+/*!
+ \fn QChar::QChar(ushort code)
+
+ Constructs a QChar for the character with Unicode code point \a
+ code.
+*/
+
+
+/*!
+ \fn QChar::QChar(short code)
+
+ Constructs a QChar for the character with Unicode code point \a
+ code.
+*/
+
+
+/*!
+ \fn QChar::QChar(uint code)
+
+ Constructs a QChar for the character with Unicode code point \a
+ code.
+*/
+
+
+/*!
+ \fn QChar::QChar(int code)
+
+ Constructs a QChar for the character with Unicode code point \a
+ code.
+*/
+
+
+/*!
+ \fn bool QChar::isNull() const
+
+ Returns true if the character is the Unicode character 0x0000
+ ('\\0'); otherwise returns false.
+*/
+
+/*!
+ \fn uchar QChar::cell() const
+
+ Returns the cell (least significant byte) of the Unicode
+ character.
+
+ \sa row()
+*/
+
+/*!
+ \fn uchar QChar::row() const
+
+ Returns the row (most significant byte) of the Unicode character.
+
+ \sa cell()
+*/
+
+/*!
+ Returns true if the character is a printable character; otherwise
+ returns false. This is any character not of category Cc or Cn.
+
+ Note that this gives no indication of whether the character is
+ available in a particular font.
+*/
+bool QChar::isPrint() const
+{
+ const int test = FLAG(Other_Control) |
+ FLAG(Other_NotAssigned);
+ return !(FLAG(qGetProp(ucs)->category) & test);
+}
+
+/*!
+ Returns true if the character is a separator character
+ (Separator_* categories); otherwise returns false.
+*/
+bool QChar::isSpace() const
+{
+ if(ucs >= 9 && ucs <=13)
+ return true;
+ const int test = FLAG(Separator_Space) |
+ FLAG(Separator_Line) |
+ FLAG(Separator_Paragraph);
+ return FLAG(qGetProp(ucs)->category) & test;
+}
+
+/*!
+ Returns true if the character is a mark (Mark_* categories);
+ otherwise returns false.
+
+ See QChar::Category for more information regarding marks.
+*/
+bool QChar::isMark() const
+{
+ const int test = FLAG(Mark_NonSpacing) |
+ FLAG(Mark_SpacingCombining) |
+ FLAG(Mark_Enclosing);
+ return FLAG(qGetProp(ucs)->category) & test;
+}
+
+/*!
+ Returns true if the character is a punctuation mark (Punctuation_*
+ categories); otherwise returns false.
+*/
+bool QChar::isPunct() const
+{
+ const int test = FLAG(Punctuation_Connector) |
+ FLAG(Punctuation_Dash) |
+ FLAG(Punctuation_Open) |
+ FLAG(Punctuation_Close) |
+ FLAG(Punctuation_InitialQuote) |
+ FLAG(Punctuation_FinalQuote) |
+ FLAG(Punctuation_Other);
+ return FLAG(qGetProp(ucs)->category) & test;
+}
+
+/*!
+ Returns true if the character is a letter (Letter_* categories);
+ otherwise returns false.
+*/
+bool QChar::isLetter() const
+{
+ const int test = FLAG(Letter_Uppercase) |
+ FLAG(Letter_Lowercase) |
+ FLAG(Letter_Titlecase) |
+ FLAG(Letter_Modifier) |
+ FLAG(Letter_Other);
+ return FLAG(qGetProp(ucs)->category) & test;
+}
+
+/*!
+ Returns true if the character is a number (Number_* categories,
+ not just 0-9); otherwise returns false.
+
+ \sa isDigit()
+*/
+bool QChar::isNumber() const
+{
+ const int test = FLAG(Number_DecimalDigit) |
+ FLAG(Number_Letter) |
+ FLAG(Number_Other);
+ return FLAG(qGetProp(ucs)->category) & test;
+}
+
+/*!
+ Returns true if the character is a letter or number (Letter_* or
+ Number_* categories); otherwise returns false.
+*/
+bool QChar::isLetterOrNumber() const
+{
+ const int test = FLAG(Letter_Uppercase) |
+ FLAG(Letter_Lowercase) |
+ FLAG(Letter_Titlecase) |
+ FLAG(Letter_Modifier) |
+ FLAG(Letter_Other) |
+ FLAG(Number_DecimalDigit) |
+ FLAG(Number_Letter) |
+ FLAG(Number_Other);
+ return FLAG(qGetProp(ucs)->category) & test;
+}
+
+
+/*!
+ Returns true if the character is a decimal digit
+ (Number_DecimalDigit); otherwise returns false.
+*/
+bool QChar::isDigit() const
+{
+ return (qGetProp(ucs)->category == Number_DecimalDigit);
+}
+
+
+/*!
+ Returns true if the character is a symbol (Symbol_* categories);
+ otherwise returns false.
+*/
+bool QChar::isSymbol() const
+{
+ const int test = FLAG(Symbol_Math) |
+ FLAG(Symbol_Currency) |
+ FLAG(Symbol_Modifier) |
+ FLAG(Symbol_Other);
+ return FLAG(qGetProp(ucs)->category) & test;
+}
+
+/*!
+ \fn bool QChar::isHighSurrogate() const
+
+ Returns true if the QChar is the high part of a utf16 surrogate
+ (ie. if its code point is between 0xd800 and 0xdbff, inclusive).
+*/
+
+/*!
+ \fn bool QChar::isLowSurrogate() const
+
+ Returns true if the QChar is the low part of a utf16 surrogate
+ (ie. if its code point is between 0xdc00 and 0xdfff, inclusive).
+*/
+
+/*!
+ \fn static bool QChar::isHighSurrogate(uint ucs4)
+ \since 4.7
+
+ Returns true if the UCS-4-encoded character specified by \a ucs4
+ is the high part of a utf16 surrogate
+ (ie. if its code point is between 0xd800 and 0xdbff, inclusive).
+*/
+
+/*!
+ \fn static bool QChar::isLowSurrogate(uint ucs4)
+ \since 4.7
+
+ Returns true if the UCS-4-encoded character specified by \a ucs4
+ is the low part of a utf16 surrogate
+ (ie. if its code point is between 0xdc00 and 0xdfff, inclusive).
+*/
+
+/*!
+ \fn static bool QChar::requiresSurrogates(uint ucs4)
+ \since 4.7
+
+ Returns true if the UCS-4-encoded character specified by \a ucs4
+ can be split into the high and low parts of a utf16 surrogate
+ (ie. if its code point is greater than or equals to 0x10000).
+*/
+
+/*!
+ \fn static uint QChar::surrogateToUcs4(ushort high, ushort low)
+
+ Converts a UTF16 surrogate pair with the given \a high and \a low values
+ to its UCS-4 code point.
+*/
+
+/*!
+ \fn static uint QChar::surrogateToUcs4(QChar high, QChar low)
+
+ Converts a utf16 surrogate pair (\a high, \a low) to its ucs4 code point.
+*/
+
+/*!
+ \fn static ushort QChar::highSurrogate(uint ucs4)
+
+ Returns the high surrogate value of a ucs4 code point.
+ The returned result is undefined if \a ucs4 is smaller than 0x10000.
+*/
+
+/*!
+ \fn static ushort QChar::lowSurrogate(uint ucs4)
+
+ Returns the low surrogate value of a ucs4 code point.
+ The returned result is undefined if \a ucs4 is smaller than 0x10000.
+*/
+
+/*!
+ Returns the numeric value of the digit, or -1 if the character is
+ not a digit.
+*/
+int QChar::digitValue() const
+{
+ return qGetProp(ucs)->digitValue;
+}
+
+/*!
+ \overload
+ Returns the numeric value of the digit, specified by the UCS-2-encoded
+ character, \a ucs2, or -1 if the character is not a digit.
+*/
+int QChar::digitValue(ushort ucs2)
+{
+ return qGetProp(ucs2)->digitValue;
+}
+
+/*!
+ \overload
+ Returns the numeric value of the digit specified by the UCS-4-encoded
+ character, \a ucs4, or -1 if the character is not a digit.
+*/
+int QChar::digitValue(uint ucs4)
+{
+ if (ucs4 > UNICODE_LAST_CODEPOINT)
+ return 0;
+ return qGetProp(ucs4)->digitValue;
+}
+
+/*!
+ Returns the character's category.
+*/
+QChar::Category QChar::category() const
+{
+ return (QChar::Category) qGetProp(ucs)->category;
+}
+
+/*!
+ \overload
+ \since 4.3
+ Returns the category of the UCS-4-encoded character specified by \a ucs4.
+*/
+QChar::Category QChar::category(uint ucs4)
+{
+ if (ucs4 > UNICODE_LAST_CODEPOINT)
+ return QChar::NoCategory;
+ return (QChar::Category) qGetProp(ucs4)->category;
+}
+
+/*!
+ \overload
+ Returns the category of the UCS-2-encoded character specified by \a ucs2.
+*/
+QChar::Category QChar::category(ushort ucs2)
+{
+ return (QChar::Category) qGetProp(ucs2)->category;
+}
+
+
+/*!
+ Returns the character's direction.
+*/
+QChar::Direction QChar::direction() const
+{
+ return (QChar::Direction) qGetProp(ucs)->direction;
+}
+
+/*!
+ \overload
+ Returns the direction of the UCS-4-encoded character specified by \a ucs4.
+*/
+QChar::Direction QChar::direction(uint ucs4)
+{
+ if (ucs4 > UNICODE_LAST_CODEPOINT)
+ return QChar::DirL;
+ return (QChar::Direction) qGetProp(ucs4)->direction;
+}
+
+/*!
+ \overload
+ Returns the direction of the UCS-2-encoded character specified by \a ucs2.
+*/
+QChar::Direction QChar::direction(ushort ucs2)
+{
+ return (QChar::Direction) qGetProp(ucs2)->direction;
+}
+
+/*!
+ Returns information about the joining properties of the character
+ (needed for certain languages such as Arabic).
+*/
+QChar::Joining QChar::joining() const
+{
+ return (QChar::Joining) qGetProp(ucs)->joining;
+}
+
+/*!
+ \overload
+ Returns information about the joining properties of the UCS-4-encoded
+ character specified by \a ucs4 (needed for certain languages such as
+ Arabic).
+*/
+QChar::Joining QChar::joining(uint ucs4)
+{
+ if (ucs4 > UNICODE_LAST_CODEPOINT)
+ return QChar::OtherJoining;
+ return (QChar::Joining) qGetProp(ucs4)->joining;
+}
+
+/*!
+ \overload
+ Returns information about the joining properties of the UCS-2-encoded
+ character specified by \a ucs2 (needed for certain languages such as
+ Arabic).
+*/
+QChar::Joining QChar::joining(ushort ucs2)
+{
+ return (QChar::Joining) qGetProp(ucs2)->joining;
+}
+
+
+/*!
+ Returns true if the character should be reversed if the text
+ direction is reversed; otherwise returns false.
+
+ Same as (ch.mirroredChar() != ch).
+
+ \sa mirroredChar()
+*/
+bool QChar::hasMirrored() const
+{
+ return qGetProp(ucs)->mirrorDiff != 0;
+}
+
+/*!
+ \fn bool QChar::isLower() const
+
+ Returns true if the character is a lowercase letter, i.e.
+ category() is Letter_Lowercase.
+
+ \sa isUpper(), toLower(), toUpper()
+*/
+
+/*!
+ \fn bool QChar::isUpper() const
+
+ Returns true if the character is an uppercase letter, i.e.
+ category() is Letter_Uppercase.
+
+ \sa isLower(), toUpper(), toLower()
+*/
+
+/*!
+ \fn bool QChar::isTitleCase() const
+ \since 4.3
+
+ Returns true if the character is a titlecase letter, i.e.
+ category() is Letter_Titlecase.
+
+ \sa isLower(), toUpper(), toLower(), toTitleCase()
+*/
+
+/*!
+ Returns the mirrored character if this character is a mirrored
+ character; otherwise returns the character itself.
+
+ \sa hasMirrored()
+*/
+QChar QChar::mirroredChar() const
+{
+ return ucs + qGetProp(ucs)->mirrorDiff;
+}
+
+/*!
+ \overload
+ Returns the mirrored character if the UCS-4-encoded character specified
+ by \a ucs4 is a mirrored character; otherwise returns the character itself.
+
+ \sa hasMirrored()
+*/
+uint QChar::mirroredChar(uint ucs4)
+{
+ if (ucs4 > UNICODE_LAST_CODEPOINT)
+ return ucs4;
+ return ucs4 + qGetProp(ucs4)->mirrorDiff;
+}
+
+/*!
+ \overload
+ Returns the mirrored character if the UCS-2-encoded character specified
+ by \a ucs2 is a mirrored character; otherwise returns the character itself.
+
+ \sa hasMirrored()
+*/
+ushort QChar::mirroredChar(ushort ucs2)
+{
+ return ucs2 + qGetProp(ucs2)->mirrorDiff;
+}
+
+
+enum {
+ Hangul_SBase = 0xac00,
+ Hangul_LBase = 0x1100,
+ Hangul_VBase = 0x1161,
+ Hangul_TBase = 0x11a7,
+ Hangul_SCount = 11172,
+ Hangul_LCount = 19,
+ Hangul_VCount = 21,
+ Hangul_TCount = 28,
+ Hangul_NCount = 21*28
+};
+
+// buffer has to have a length of 3. It's needed for Hangul decomposition
+static const unsigned short * QT_FASTCALL decompositionHelper
+ (uint ucs4, int *length, int *tag, unsigned short *buffer)
+{
+ *length = 0;
+ if (ucs4 > UNICODE_LAST_CODEPOINT)
+ return 0;
+ if (ucs4 >= Hangul_SBase && ucs4 < Hangul_SBase + Hangul_SCount) {
+ int SIndex = ucs4 - Hangul_SBase;
+ buffer[0] = Hangul_LBase + SIndex / Hangul_NCount; // L
+ buffer[1] = Hangul_VBase + (SIndex % Hangul_NCount) / Hangul_TCount; // V
+ buffer[2] = Hangul_TBase + SIndex % Hangul_TCount; // T
+ *length = buffer[2] == Hangul_TBase ? 2 : 3;
+ *tag = QChar::Canonical;
+ return buffer;
+ }
+
+ const unsigned short index = GET_DECOMPOSITION_INDEX(ucs4);
+ if (index == 0xffff)
+ return 0;
+ const unsigned short *decomposition = uc_decomposition_map+index;
+ *tag = (*decomposition) & 0xff;
+ *length = (*decomposition) >> 8;
+ return decomposition+1;
+}
+
+/*!
+ Decomposes a character into its parts. Returns an empty string if
+ no decomposition exists.
+*/
+QString QChar::decomposition() const
+{
+ return decomposition(ucs);
+}
+
+/*!
+ \overload
+ Decomposes the UCS-4-encoded character specified by \a ucs4 into its
+ constituent parts. Returns an empty string if no decomposition exists.
+*/
+QString QChar::decomposition(uint ucs4)
+{
+ unsigned short buffer[3];
+ int length;
+ int tag;
+ const unsigned short *d = decompositionHelper(ucs4, &length, &tag, buffer);
+ return QString::fromUtf16(d, length);
+}
+
+/*!
+ Returns the tag defining the composition of the character. Returns
+ QChar::Single if no decomposition exists.
+*/
+QChar::Decomposition QChar::decompositionTag() const
+{
+ return decompositionTag(ucs);
+}
+
+/*!
+ \overload
+ Returns the tag defining the composition of the UCS-4-encoded character
+ specified by \a ucs4. Returns QChar::Single if no decomposition exists.
+*/
+QChar::Decomposition QChar::decompositionTag(uint ucs4)
+{
+ if (ucs4 > UNICODE_LAST_CODEPOINT)
+ return QChar::NoDecomposition;
+ const unsigned short index = GET_DECOMPOSITION_INDEX(ucs4);
+ if (index == 0xffff)
+ return QChar::NoDecomposition;
+ return (QChar::Decomposition)(uc_decomposition_map[index] & 0xff);
+}
+
+/*!
+ Returns the combining class for the character as defined in the
+ Unicode standard. This is mainly useful as a positioning hint for
+ marks attached to a base character.
+
+ The Qt text rendering engine uses this information to correctly
+ position non-spacing marks around a base character.
+*/
+unsigned char QChar::combiningClass() const
+{
+ return (unsigned char) qGetProp(ucs)->combiningClass;
+}
+
+/*!
+ \overload
+ Returns the combining class for the UCS-4-encoded character specified by
+ \a ucs4, as defined in the Unicode standard.
+*/
+unsigned char QChar::combiningClass(uint ucs4)
+{
+ if (ucs4 > UNICODE_LAST_CODEPOINT)
+ return 0;
+ return (unsigned char) qGetProp(ucs4)->combiningClass;
+}
+
+/*!
+ \overload
+ Returns the combining class for the UCS-2-encoded character specified by
+ \a ucs2, as defined in the Unicode standard.
+*/
+unsigned char QChar::combiningClass(ushort ucs2)
+{
+ return (unsigned char) qGetProp(ucs2)->combiningClass;
+}
+
+/*!
+ Returns the Unicode version that introduced this character.
+*/
+QChar::UnicodeVersion QChar::unicodeVersion() const
+{
+ return (QChar::UnicodeVersion) qGetProp(ucs)->unicodeVersion;
+}
+
+/*!
+ \overload
+ Returns the Unicode version that introduced the character specified in
+ its UCS-4-encoded form as \a ucs4.
+*/
+QChar::UnicodeVersion QChar::unicodeVersion(uint ucs4)
+{
+ if (ucs4 > UNICODE_LAST_CODEPOINT)
+ return QChar::Unicode_Unassigned;
+ return (QChar::UnicodeVersion) qGetProp(ucs4)->unicodeVersion;
+}
+
+/*!
+ \overload
+ Returns the Unicode version that introduced the character specified in
+ its UCS-2-encoded form as \a ucs2.
+*/
+QChar::UnicodeVersion QChar::unicodeVersion(ushort ucs2)
+{
+ return (QChar::UnicodeVersion) qGetProp(ucs2)->unicodeVersion;
+}
+
+/*!
+ \since 4.8
+
+ Returns the most recent supported Unicode version.
+*/
+QChar::UnicodeVersion QChar::currentUnicodeVersion()
+{
+ return UNICODE_DATA_VERSION;
+}
+
+/*!
+ Returns the lowercase equivalent if the character is uppercase or titlecase;
+ otherwise returns the character itself.
+*/
+QChar QChar::toLower() const
+{
+ const QUnicodeTables::Properties *p = qGetProp(ucs);
+ if (!p->lowerCaseSpecial)
+ return ucs + p->lowerCaseDiff;
+ return ucs;
+}
+
+/*!
+ \overload
+ Returns the lowercase equivalent of the UCS-4-encoded character specified
+ by \a ucs4 if the character is uppercase or titlecase; otherwise returns
+ the character itself.
+*/
+uint QChar::toLower(uint ucs4)
+{
+ if (ucs4 > UNICODE_LAST_CODEPOINT)
+ return ucs4;
+ const QUnicodeTables::Properties *p = qGetProp(ucs4);
+ if (!p->lowerCaseSpecial)
+ return ucs4 + p->lowerCaseDiff;
+ return ucs4;
+}
+
+/*!
+ \overload
+ Returns the lowercase equivalent of the UCS-2-encoded character specified
+ by \a ucs2 if the character is uppercase or titlecase; otherwise returns
+ the character itself.
+*/
+ushort QChar::toLower(ushort ucs2)
+{
+ const QUnicodeTables::Properties *p = qGetProp(ucs2);
+ if (!p->lowerCaseSpecial)
+ return ucs2 + p->lowerCaseDiff;
+ return ucs2;
+}
+
+/*!
+ Returns the uppercase equivalent if the character is lowercase or titlecase;
+ otherwise returns the character itself.
+*/
+QChar QChar::toUpper() const
+{
+ const QUnicodeTables::Properties *p = qGetProp(ucs);
+ if (!p->upperCaseSpecial)
+ return ucs + p->upperCaseDiff;
+ return ucs;
+}
+
+/*!
+ \overload
+ Returns the uppercase equivalent of the UCS-4-encoded character specified
+ by \a ucs4 if the character is lowercase or titlecase; otherwise returns
+ the character itself.
+*/
+uint QChar::toUpper(uint ucs4)
+{
+ if (ucs4 > UNICODE_LAST_CODEPOINT)
+ return ucs4;
+ const QUnicodeTables::Properties *p = qGetProp(ucs4);
+ if (!p->upperCaseSpecial)
+ return ucs4 + p->upperCaseDiff;
+ return ucs4;
+}
+
+/*!
+ \overload
+ Returns the uppercase equivalent of the UCS-2-encoded character specified
+ by \a ucs2 if the character is lowercase or titlecase; otherwise returns
+ the character itself.
+*/
+ushort QChar::toUpper(ushort ucs2)
+{
+ const QUnicodeTables::Properties *p = qGetProp(ucs2);
+ if (!p->upperCaseSpecial)
+ return ucs2 + p->upperCaseDiff;
+ return ucs2;
+}
+
+/*!
+ Returns the title case equivalent if the character is lowercase or uppercase;
+ otherwise returns the character itself.
+*/
+QChar QChar::toTitleCase() const
+{
+ const QUnicodeTables::Properties *p = qGetProp(ucs);
+ if (!p->titleCaseSpecial)
+ return ucs + p->titleCaseDiff;
+ return ucs;
+}
+
+/*!
+ \overload
+ Returns the title case equivalent of the UCS-4-encoded character specified
+ by \a ucs4 if the character is lowercase or uppercase; otherwise returns
+ the character itself.
+*/
+uint QChar::toTitleCase(uint ucs4)
+{
+ if (ucs4 > UNICODE_LAST_CODEPOINT)
+ return ucs4;
+ const QUnicodeTables::Properties *p = qGetProp(ucs4);
+ if (!p->titleCaseSpecial)
+ return ucs4 + p->titleCaseDiff;
+ return ucs4;
+}
+
+/*!
+ \overload
+ Returns the title case equivalent of the UCS-2-encoded character specified
+ by \a ucs2 if the character is lowercase or uppercase; otherwise returns
+ the character itself.
+*/
+ushort QChar::toTitleCase(ushort ucs2)
+{
+ const QUnicodeTables::Properties *p = qGetProp(ucs2);
+ if (!p->titleCaseSpecial)
+ return ucs2 + p->titleCaseDiff;
+ return ucs2;
+}
+
+
+static inline uint foldCase(const ushort *ch, const ushort *start)
+{
+ uint c = *ch;
+ if (QChar(c).isLowSurrogate() && ch > start && QChar(*(ch - 1)).isHighSurrogate())
+ c = QChar::surrogateToUcs4(*(ch - 1), c);
+ return *ch + qGetProp(c)->caseFoldDiff;
+}
+
+static inline uint foldCase(uint ch, uint &last)
+{
+ uint c = ch;
+ if (QChar(c).isLowSurrogate() && QChar(last).isHighSurrogate())
+ c = QChar::surrogateToUcs4(last, c);
+ last = ch;
+ return ch + qGetProp(c)->caseFoldDiff;
+}
+
+static inline ushort foldCase(ushort ch)
+{
+ return ch + qGetProp(ch)->caseFoldDiff;
+}
+
+/*!
+ Returns the case folded equivalent of the character. For most Unicode characters this
+ is the same as toLowerCase().
+*/
+QChar QChar::toCaseFolded() const
+{
+ return ucs + qGetProp(ucs)->caseFoldDiff;
+}
+
+/*!
+ \overload
+ Returns the case folded equivalent of the UCS-4-encoded character specified
+ by \a ucs4. For most Unicode characters this is the same as toLowerCase().
+*/
+uint QChar::toCaseFolded(uint ucs4)
+{
+ if (ucs4 > UNICODE_LAST_CODEPOINT)
+ return ucs4;
+ return ucs4 + qGetProp(ucs4)->caseFoldDiff;
+}
+
+/*!
+ \overload
+ Returns the case folded equivalent of the UCS-2-encoded character specified
+ by \a ucs2. For most Unicode characters this is the same as toLowerCase().
+*/
+ushort QChar::toCaseFolded(ushort ucs2)
+{
+ return ucs2 + qGetProp(ucs2)->caseFoldDiff;
+}
+
+
+/*!
+ \fn char QChar::latin1() const
+
+ Use toLatin1() instead.
+*/
+
+/*!
+ \fn char QChar::ascii() const
+
+ Use toAscii() instead.
+*/
+
+/*!
+ \fn char QChar::toLatin1() const
+
+ Returns the Latin-1 character equivalent to the QChar, or 0. This
+ is mainly useful for non-internationalized software.
+
+ \sa toAscii(), unicode(), QTextCodec::codecForCStrings()
+*/
+
+/*!
+ \fn char QChar::toAscii() const
+ Returns the character value of the QChar obtained using the current
+ codec used to read C strings, or 0 if the character is not representable
+ using this codec. The default codec handles Latin-1 encoded text,
+ but this can be changed to assist developers writing source code using
+ other encodings.
+
+ The main purpose of this function is to preserve ASCII characters used
+ in C strings. This is mainly useful for developers of non-internationalized
+ software.
+
+ \sa toLatin1(), unicode(), QTextCodec::codecForCStrings()
+*/
+#ifdef Q_COMPILER_MANGLES_RETURN_TYPE
+const char QChar::toAscii() const
+#else
+char QChar::toAscii() const
+#endif
+{
+#ifndef QT_NO_CODEC_FOR_C_STRINGS
+ if (QTextCodec::codecForCStrings())
+ // #####
+ return QTextCodec::codecForCStrings()->fromUnicode(QString(*this)).at(0);
+#endif
+ return ucs > 0xff ? 0 : char(ucs);
+}
+
+/*!
+ \fn QChar QChar::fromLatin1(char c)
+
+ Converts the Latin-1 character \a c to its equivalent QChar. This
+ is mainly useful for non-internationalized software.
+
+ \sa fromAscii(), unicode(), QTextCodec::codecForCStrings()
+*/
+
+/*!
+ Converts the ASCII character \a c to its equivalent QChar. This
+ is mainly useful for non-internationalized software.
+
+ An alternative is to use QLatin1Char.
+
+ \sa fromLatin1(), unicode(), QTextCodec::codecForCStrings()
+*/
+QChar QChar::fromAscii(char c)
+{
+#ifndef QT_NO_CODEC_FOR_C_STRINGS
+ if (QTextCodec::codecForCStrings())
+ // #####
+ return QTextCodec::codecForCStrings()->toUnicode(&c, 1).at(0).unicode();
+#endif
+ return QChar(ushort((uchar)c));
+}
+
+#ifndef QT_NO_DATASTREAM
+/*!
+ \relates QChar
+
+ Writes the char \a chr to the stream \a out.
+
+ \sa {Serializing Qt Data Types}
+*/
+QDataStream &operator<<(QDataStream &out, const QChar &chr)
+{
+ out << quint16(chr.unicode());
+ return out;
+}
+
+/*!
+ \relates QChar
+
+ Reads a char from the stream \a in into char \a chr.
+
+ \sa {Serializing Qt Data Types}
+*/
+QDataStream &operator>>(QDataStream &in, QChar &chr)
+{
+ quint16 u;
+ in >> u;
+ chr.unicode() = ushort(u);
+ return in;
+}
+#endif // QT_NO_DATASTREAM
+
+/*!
+ \fn ushort & QChar::unicode()
+
+ Returns a reference to the numeric Unicode value of the QChar.
+*/
+
+/*!
+ \fn ushort QChar::unicode() const
+
+ \overload
+*/
+
+/*****************************************************************************
+ Documentation of QChar related functions
+ *****************************************************************************/
+
+/*!
+ \fn bool operator==(QChar c1, QChar c2)
+
+ \relates QChar
+
+ Returns true if \a c1 and \a c2 are the same Unicode character;
+ otherwise returns false.
+*/
+
+/*!
+ \fn int operator!=(QChar c1, QChar c2)
+
+ \relates QChar
+
+ Returns true if \a c1 and \a c2 are not the same Unicode
+ character; otherwise returns false.
+*/
+
+/*!
+ \fn int operator<=(QChar c1, QChar c2)
+
+ \relates QChar
+
+ Returns true if the numeric Unicode value of \a c1 is less than
+ or equal to that of \a c2; otherwise returns false.
+*/
+
+/*!
+ \fn int operator>=(QChar c1, QChar c2)
+
+ \relates QChar
+
+ Returns true if the numeric Unicode value of \a c1 is greater than
+ or equal to that of \a c2; otherwise returns false.
+*/
+
+/*!
+ \fn int operator<(QChar c1, QChar c2)
+
+ \relates QChar
+
+ Returns true if the numeric Unicode value of \a c1 is less than
+ that of \a c2; otherwise returns false.
+*/
+
+/*!
+ \fn int operator>(QChar c1, QChar c2)
+
+ \relates QChar
+
+ Returns true if the numeric Unicode value of \a c1 is greater than
+ that of \a c2; otherwise returns false.
+*/
+
+/*!
+ \fn bool QChar::mirrored() const
+
+ Use hasMirrored() instead.
+*/
+
+/*!
+ \fn QChar QChar::lower() const
+
+ Use toLower() instead.
+*/
+
+/*!
+ \fn QChar QChar::upper() const
+
+ Use toUpper() instead.
+*/
+
+/*!
+ \fn bool QChar::networkOrdered()
+
+ See if QSysInfo::ByteOrder == QSysInfo::BigEndian instead.
+*/
+
+
+// ---------------------------------------------------------------------------
+
+
+static void decomposeHelper(QString *str, bool canonical, QChar::UnicodeVersion version, int from)
+{
+ unsigned short buffer[3];
+
+ QString &s = *str;
+
+ const unsigned short *utf16 = reinterpret_cast<unsigned short *>(s.data());
+ const unsigned short *uc = utf16 + s.length();
+ while (uc != utf16 + from) {
+ uint ucs4 = *(--uc);
+ if (QChar(ucs4).isLowSurrogate() && uc != utf16) {
+ ushort high = *(uc - 1);
+ if (QChar(high).isHighSurrogate()) {
+ --uc;
+ ucs4 = QChar::surrogateToUcs4(high, ucs4);
+ }
+ }
+ if (QChar::unicodeVersion(ucs4) > version)
+ continue;
+ int length;
+ int tag;
+ const unsigned short *d = decompositionHelper(ucs4, &length, &tag, buffer);
+ if (!d || (canonical && tag != QChar::Canonical))
+ continue;
+
+ int pos = uc - utf16;
+ s.replace(pos, QChar::requiresSurrogates(ucs4) ? 2 : 1, reinterpret_cast<const QChar *>(d), length);
+ // since the insert invalidates the pointers and we do decomposition recursive
+ utf16 = reinterpret_cast<unsigned short *>(s.data());
+ uc = utf16 + pos + length;
+ }
+}
+
+
+struct UCS2Pair {
+ ushort u1;
+ ushort u2;
+};
+
+inline bool operator<(ushort u1, const UCS2Pair &ligature)
+{ return u1 < ligature.u1; }
+inline bool operator<(const UCS2Pair &ligature, ushort u1)
+{ return ligature.u1 < u1; }
+
+static ushort ligatureHelper(ushort u1, ushort u2)
+{
+ // hangul L-V pair
+ int LIndex = u1 - Hangul_LBase;
+ if (0 <= LIndex && LIndex < Hangul_LCount) {
+ int VIndex = u2 - Hangul_VBase;
+ if (0 <= VIndex && VIndex < Hangul_VCount)
+ return Hangul_SBase + (LIndex * Hangul_VCount + VIndex) * Hangul_TCount;
+ }
+
+ // hangul LV-T pair
+ int SIndex = u1 - Hangul_SBase;
+ if (0 <= SIndex && SIndex < Hangul_SCount && (SIndex % Hangul_TCount) == 0) {
+ int TIndex = u2 - Hangul_TBase;
+ if (0 <= TIndex && TIndex <= Hangul_TCount)
+ return u1 + TIndex;
+ }
+
+ const unsigned short index = GET_LIGATURE_INDEX(u2);
+ if (index == 0xffff)
+ return 0;
+ const unsigned short *ligatures = uc_ligature_map+index;
+ ushort length = *ligatures++;
+ {
+ const UCS2Pair *data = reinterpret_cast<const UCS2Pair *>(ligatures);
+ const UCS2Pair *r = qBinaryFind(data, data + length, u1);
+ if (r != data + length)
+ return r->u2;
+ }
+
+ return 0;
+}
+
+static void composeHelper(QString *str, int from)
+{
+ QString &s = *str;
+
+ if (s.length() - from < 2)
+ return;
+
+ // the loop can partly ignore high Unicode as all ligatures are in the BMP
+ int starter = 0;
+ int lastCombining = 0;
+ int pos = from;
+ while (pos < s.length()) {
+ uint uc = s.at(pos).unicode();
+ if (QChar(uc).isHighSurrogate() && pos < s.length()-1) {
+ ushort low = s.at(pos+1).unicode();
+ if (QChar(low).isLowSurrogate()) {
+ uc = QChar::surrogateToUcs4(uc, low);
+ ++pos;
+ }
+ }
+ int combining = QChar::combiningClass(uc);
+ if (starter == pos - 1 || combining > lastCombining) {
+ // allowed to form ligature with S
+ QChar ligature = ligatureHelper(s.at(starter).unicode(), uc);
+ if (ligature.unicode()) {
+ s[starter] = ligature;
+ s.remove(pos, 1);
+ continue;
+ }
+ }
+ if (!combining)
+ starter = pos;
+ lastCombining = combining;
+ ++pos;
+ }
+}
+
+
+static void canonicalOrderHelper(QString *str, QChar::UnicodeVersion version, int from)
+{
+ QString &s = *str;
+ const int l = s.length()-1;
+ int pos = from;
+ while (pos < l) {
+ int p2 = pos+1;
+ uint u1 = s.at(pos).unicode();
+ if (QChar(u1).isHighSurrogate()) {
+ ushort low = s.at(p2).unicode();
+ if (QChar(low).isLowSurrogate()) {
+ u1 = QChar::surrogateToUcs4(u1, low);
+ if (p2 >= l)
+ break;
+ ++p2;
+ }
+ }
+ uint u2 = s.at(p2).unicode();
+ if (QChar(u2).isHighSurrogate() && p2 < l) {
+ ushort low = s.at(p2+1).unicode();
+ if (QChar(low).isLowSurrogate()) {
+ u2 = QChar::surrogateToUcs4(u2, low);
+ ++p2;
+ }
+ }
+
+ ushort c2 = 0;
+ {
+ const QUnicodeTables::Properties *p = qGetProp(u2);
+ if ((QChar::UnicodeVersion)p->unicodeVersion <= version)
+ c2 = p->combiningClass;
+ }
+ if (c2 == 0) {
+ pos = p2+1;
+ continue;
+ }
+
+ ushort c1 = 0;
+ {
+ const QUnicodeTables::Properties *p = qGetProp(u1);
+ if ((QChar::UnicodeVersion)p->unicodeVersion <= version)
+ c1 = p->combiningClass;
+ }
+
+ if (c1 > c2) {
+ QChar *uc = s.data();
+ int p = pos;
+ // exchange characters
+ if (!QChar::requiresSurrogates(u2)) {
+ uc[p++] = u2;
+ } else {
+ uc[p++] = QChar::highSurrogate(u2);
+ uc[p++] = QChar::lowSurrogate(u2);
+ }
+ if (!QChar::requiresSurrogates(u1)) {
+ uc[p++] = u1;
+ } else {
+ uc[p++] = QChar::highSurrogate(u1);
+ uc[p++] = QChar::lowSurrogate(u1);
+ }
+ if (pos > 0)
+ --pos;
+ if (pos > 0 && s.at(pos).isLowSurrogate())
+ --pos;
+ } else {
+ ++pos;
+ if (QChar::requiresSurrogates(u1))
+ ++pos;
+ }
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qchar.h b/src/corelib/tools/qchar.h
new file mode 100644
index 0000000000..508053671c
--- /dev/null
+++ b/src/corelib/tools/qchar.h
@@ -0,0 +1,404 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCHAR_H
+#define QCHAR_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QString;
+
+struct QLatin1Char
+{
+public:
+ inline explicit QLatin1Char(char c) : ch(c) {}
+#ifdef Q_COMPILER_MANGLES_RETURN_TYPE
+ inline const char toLatin1() const { return ch; }
+ inline const ushort unicode() const { return ushort(uchar(ch)); }
+#else
+ inline char toLatin1() const { return ch; }
+ inline ushort unicode() const { return ushort(uchar(ch)); }
+#endif
+
+private:
+ char ch;
+};
+
+
+class Q_CORE_EXPORT QChar {
+public:
+ QChar();
+#ifndef QT_NO_CAST_FROM_ASCII
+ QT_ASCII_CAST_WARN_CONSTRUCTOR QChar(char c);
+ QT_ASCII_CAST_WARN_CONSTRUCTOR QChar(uchar c);
+#endif
+ QChar(QLatin1Char ch);
+ QChar(uchar c, uchar r);
+ inline QChar(ushort rc) : ucs(rc){}
+ QChar(short rc);
+ QChar(uint rc);
+ QChar(int rc);
+ enum SpecialCharacter {
+ Null = 0x0000,
+ Nbsp = 0x00a0,
+ ReplacementCharacter = 0xfffd,
+ ObjectReplacementCharacter = 0xfffc,
+ ByteOrderMark = 0xfeff,
+ ByteOrderSwapped = 0xfffe,
+#ifdef QT3_SUPPORT
+ null = Null,
+ replacement = ReplacementCharacter,
+ byteOrderMark = ByteOrderMark,
+ byteOrderSwapped = ByteOrderSwapped,
+ nbsp = Nbsp,
+#endif
+ ParagraphSeparator = 0x2029,
+ LineSeparator = 0x2028
+ };
+ QChar(SpecialCharacter sc);
+
+ // Unicode information
+
+ enum Category
+ {
+ NoCategory, // ### Qt 5: replace with Other_NotAssigned
+
+ Mark_NonSpacing, // Mn
+ Mark_SpacingCombining, // Mc
+ Mark_Enclosing, // Me
+
+ Number_DecimalDigit, // Nd
+ Number_Letter, // Nl
+ Number_Other, // No
+
+ Separator_Space, // Zs
+ Separator_Line, // Zl
+ Separator_Paragraph, // Zp
+
+ Other_Control, // Cc
+ Other_Format, // Cf
+ Other_Surrogate, // Cs
+ Other_PrivateUse, // Co
+ Other_NotAssigned, // Cn
+
+ Letter_Uppercase, // Lu
+ Letter_Lowercase, // Ll
+ Letter_Titlecase, // Lt
+ Letter_Modifier, // Lm
+ Letter_Other, // Lo
+
+ Punctuation_Connector, // Pc
+ Punctuation_Dash, // Pd
+ Punctuation_Open, // Ps
+ Punctuation_Close, // Pe
+ Punctuation_InitialQuote, // Pi
+ Punctuation_FinalQuote, // Pf
+ Punctuation_Other, // Po
+
+ Symbol_Math, // Sm
+ Symbol_Currency, // Sc
+ Symbol_Modifier, // Sk
+ Symbol_Other, // So
+
+ Punctuation_Dask = Punctuation_Dash // ### Qt 5: remove
+ };
+
+ enum Direction
+ {
+ DirL, DirR, DirEN, DirES, DirET, DirAN, DirCS, DirB, DirS, DirWS, DirON,
+ DirLRE, DirLRO, DirAL, DirRLE, DirRLO, DirPDF, DirNSM, DirBN
+ };
+
+ enum Decomposition
+ {
+ NoDecomposition,
+ Canonical,
+ Font,
+ NoBreak,
+ Initial,
+ Medial,
+ Final,
+ Isolated,
+ Circle,
+ Super,
+ Sub,
+ Vertical,
+ Wide,
+ Narrow,
+ Small,
+ Square,
+ Compat,
+ Fraction
+
+#ifdef QT3_SUPPORT
+ , Single = NoDecomposition
+#endif
+ };
+
+ enum Joining
+ {
+ OtherJoining, Dual, Right, Center
+ };
+
+ enum CombiningClass
+ {
+ Combining_BelowLeftAttached = 200,
+ Combining_BelowAttached = 202,
+ Combining_BelowRightAttached = 204,
+ Combining_LeftAttached = 208,
+ Combining_RightAttached = 210,
+ Combining_AboveLeftAttached = 212,
+ Combining_AboveAttached = 214,
+ Combining_AboveRightAttached = 216,
+
+ Combining_BelowLeft = 218,
+ Combining_Below = 220,
+ Combining_BelowRight = 222,
+ Combining_Left = 224,
+ Combining_Right = 226,
+ Combining_AboveLeft = 228,
+ Combining_Above = 230,
+ Combining_AboveRight = 232,
+
+ Combining_DoubleBelow = 233,
+ Combining_DoubleAbove = 234,
+ Combining_IotaSubscript = 240
+ };
+
+ enum UnicodeVersion {
+ Unicode_Unassigned, // ### Qt 5: assign with some constantly big value
+ Unicode_1_1,
+ Unicode_2_0,
+ Unicode_2_1_2,
+ Unicode_3_0,
+ Unicode_3_1,
+ Unicode_3_2,
+ Unicode_4_0,
+ Unicode_4_1,
+ Unicode_5_0
+ };
+ // ****** WHEN ADDING FUNCTIONS, CONSIDER ADDING TO QCharRef TOO
+
+ Category category() const;
+ Direction direction() const;
+ Joining joining() const;
+ bool hasMirrored() const;
+ unsigned char combiningClass() const;
+
+ QChar mirroredChar() const;
+ QString decomposition() const;
+ Decomposition decompositionTag() const;
+
+ int digitValue() const;
+ QChar toLower() const;
+ QChar toUpper() const;
+ QChar toTitleCase() const;
+ QChar toCaseFolded() const;
+
+ UnicodeVersion unicodeVersion() const;
+
+#ifdef Q_COMPILER_MANGLES_RETURN_TYPE
+ const char toAscii() const;
+ inline const char toLatin1() const;
+ inline const ushort unicode() const { return ucs; }
+#else
+ char toAscii() const;
+ inline char toLatin1() const;
+ inline ushort unicode() const { return ucs; }
+#endif
+#ifdef Q_NO_PACKED_REFERENCE
+ inline ushort &unicode() { return const_cast<ushort&>(ucs); }
+#else
+ inline ushort &unicode() { return ucs; }
+#endif
+
+ static QChar fromAscii(char c);
+ static QChar fromLatin1(char c);
+
+ inline bool isNull() const { return ucs == 0; }
+ bool isPrint() const;
+ bool isPunct() const;
+ bool isSpace() const;
+ bool isMark() const;
+ bool isLetter() const;
+ bool isNumber() const;
+ bool isLetterOrNumber() const;
+ bool isDigit() const;
+ bool isSymbol() const;
+ inline bool isLower() const { return category() == Letter_Lowercase; }
+ inline bool isUpper() const { return category() == Letter_Uppercase; }
+ inline bool isTitleCase() const { return category() == Letter_Titlecase; }
+
+ inline bool isHighSurrogate() const {
+ return ((ucs & 0xfc00) == 0xd800);
+ }
+ inline bool isLowSurrogate() const {
+ return ((ucs & 0xfc00) == 0xdc00);
+ }
+
+ inline uchar cell() const { return uchar(ucs & 0xff); }
+ inline uchar row() const { return uchar((ucs>>8)&0xff); }
+ inline void setCell(uchar cell);
+ inline void setRow(uchar row);
+
+ static inline bool isHighSurrogate(uint ucs4) {
+ return ((ucs4 & 0xfffffc00) == 0xd800);
+ }
+ static inline bool isLowSurrogate(uint ucs4) {
+ return ((ucs4 & 0xfffffc00) == 0xdc00);
+ }
+ static inline bool requiresSurrogates(uint ucs4) {
+ return (ucs4 >= 0x10000);
+ }
+ static inline uint surrogateToUcs4(ushort high, ushort low) {
+ return (uint(high)<<10) + low - 0x35fdc00;
+ }
+ static inline uint surrogateToUcs4(QChar high, QChar low) {
+ return (uint(high.ucs)<<10) + low.ucs - 0x35fdc00;
+ }
+ static inline ushort highSurrogate(uint ucs4) {
+ return ushort((ucs4>>10) + 0xd7c0);
+ }
+ static inline ushort lowSurrogate(uint ucs4) {
+ return ushort(ucs4%0x400 + 0xdc00);
+ }
+
+ static Category QT_FASTCALL category(uint ucs4);
+ static Category QT_FASTCALL category(ushort ucs2);
+ static Direction QT_FASTCALL direction(uint ucs4);
+ static Direction QT_FASTCALL direction(ushort ucs2);
+ static Joining QT_FASTCALL joining(uint ucs4);
+ static Joining QT_FASTCALL joining(ushort ucs2);
+ static unsigned char QT_FASTCALL combiningClass(uint ucs4);
+ static unsigned char QT_FASTCALL combiningClass(ushort ucs2);
+
+ static uint QT_FASTCALL mirroredChar(uint ucs4);
+ static ushort QT_FASTCALL mirroredChar(ushort ucs2);
+ static Decomposition QT_FASTCALL decompositionTag(uint ucs4);
+
+ static int QT_FASTCALL digitValue(uint ucs4);
+ static int QT_FASTCALL digitValue(ushort ucs2);
+ static uint QT_FASTCALL toLower(uint ucs4);
+ static ushort QT_FASTCALL toLower(ushort ucs2);
+ static uint QT_FASTCALL toUpper(uint ucs4);
+ static ushort QT_FASTCALL toUpper(ushort ucs2);
+ static uint QT_FASTCALL toTitleCase(uint ucs4);
+ static ushort QT_FASTCALL toTitleCase(ushort ucs2);
+ static uint QT_FASTCALL toCaseFolded(uint ucs4);
+ static ushort QT_FASTCALL toCaseFolded(ushort ucs2);
+
+ static UnicodeVersion QT_FASTCALL unicodeVersion(uint ucs4);
+ static UnicodeVersion QT_FASTCALL unicodeVersion(ushort ucs2);
+
+ static UnicodeVersion QT_FASTCALL currentUnicodeVersion();
+
+ static QString QT_FASTCALL decomposition(uint ucs4);
+
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT bool mirrored() const { return hasMirrored(); }
+ inline QT3_SUPPORT QChar lower() const { return toLower(); }
+ inline QT3_SUPPORT QChar upper() const { return toUpper(); }
+ static inline QT3_SUPPORT bool networkOrdered() {
+ return QSysInfo::ByteOrder == QSysInfo::BigEndian;
+ }
+#ifdef Q_COMPILER_MANGLES_RETURN_TYPE
+ inline QT3_SUPPORT const char latin1() const { return toLatin1(); }
+ inline QT3_SUPPORT const char ascii() const { return toAscii(); }
+#else
+ inline QT3_SUPPORT char latin1() const { return toLatin1(); }
+ inline QT3_SUPPORT char ascii() const { return toAscii(); }
+#endif
+#endif
+
+private:
+#ifdef QT_NO_CAST_FROM_ASCII
+ QChar(char c);
+ QChar(uchar c);
+#endif
+ ushort ucs;
+};
+
+Q_DECLARE_TYPEINFO(QChar, Q_MOVABLE_TYPE);
+
+inline QChar::QChar() : ucs(0) {}
+
+#ifdef Q_COMPILER_MANGLES_RETURN_TYPE
+inline const char QChar::toLatin1() const { return ucs > 0xff ? '\0' : char(ucs); }
+#else
+inline char QChar::toLatin1() const { return ucs > 0xff ? '\0' : char(ucs); }
+#endif
+inline QChar QChar::fromLatin1(char c) { return QChar(ushort(uchar(c))); }
+
+inline QChar::QChar(uchar c, uchar r) : ucs(ushort((r << 8) | c)){}
+inline QChar::QChar(short rc) : ucs(ushort(rc)){}
+inline QChar::QChar(uint rc) : ucs(ushort(rc & 0xffff)){}
+inline QChar::QChar(int rc) : ucs(ushort(rc & 0xffff)){}
+inline QChar::QChar(SpecialCharacter s) : ucs(ushort(s)) {}
+inline QChar::QChar(QLatin1Char ch) : ucs(ch.unicode()) {}
+
+inline void QChar::setCell(uchar acell)
+{ ucs = ushort((ucs & 0xff00) + acell); }
+inline void QChar::setRow(uchar arow)
+{ ucs = ushort((ushort(arow)<<8) + (ucs&0xff)); }
+
+inline bool operator==(QChar c1, QChar c2) { return c1.unicode() == c2.unicode(); }
+inline bool operator!=(QChar c1, QChar c2) { return c1.unicode() != c2.unicode(); }
+inline bool operator<=(QChar c1, QChar c2) { return c1.unicode() <= c2.unicode(); }
+inline bool operator>=(QChar c1, QChar c2) { return c1.unicode() >= c2.unicode(); }
+inline bool operator<(QChar c1, QChar c2) { return c1.unicode() < c2.unicode(); }
+inline bool operator>(QChar c1, QChar c2) { return c1.unicode() > c2.unicode(); }
+
+#ifndef QT_NO_DATASTREAM
+Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QChar &);
+Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QChar &);
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QCHAR_H
diff --git a/src/corelib/tools/qcontainerfwd.h b/src/corelib/tools/qcontainerfwd.h
new file mode 100644
index 0000000000..28f8a6f1a3
--- /dev/null
+++ b/src/corelib/tools/qcontainerfwd.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCONTAINERFWD_H
+#define QCONTAINERFWD_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+template <class Key, class T> class QCache;
+template <class Key, class T> class QHash;
+template <class T> class QLinkedList;
+template <class T> class QList;
+template <class Key, class T> class QMap;
+template <class Key, class T> class QMultiHash;
+template <class Key, class T> class QMultiMap;
+template <class T1, class T2> struct QPair;
+template <class T> class QQueue;
+template <class T> class QSet;
+template <class T> class QStack;
+template<class T, int Prealloc = 256> class QVarLengthArray;
+template <class T> class QVector;
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QCONTAINERFWD_H
diff --git a/src/corelib/tools/qcontiguouscache.cpp b/src/corelib/tools/qcontiguouscache.cpp
new file mode 100644
index 0000000000..8e1c4c49a2
--- /dev/null
+++ b/src/corelib/tools/qcontiguouscache.cpp
@@ -0,0 +1,474 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qcontiguouscache.h"
+#ifdef QT_QCONTIGUOUSCACHE_DEBUG
+#include <QDebug>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#ifdef QT_QCONTIGUOUSCACHE_DEBUG
+void QContiguousCacheData::dump() const
+{
+ qDebug() << "capacity:" << alloc;
+ qDebug() << "count:" << count;
+ qDebug() << "start:" << start;
+ qDebug() << "offset:" << offset;
+}
+#endif
+
+QContiguousCacheData *QContiguousCacheData::allocate(int size, int alignment)
+{
+ return static_cast<QContiguousCacheData *>(qMallocAligned(size, alignment));
+}
+
+void QContiguousCacheData::free(QContiguousCacheData *data)
+{
+ qFreeAligned(data);
+}
+
+/*! \class QContiguousCache
+ \brief The QContiguousCache class is a template class that provides a contiguous cache.
+ \ingroup tools
+ \ingroup shared
+ \reentrant
+ \since 4.6
+
+ The QContiguousCache class provides an efficient way of caching items for
+ display in a user interface view. Unlike QCache, it adds a restriction
+ that elements within the cache are contiguous. This has the advantage
+ of matching how user interface views most commonly request data, as
+ a set of rows localized around the current scrolled position. This
+ restriction allows the cache to consume less memory and processor
+ cycles than QCache. The QContiguousCache class also can provide
+ an upper bound on memory usage via setCapacity().
+
+ The simplest way of using a contiguous cache is to use the append()
+ and prepend().
+
+\code
+MyRecord record(int row) const
+{
+ Q_ASSERT(row >= 0 && row < count());
+
+ while(row > cache.lastIndex())
+ cache.append(slowFetchRecord(cache.lastIndex()+1));
+ while(row < cache.firstIndex())
+ cache.prepend(slowFetchRecord(cache.firstIndex()-1));
+
+ return cache.at(row);
+}
+\endcode
+
+ If the cache is full then the item at the opposite end of the cache from
+ where the new item is appended or prepended will be removed.
+
+ This usage can be further optimized by using the insert() function
+ in the case where the requested row is a long way from the currently cached
+ items. If there is a gap between where the new item is inserted and the currently
+ cached items then the existing cached items are first removed to retain
+ the contiguous nature of the cache. Hence it is important to take some care then
+ when using insert() in order to avoid unwanted clearing of the cache.
+
+ The range of valid indexes for the QContiguousCache class are from
+ 0 to INT_MAX. Calling prepend() such that the first index would become less
+ than 0 or append() such that the last index would become greater
+ than INT_MAX can result in the indexes of the cache being invalid.
+ When the cache indexes are invalid it is important to call
+ normalizeIndexes() before calling any of containsIndex(), firstIndex(),
+ lastIndex(), at() or \l{QContiguousCache::operator[]()}{operator[]()}.
+ Calling these functions when the cache has invalid indexes will result in
+ undefined behavior. The indexes can be checked by using areIndexesValid()
+
+ In most cases the indexes will not exceed 0 to INT_MAX, and
+ normalizeIndexes() will not need to be used.
+
+ See the \l{Contiguous Cache Example}{Contiguous Cache} example.
+*/
+
+/*! \fn QContiguousCache::QContiguousCache(int capacity)
+
+ Constructs a cache with the given \a capacity.
+
+ \sa setCapacity()
+*/
+
+/*! \fn QContiguousCache::QContiguousCache(const QContiguousCache<T> &other)
+
+ Constructs a copy of \a other.
+
+ This operation takes \l{constant time}, because QContiguousCache is
+ \l{implicitly shared}. This makes returning a QContiguousCache from a
+ function very fast. If a shared instance is modified, it will be
+ copied (copy-on-write), and that takes \l{linear time}.
+
+ \sa operator=()
+*/
+
+/*! \fn QContiguousCache::~QContiguousCache()
+
+ Destroys the cache.
+*/
+
+/*! \fn void QContiguousCache::detach()
+ \internal
+*/
+
+/*! \fn bool QContiguousCache::isDetached() const
+ \internal
+*/
+
+/*! \fn void QContiguousCache::setSharable(bool sharable)
+ \internal
+*/
+
+/*! \typedef QContiguousCache::value_type
+ \internal
+ */
+
+/*! \typedef QContiguousCache::pointer
+ \internal
+ */
+
+/*! \typedef QContiguousCache::const_pointer
+ \internal
+ */
+
+/*! \typedef QContiguousCache::reference
+ \internal
+ */
+
+/*! \typedef QContiguousCache::const_reference
+ \internal
+ */
+
+/*! \typedef QContiguousCache::difference_type
+ \internal
+ */
+
+/*! \typedef QContiguousCache::size_type
+ \internal
+ */
+
+/*! \fn QContiguousCache<T> &QContiguousCache::operator=(const QContiguousCache<T> &other)
+
+ Assigns \a other to this cache and returns a reference to this cache.
+*/
+
+/*! \fn void QContiguousCache::swap(QContiguousCache<T> &other)
+ \since 4.8
+
+ Swaps cache \a other with this cache. This operation is very
+ fast and never fails.
+*/
+
+/*! \fn bool QContiguousCache::operator==(const QContiguousCache<T> &other) const
+
+ Returns true if \a other is equal to this cache; otherwise returns false.
+
+ Two caches are considered equal if they contain the same values at the same
+ indexes. This function requires the value type to implement the \c operator==().
+
+ \sa operator!=()
+*/
+
+/*! \fn bool QContiguousCache::operator!=(const QContiguousCache<T> &other) const
+
+ Returns true if \a other is not equal to this cache; otherwise
+ returns false.
+
+ Two caches are considered equal if they contain the same values at the same
+ indexes. This function requires the value type to implement the \c operator==().
+
+ \sa operator==()
+*/
+
+/*! \fn int QContiguousCache::capacity() const
+
+ Returns the number of items the cache can store before it is full.
+ When a cache contains a number of items equal to its capacity, adding new
+ items will cause items farthest from the added item to be removed.
+
+ \sa setCapacity(), size()
+*/
+
+/*! \fn int QContiguousCache::count() const
+
+ Same as size().
+*/
+
+/*! \fn int QContiguousCache::size() const
+
+ Returns the number of items contained within the cache.
+
+ \sa capacity()
+*/
+
+/*! \fn bool QContiguousCache::isEmpty() const
+
+ Returns true if no items are stored within the cache.
+
+ \sa size(), capacity()
+*/
+
+/*! \fn bool QContiguousCache::isFull() const
+
+ Returns true if the number of items stored within the cache is equal
+ to the capacity of the cache.
+
+ \sa size(), capacity()
+*/
+
+/*! \fn int QContiguousCache::available() const
+
+ Returns the number of items that can be added to the cache before it becomes full.
+
+ \sa size(), capacity(), isFull()
+*/
+
+/*! \fn void QContiguousCache::clear()
+
+ Removes all items from the cache. The capacity is unchanged.
+*/
+
+/*! \fn void QContiguousCache::setCapacity(int size)
+
+ Sets the capacity of the cache to the given \a size. A cache can hold a
+ number of items equal to its capacity. When inserting, appending or prepending
+ items to the cache, if the cache is already full then the item farthest from
+ the added item will be removed.
+
+ If the given \a size is smaller than the current count of items in the cache
+ then only the last \a size items from the cache will remain.
+
+ \sa capacity(), isFull()
+*/
+
+/*! \fn const T &QContiguousCache::at(int i) const
+
+ Returns the item at index position \a i in the cache. \a i must
+ be a valid index position in the cache (i.e, firstIndex() <= \a i <= lastIndex()).
+
+ The indexes in the cache refer to the number of positions the item is from the
+ first item appended into the cache. That is to say a cache with a capacity of
+ 100, that has had 150 items appended will have a valid index range of
+ 50 to 149. This allows inserting and retrieving items into the cache based
+ on a theoretical infinite list
+
+ \sa firstIndex(), lastIndex(), insert(), operator[]()
+*/
+
+/*! \fn T &QContiguousCache::operator[](int i)
+
+ Returns the item at index position \a i as a modifiable reference. If
+ the cache does not contain an item at the given index position \a i
+ then it will first insert an empty item at that position.
+
+ In most cases it is better to use either at() or insert().
+
+ \note This non-const overload of operator[] requires QContiguousCache
+ to make a deep copy. Use at() for read-only access to a non-const
+ QContiguousCache.
+
+ \sa insert(), at()
+*/
+
+/*! \fn const T &QContiguousCache::operator[](int i) const
+
+ \overload
+
+ Same as at(\a i).
+*/
+
+/*! \fn void QContiguousCache::append(const T &value)
+
+ Inserts \a value at the end of the cache. If the cache is already full
+ the item at the start of the cache will be removed.
+
+ \sa prepend(), insert(), isFull()
+*/
+
+/*! \fn void QContiguousCache::prepend(const T &value)
+
+ Inserts \a value at the start of the cache. If the cache is already full
+ the item at the end of the cache will be removed.
+
+ \sa append(), insert(), isFull()
+*/
+
+/*! \fn void QContiguousCache::insert(int i, const T &value)
+
+ Inserts the \a value at the index position \a i. If the cache already contains
+ an item at \a i then that value is replaced. If \a i is either one more than
+ lastIndex() or one less than firstIndex() it is the equivalent to an append()
+ or a prepend().
+
+ If the given index \a i is not within the current range of the cache nor adjacent
+ to the bounds of the cache's index range, the cache is first cleared before
+ inserting the item. At this point the cache will have a size of 1. It is
+ worthwhile taking effort to insert items in an order that starts adjacent
+ to the current index range for the cache.
+
+ The range of valid indexes for the QContiguousCache class are from
+ 0 to INT_MAX. Inserting outside of this range has undefined behavior.
+
+
+ \sa prepend(), append(), isFull(), firstIndex(), lastIndex()
+*/
+
+/*! \fn bool QContiguousCache::containsIndex(int i) const
+
+ Returns true if the cache's index range includes the given index \a i.
+
+ \sa firstIndex(), lastIndex()
+*/
+
+/*! \fn int QContiguousCache::firstIndex() const
+
+ Returns the first valid index in the cache. The index will be invalid if the
+ cache is empty.
+
+ \sa capacity(), size(), lastIndex()
+*/
+
+/*! \fn int QContiguousCache::lastIndex() const
+
+ Returns the last valid index in the cache. The index will be invalid if the cache is empty.
+
+ \sa capacity(), size(), firstIndex()
+*/
+
+
+/*! \fn T &QContiguousCache::first()
+
+ Returns a reference to the first item in the cache. This function
+ assumes that the cache isn't empty.
+
+ \sa last(), isEmpty()
+*/
+
+/*! \fn T &QContiguousCache::last()
+
+ Returns a reference to the last item in the cache. This function
+ assumes that the cache isn't empty.
+
+ \sa first(), isEmpty()
+*/
+
+/*! \fn const T& QContiguousCache::first() const
+
+ \overload
+*/
+
+/*! \fn const T& QContiguousCache::last() const
+
+ \overload
+*/
+
+/*! \fn void QContiguousCache::removeFirst()
+
+ Removes the first item from the cache. This function assumes that
+ the cache isn't empty.
+
+ \sa removeLast()
+*/
+
+/*! \fn void QContiguousCache::removeLast()
+
+ Removes the last item from the cache. This function assumes that
+ the cache isn't empty.
+
+ \sa removeFirst()
+*/
+
+/*! \fn T QContiguousCache::takeFirst()
+
+ Removes the first item in the cache and returns it. This function
+ assumes that the cache isn't empty.
+
+ If you don't use the return value, removeFirst() is more efficient.
+
+ \sa takeLast(), removeFirst()
+*/
+
+/*! \fn T QContiguousCache::takeLast()
+
+ Removes the last item in the cache and returns it. This function
+ assumes that the cache isn't empty.
+
+ If you don't use the return value, removeLast() is more efficient.
+
+ \sa takeFirst(), removeLast()
+*/
+
+/*! \fn void QContiguousCache::normalizeIndexes()
+
+ Moves the first index and last index of the cache
+ such that they point to valid indexes. The function does not modify
+ the contents of the cache or the ordering of elements within the cache.
+
+ It is provided so that index overflows can be corrected when using the
+ cache as a circular buffer.
+
+ \code
+ QContiguousCache<int> cache(10);
+ cache.insert(INT_MAX, 1); // cache contains one value and has valid indexes, INT_MAX to INT_MAX
+ cache.append(2); // cache contains two values but does not have valid indexes.
+ cache.normalizeIndexes(); // cache has two values, 1 and 2. New first index will be in the range of 0 to capacity().
+ \endcode
+
+ \sa areIndexesValid(), append(), prepend()
+*/
+
+/*! \fn bool QContiguousCache::areIndexesValid() const
+
+ Returns whether the indexes for items stored in the cache are valid.
+ Indexes can become invalid if items are appended after the index position
+ INT_MAX or prepended before the index position 0. This is only expected
+ to occur in very long lived circular buffer style usage of the
+ contiguous cache. Indexes can be made valid again by calling
+ normalizeIndexs().
+
+ \sa normalizeIndexes(), append(), prepend()
+*/
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qcontiguouscache.h b/src/corelib/tools/qcontiguouscache.h
new file mode 100644
index 0000000000..7880c2e411
--- /dev/null
+++ b/src/corelib/tools/qcontiguouscache.h
@@ -0,0 +1,466 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCONTIGUOUSCACHE_H
+#define QCONTIGUOUSCACHE_H
+
+#include <QtCore/qatomic.h>
+#include <limits.h>
+#include <new>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+#undef QT_QCONTIGUOUSCACHE_DEBUG
+QT_MODULE(Core)
+
+
+struct Q_CORE_EXPORT QContiguousCacheData
+{
+ QBasicAtomicInt ref;
+ int alloc;
+ int count;
+ int start;
+ int offset;
+ uint sharable : 1;
+ uint reserved : 31;
+
+ // total is 24 bytes (HP-UX aCC: 40 bytes)
+ // the next entry is already aligned to 8 bytes
+ // there will be an 8 byte gap here if T requires 16-byte alignment
+ // (such as long double on 64-bit platforms, __int128, __float128)
+
+ static QContiguousCacheData *allocate(int size, int alignment);
+ static void free(QContiguousCacheData *data);
+
+#ifdef QT_QCONTIGUOUSCACHE_DEBUG
+ void dump() const;
+#endif
+};
+
+template <typename T>
+struct QContiguousCacheTypedData: private QContiguousCacheData
+{
+ // private inheritance to avoid aliasing warningss
+ T array[1];
+
+ static inline void free(QContiguousCacheTypedData *data) { QContiguousCacheData::free(data); }
+};
+
+template<typename T>
+class QContiguousCache {
+ typedef QContiguousCacheTypedData<T> Data;
+ union { QContiguousCacheData *d; QContiguousCacheTypedData<T> *p; };
+public:
+ // STL compatibility
+ typedef T value_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+ typedef qptrdiff difference_type;
+ typedef int size_type;
+
+ explicit QContiguousCache(int capacity = 0);
+ QContiguousCache(const QContiguousCache<T> &v) : d(v.d) { d->ref.ref(); if (!d->sharable) detach_helper(); }
+
+ inline ~QContiguousCache() { if (!d) return; if (!d->ref.deref()) free(p); }
+
+ inline void detach() { if (d->ref != 1) detach_helper(); }
+ inline bool isDetached() const { return d->ref == 1; }
+ inline void setSharable(bool sharable) { if (!sharable) detach(); d->sharable = sharable; }
+
+ QContiguousCache<T> &operator=(const QContiguousCache<T> &other);
+#ifdef Q_COMPILER_RVALUE_REFS
+ inline QContiguousCache<T> &operator=(QContiguousCache<T> &&other)
+ { qSwap(d, other.d); return *this; }
+#endif
+ inline void swap(QContiguousCache<T> &other) { qSwap(d, other.d); }
+ bool operator==(const QContiguousCache<T> &other) const;
+ inline bool operator!=(const QContiguousCache<T> &other) const { return !(*this == other); }
+
+ inline int capacity() const {return d->alloc; }
+ inline int count() const { return d->count; }
+ inline int size() const { return d->count; }
+
+ inline bool isEmpty() const { return d->count == 0; }
+ inline bool isFull() const { return d->count == d->alloc; }
+ inline int available() const { return d->alloc - d->count; }
+
+ void clear();
+ void setCapacity(int size);
+
+ const T &at(int pos) const;
+ T &operator[](int i);
+ const T &operator[](int i) const;
+
+ void append(const T &value);
+ void prepend(const T &value);
+ void insert(int pos, const T &value);
+
+ inline bool containsIndex(int pos) const { return pos >= d->offset && pos - d->offset < d->count; }
+ inline int firstIndex() const { return d->offset; }
+ inline int lastIndex() const { return d->offset + d->count - 1; }
+
+ inline const T &first() const { Q_ASSERT(!isEmpty()); return p->array[d->start]; }
+ inline const T &last() const { Q_ASSERT(!isEmpty()); return p->array[(d->start + d->count -1) % d->alloc]; }
+ inline T &first() { Q_ASSERT(!isEmpty()); detach(); return p->array[d->start]; }
+ inline T &last() { Q_ASSERT(!isEmpty()); detach(); return p->array[(d->start + d->count -1) % d->alloc]; }
+
+ void removeFirst();
+ T takeFirst();
+ void removeLast();
+ T takeLast();
+
+ inline bool areIndexesValid() const
+ { return d->offset >= 0 && d->offset < INT_MAX - d->count && (d->offset % d->alloc) == d->start; }
+
+ inline void normalizeIndexes() { d->offset = d->start; }
+
+#ifdef QT_QCONTIGUOUSCACHE_DEBUG
+ void dump() const { p->dump(); }
+#endif
+private:
+ void detach_helper();
+
+ QContiguousCacheData *malloc(int aalloc);
+ void free(Data *x);
+ int sizeOfTypedData() {
+ // this is more or less the same as sizeof(Data), except that it doesn't
+ // count the padding at the end
+ return reinterpret_cast<const char *>(&(reinterpret_cast<const Data *>(this))->array[1]) - reinterpret_cast<const char *>(this);
+ }
+ int alignOfTypedData() const
+ {
+#ifdef Q_ALIGNOF
+ return qMax<int>(sizeof(void*), Q_ALIGNOF(Data));
+#else
+ return 0;
+#endif
+ }
+};
+
+template <typename T>
+void QContiguousCache<T>::detach_helper()
+{
+ union { QContiguousCacheData *d; QContiguousCacheTypedData<T> *p; } x;
+
+ x.d = malloc(d->alloc);
+ x.d->ref = 1;
+ x.d->count = d->count;
+ x.d->start = d->start;
+ x.d->offset = d->offset;
+ x.d->alloc = d->alloc;
+ x.d->sharable = true;
+ x.d->reserved = 0;
+
+ T *dest = x.p->array + x.d->start;
+ T *src = p->array + d->start;
+ int oldcount = x.d->count;
+ while (oldcount--) {
+ if (QTypeInfo<T>::isComplex) {
+ new (dest) T(*src);
+ } else {
+ *dest = *src;
+ }
+ dest++;
+ if (dest == x.p->array + x.d->alloc)
+ dest = x.p->array;
+ src++;
+ if (src == p->array + d->alloc)
+ src = p->array;
+ }
+
+ if (!d->ref.deref())
+ free(p);
+ d = x.d;
+}
+
+template <typename T>
+void QContiguousCache<T>::setCapacity(int asize)
+{
+ if (asize == d->alloc)
+ return;
+ detach();
+ union { QContiguousCacheData *d; QContiguousCacheTypedData<T> *p; } x;
+ x.d = malloc(asize);
+ x.d->alloc = asize;
+ x.d->count = qMin(d->count, asize);
+ x.d->offset = d->offset + d->count - x.d->count;
+ if(asize)
+ x.d->start = x.d->offset % x.d->alloc;
+ else
+ x.d->start = 0;
+
+ int oldcount = x.d->count;
+ if(oldcount)
+ {
+ T *dest = x.p->array + (x.d->start + x.d->count-1) % x.d->alloc;
+ T *src = p->array + (d->start + d->count-1) % d->alloc;
+ while (oldcount--) {
+ if (QTypeInfo<T>::isComplex) {
+ new (dest) T(*src);
+ } else {
+ *dest = *src;
+ }
+ if (dest == x.p->array)
+ dest = x.p->array + x.d->alloc;
+ dest--;
+ if (src == p->array)
+ src = p->array + d->alloc;
+ src--;
+ }
+ }
+ /* free old */
+ free(p);
+ d = x.d;
+}
+
+template <typename T>
+void QContiguousCache<T>::clear()
+{
+ if (d->ref == 1) {
+ if (QTypeInfo<T>::isComplex) {
+ int oldcount = d->count;
+ T * i = p->array + d->start;
+ T * e = p->array + d->alloc;
+ while (oldcount--) {
+ i->~T();
+ i++;
+ if (i == e)
+ i = p->array;
+ }
+ }
+ d->count = d->start = d->offset = 0;
+ } else {
+ union { QContiguousCacheData *d; QContiguousCacheTypedData<T> *p; } x;
+ x.d = malloc(d->alloc);
+ x.d->ref = 1;
+ x.d->alloc = d->alloc;
+ x.d->count = x.d->start = x.d->offset = 0;
+ x.d->sharable = true;
+ if (!d->ref.deref()) free(p);
+ d = x.d;
+ }
+}
+
+template <typename T>
+inline QContiguousCacheData *QContiguousCache<T>::malloc(int aalloc)
+{
+ return QContiguousCacheData::allocate(sizeOfTypedData() + (aalloc - 1) * sizeof(T), alignOfTypedData());
+}
+
+template <typename T>
+QContiguousCache<T>::QContiguousCache(int cap)
+{
+ d = malloc(cap);
+ d->ref = 1;
+ d->alloc = cap;
+ d->count = d->start = d->offset = 0;
+ d->sharable = true;
+}
+
+template <typename T>
+QContiguousCache<T> &QContiguousCache<T>::operator=(const QContiguousCache<T> &other)
+{
+ other.d->ref.ref();
+ if (!d->ref.deref())
+ free(d);
+ d = other.d;
+ if (!d->sharable)
+ detach_helper();
+ return *this;
+}
+
+template <typename T>
+bool QContiguousCache<T>::operator==(const QContiguousCache<T> &other) const
+{
+ if (other.d == d)
+ return true;
+ if (other.d->start != d->start
+ || other.d->count != d->count
+ || other.d->offset != d->offset
+ || other.d->alloc != d->alloc)
+ return false;
+ for (int i = firstIndex(); i <= lastIndex(); ++i)
+ if (!(at(i) == other.at(i)))
+ return false;
+ return true;
+}
+
+template <typename T>
+void QContiguousCache<T>::free(Data *x)
+{
+ if (QTypeInfo<T>::isComplex) {
+ int oldcount = d->count;
+ T * i = p->array + d->start;
+ T * e = p->array + d->alloc;
+ while (oldcount--) {
+ i->~T();
+ i++;
+ if (i == e)
+ i = p->array;
+ }
+ }
+ x->free(x);
+}
+template <typename T>
+void QContiguousCache<T>::append(const T &value)
+{
+ detach();
+ if (QTypeInfo<T>::isComplex) {
+ if (d->count == d->alloc)
+ (p->array + (d->start+d->count) % d->alloc)->~T();
+ new (p->array + (d->start+d->count) % d->alloc) T(value);
+ } else {
+ p->array[(d->start+d->count) % d->alloc] = value;
+ }
+
+ if (d->count == d->alloc) {
+ d->start++;
+ d->start %= d->alloc;
+ d->offset++;
+ } else {
+ d->count++;
+ }
+}
+
+template<typename T>
+void QContiguousCache<T>::prepend(const T &value)
+{
+ detach();
+ if (d->start)
+ d->start--;
+ else
+ d->start = d->alloc-1;
+ d->offset--;
+
+ if (d->count != d->alloc)
+ d->count++;
+ else
+ if (d->count == d->alloc)
+ (p->array + d->start)->~T();
+
+ if (QTypeInfo<T>::isComplex)
+ new (p->array + d->start) T(value);
+ else
+ p->array[d->start] = value;
+}
+
+template<typename T>
+void QContiguousCache<T>::insert(int pos, const T &value)
+{
+ Q_ASSERT_X(pos >= 0 && pos < INT_MAX, "QContiguousCache<T>::insert", "index out of range");
+ detach();
+ if (containsIndex(pos)) {
+ if(QTypeInfo<T>::isComplex)
+ new (p->array + pos % d->alloc) T(value);
+ else
+ p->array[pos % d->alloc] = value;
+ } else if (pos == d->offset-1)
+ prepend(value);
+ else if (pos == d->offset+d->count)
+ append(value);
+ else {
+ // we don't leave gaps.
+ clear();
+ d->offset = pos;
+ d->start = pos % d->alloc;
+ d->count = 1;
+ if (QTypeInfo<T>::isComplex)
+ new (p->array + d->start) T(value);
+ else
+ p->array[d->start] = value;
+ }
+}
+
+template <typename T>
+inline const T &QContiguousCache<T>::at(int pos) const
+{ Q_ASSERT_X(pos >= d->offset && pos - d->offset < d->count, "QContiguousCache<T>::at", "index out of range"); return p->array[pos % d->alloc]; }
+template <typename T>
+inline const T &QContiguousCache<T>::operator[](int pos) const
+{ Q_ASSERT_X(pos >= d->offset && pos - d->offset < d->count, "QContiguousCache<T>::at", "index out of range"); return p->array[pos % d->alloc]; }
+
+template <typename T>
+inline T &QContiguousCache<T>::operator[](int pos)
+{
+ detach();
+ if (!containsIndex(pos))
+ insert(pos, T());
+ return p->array[pos % d->alloc];
+}
+
+template <typename T>
+inline void QContiguousCache<T>::removeFirst()
+{
+ Q_ASSERT(d->count > 0);
+ detach();
+ d->count--;
+ if (QTypeInfo<T>::isComplex)
+ (p->array + d->start)->~T();
+ d->start = (d->start + 1) % d->alloc;
+ d->offset++;
+}
+
+template <typename T>
+inline void QContiguousCache<T>::removeLast()
+{
+ Q_ASSERT(d->count > 0);
+ detach();
+ d->count--;
+ if (QTypeInfo<T>::isComplex)
+ (p->array + (d->start + d->count) % d->alloc)->~T();
+}
+
+template <typename T>
+inline T QContiguousCache<T>::takeFirst()
+{ T t = first(); removeFirst(); return t; }
+
+template <typename T>
+inline T QContiguousCache<T>::takeLast()
+{ T t = last(); removeLast(); return t; }
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/corelib/tools/qcryptographichash.cpp b/src/corelib/tools/qcryptographichash.cpp
new file mode 100644
index 0000000000..630e390563
--- /dev/null
+++ b/src/corelib/tools/qcryptographichash.cpp
@@ -0,0 +1,200 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qcryptographichash.h>
+
+#ifdef Q_OS_SYMBIAN
+#define _MD5_H_ // Needed to disable system header
+#endif
+
+#include "../../3rdparty/md5/md5.h"
+#include "../../3rdparty/md5/md5.cpp"
+#include "../../3rdparty/md4/md4.h"
+#include "../../3rdparty/md4/md4.cpp"
+#include "../../3rdparty/sha1/sha1.cpp"
+
+
+QT_BEGIN_NAMESPACE
+
+class QCryptographicHashPrivate
+{
+public:
+ QCryptographicHash::Algorithm method;
+ union {
+ MD5Context md5Context;
+ md4_context md4Context;
+ Sha1State sha1Context;
+ };
+ QByteArray result;
+};
+
+/*!
+ \class QCryptographicHash
+
+ \brief The QCryptographicHash class provides a way to generate cryptographic hashes.
+
+ \since 4.3
+
+ \ingroup tools
+ \reentrant
+
+ QCryptographicHash can be used to generate cryptographic hashes of binary or text data.
+
+ Currently MD4, MD5, and SHA-1 are supported.
+*/
+
+/*!
+ \enum QCryptographicHash::Algorithm
+
+ \value Md4 Generate an MD4 hash sum
+ \value Md5 Generate an MD5 hash sum
+ \value Sha1 Generate an SHA1 hash sum
+*/
+
+/*!
+ Constructs an object that can be used to create a cryptographic hash from data using \a method.
+*/
+QCryptographicHash::QCryptographicHash(Algorithm method)
+ : d(new QCryptographicHashPrivate)
+{
+ d->method = method;
+ reset();
+}
+
+/*!
+ Destroys the object.
+*/
+QCryptographicHash::~QCryptographicHash()
+{
+ delete d;
+}
+
+/*!
+ Resets the object.
+*/
+void QCryptographicHash::reset()
+{
+ switch (d->method) {
+ case Md4:
+ md4_init(&d->md4Context);
+ break;
+ case Md5:
+ MD5Init(&d->md5Context);
+ break;
+ case Sha1:
+ sha1InitState(&d->sha1Context);
+ break;
+ }
+ d->result.clear();
+}
+
+/*!
+ Adds the first \a length chars of \a data to the cryptographic
+ hash.
+*/
+void QCryptographicHash::addData(const char *data, int length)
+{
+ switch (d->method) {
+ case Md4:
+ md4_update(&d->md4Context, (const unsigned char *)data, length);
+ break;
+ case Md5:
+ MD5Update(&d->md5Context, (const unsigned char *)data, length);
+ break;
+ case Sha1:
+ sha1Update(&d->sha1Context, (const unsigned char *)data, length);
+ break;
+ }
+ d->result.clear();
+}
+
+/*!
+ \overload addData()
+*/
+void QCryptographicHash::addData(const QByteArray &data)
+{
+ addData(data.constData(), data.length());
+}
+
+/*!
+ Returns the final hash value.
+
+ \sa QByteArray::toHex()
+*/
+QByteArray QCryptographicHash::result() const
+{
+ if (!d->result.isEmpty())
+ return d->result;
+
+ switch (d->method) {
+ case Md4: {
+ md4_context copy = d->md4Context;
+ d->result.resize(MD4_RESULTLEN);
+ md4_final(&copy, (unsigned char *)d->result.data());
+ break;
+ }
+ case Md5: {
+ MD5Context copy = d->md5Context;
+ d->result.resize(16);
+ MD5Final(&copy, (unsigned char *)d->result.data());
+ break;
+ }
+ case Sha1: {
+ Sha1State copy = d->sha1Context;
+ d->result.resize(20);
+ sha1FinalizeState(&copy);
+ sha1ToHash(&copy, (unsigned char *)d->result.data());
+ }
+ }
+ return d->result;
+}
+
+/*!
+ Returns the hash of \a data using \a method.
+*/
+QByteArray QCryptographicHash::hash(const QByteArray &data, Algorithm method)
+{
+ QCryptographicHash hash(method);
+ hash.addData(data);
+ return hash.result();
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qcryptographichash.h b/src/corelib/tools/qcryptographichash.h
new file mode 100644
index 0000000000..8506961882
--- /dev/null
+++ b/src/corelib/tools/qcryptographichash.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCRYPTOGRAPHICSHASH_H
+#define QCRYPTOGRAPHICSHASH_H
+
+#include <QtCore/qbytearray.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QCryptographicHashPrivate;
+
+class Q_CORE_EXPORT QCryptographicHash
+{
+public:
+ enum Algorithm {
+ Md4,
+ Md5,
+ Sha1
+ };
+
+ QCryptographicHash(Algorithm method);
+ ~QCryptographicHash();
+
+ void reset();
+
+ void addData(const char *data, int length);
+ void addData(const QByteArray &data);
+
+ QByteArray result() const;
+
+ static QByteArray hash(const QByteArray &data, Algorithm method);
+private:
+ Q_DISABLE_COPY(QCryptographicHash)
+ QCryptographicHashPrivate *d;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp
new file mode 100644
index 0000000000..a3a8884374
--- /dev/null
+++ b/src/corelib/tools/qdatetime.cpp
@@ -0,0 +1,5881 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+#include "private/qdatetime_p.h"
+
+#include "qdatastream.h"
+#include "qset.h"
+#include "qlocale.h"
+#include "qdatetime.h"
+#include "qregexp.h"
+#include "qdebug.h"
+#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
+#include <qt_windows.h>
+#endif
+#ifndef Q_WS_WIN
+#include <locale.h>
+#endif
+
+#include <time.h>
+#if defined(Q_OS_WINCE)
+#include "qfunctions_wince.h"
+#endif
+
+//#define QDATETIMEPARSER_DEBUG
+#if defined (QDATETIMEPARSER_DEBUG) && !defined(QT_NO_DEBUG_STREAM)
+# define QDTPDEBUG qDebug() << QString("%1:%2").arg(__FILE__).arg(__LINE__)
+# define QDTPDEBUGN qDebug
+#else
+# define QDTPDEBUG if (false) qDebug()
+# define QDTPDEBUGN if (false) qDebug
+#endif
+
+#if defined(Q_WS_MAC)
+#include <private/qcore_mac_p.h>
+#endif
+
+#if defined(Q_OS_SYMBIAN)
+#include <e32std.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+enum {
+ FIRST_YEAR = -4713,
+ FIRST_MONTH = 1,
+ FIRST_DAY = 2, // ### Qt 5: make FIRST_DAY = 1, by support jd == 0 as valid
+ SECS_PER_DAY = 86400,
+ MSECS_PER_DAY = 86400000,
+ SECS_PER_HOUR = 3600,
+ MSECS_PER_HOUR = 3600000,
+ SECS_PER_MIN = 60,
+ MSECS_PER_MIN = 60000,
+ JULIAN_DAY_FOR_EPOCH = 2440588 // result of julianDayFromGregorianDate(1970, 1, 1)
+};
+
+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;
+}
+
+static inline uint julianDayFromGregorianDate(int year, int month, int day)
+{
+ // Gregorian calendar starting from October 15, 1582
+ // Algorithm from Henry F. Fliegel and Thomas C. Van Flandern
+ return (1461 * (year + 4800 + (month - 14) / 12)) / 4
+ + (367 * (month - 2 - 12 * ((month - 14) / 12))) / 12
+ - (3 * ((year + 4900 + (month - 14) / 12) / 100)) / 4
+ + day - 32075;
+}
+
+static uint julianDayFromDate(int year, int month, int day)
+{
+ if (year < 0)
+ ++year;
+
+ if (year > 1582 || (year == 1582 && (month > 10 || (month == 10 && day >= 15)))) {
+ return julianDayFromGregorianDate(year, month, day);
+ } else if (year < 1582 || (year == 1582 && (month < 10 || (month == 10 && day <= 4)))) {
+ // Julian calendar until October 4, 1582
+ // Algorithm from Frequently Asked Questions about Calendars by Claus Toendering
+ int a = (14 - month) / 12;
+ return (153 * (month + (12 * a) - 3) + 2) / 5
+ + (1461 * (year + 4800 - a)) / 4
+ + day - 32083;
+ } else {
+ // the day following October 4, 1582 is October 15, 1582
+ return 0;
+ }
+}
+
+static void getDateFromJulianDay(uint julianDay, int *year, int *month, int *day)
+{
+ int y, m, d;
+
+ if (julianDay >= 2299161) {
+ // Gregorian calendar starting from October 15, 1582
+ // This algorithm is from Henry F. Fliegel and Thomas C. Van Flandern
+ qulonglong ell, n, i, j;
+ ell = qulonglong(julianDay) + 68569;
+ n = (4 * ell) / 146097;
+ ell = ell - (146097 * n + 3) / 4;
+ i = (4000 * (ell + 1)) / 1461001;
+ ell = ell - (1461 * i) / 4 + 31;
+ j = (80 * ell) / 2447;
+ d = ell - (2447 * j) / 80;
+ ell = j / 11;
+ m = j + 2 - (12 * ell);
+ y = 100 * (n - 49) + i + ell;
+ } else {
+ // Julian calendar until October 4, 1582
+ // Algorithm from Frequently Asked Questions about Calendars by Claus Toendering
+ julianDay += 32082;
+ int dd = (4 * julianDay + 3) / 1461;
+ int ee = julianDay - (1461 * dd) / 4;
+ int mm = ((5 * ee) + 2) / 153;
+ d = ee - (153 * mm + 2) / 5 + 1;
+ m = mm + 3 - 12 * (mm / 10);
+ y = dd - 4800 + (mm / 10);
+ if (y <= 0)
+ --y;
+ }
+ if (year)
+ *year = y;
+ if (month)
+ *month = m;
+ if (day)
+ *day = d;
+}
+
+
+static const char monthDays[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+#ifndef QT_NO_TEXTDATE
+static const char * const qt_shortMonthNames[] = {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+#endif
+#ifndef QT_NO_DATESTRING
+static QString fmtDateTime(const QString& f, const QTime* dt = 0, const QDate* dd = 0);
+#endif
+
+/*****************************************************************************
+ 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
+ \reentrant
+ \brief The QDate class provides date functions.
+
+
+ A QDate object contains a calendar date, i.e. year, month, and day
+ numbers, in the Gregorian calendar. (see \l{QDate G and J} {Use of
+ Gregorian and Julian Calendars} for dates prior to 15 October
+ 1582). 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 either by giving the year,
+ month, and day numbers explicitly. Note that QDate interprets two
+ digit years as is, i.e., years 0 - 99. 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
+
+ \target QDate G and J
+ \section2 Use of Gregorian and Julian Calendars
+
+ QDate uses the Gregorian calendar in all locales, beginning
+ on the date 15 October 1582. For dates up to and including 4
+ October 1582, the Julian calendar is used. This means there is a
+ 10-day gap in the internal calendar between the 4th and the 15th
+ of October 1582. When you use QDateTime for dates in that epoch,
+ the day after 4 October 1582 is 15 October 1582, and the dates in
+ the gap are invalid.
+
+ The Julian to Gregorian changeover date used here is the date when
+ the Gregorian calendar was first introduced, by Pope Gregory
+ XIII. That change was not universally accepted and some localities
+ only executed it at a later date (if at all). QDateTime
+ doesn't take any of these historical facts into account. If an
+ application must support a locale-specific dating system, it must
+ do so on its own, remembering to convert the dates using the
+ Julian day.
+
+ \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 0001-01-01 is December 31st, 1 BCE.
+
+ \section2 Range of Valid Dates
+
+ The range of valid dates is from January 2nd, 4713 BCE, to
+ sometime in the year 11 million CE. The Julian Day returned by
+ QDate::toJulianDay() is a number in the contiguous range from 1 to
+ \e{overflow}, even across QDateTime's "date holes". It is suitable
+ for use in applications that must convert a QDateTime to a date in
+ another calendar system, e.g., Hebrew, Islamic or Chinese.
+
+ \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 false. A date before 2 January 4713 B.C. is
+ considered invalid.
+
+ \warning Years 0 to 99 are interpreted as is, i.e., years
+ 0-99.
+
+ \sa isValid()
+*/
+
+QDate::QDate(int y, int m, int d)
+{
+ setDate(y, m, d);
+}
+
+
+/*!
+ \fn bool QDate::isNull() const
+
+ Returns true if the date is null; otherwise returns false. A null
+ date is invalid.
+
+ \note The behavior of this function is equivalent to isValid().
+
+ \sa isValid()
+*/
+
+
+/*!
+ Returns true if this date is valid; otherwise returns false.
+
+ \sa isNull()
+*/
+
+bool QDate::isValid() const
+{
+ return !isNull();
+}
+
+
+/*!
+ Returns the year of this date. Negative numbers indicate years
+ before 1 A.D. = 1 C.E., such that year -44 is 44 B.C.
+
+ \sa month(), day()
+*/
+
+int QDate::year() const
+{
+ int y;
+ getDateFromJulianDay(jd, &y, 0, 0);
+ return y;
+}
+
+/*!
+ Returns the number corresponding to the month of this date, using
+ the following convention:
+
+ \list
+ \i 1 = "January"
+ \i 2 = "February"
+ \i 3 = "March"
+ \i 4 = "April"
+ \i 5 = "May"
+ \i 6 = "June"
+ \i 7 = "July"
+ \i 8 = "August"
+ \i 9 = "September"
+ \i 10 = "October"
+ \i 11 = "November"
+ \i 12 = "December"
+ \endlist
+
+ \sa year(), day()
+*/
+
+int QDate::month() const
+{
+ int m;
+ getDateFromJulianDay(jd, 0, &m, 0);
+ return m;
+}
+
+/*!
+ Returns the day of the month (1 to 31) of this date.
+
+ \sa year(), month(), dayOfWeek()
+*/
+
+int QDate::day() const
+{
+ int d;
+ getDateFromJulianDay(jd, 0, 0, &d);
+ return d;
+}
+
+/*!
+ Returns the weekday (1 to 7) for this date.
+
+ \sa day(), dayOfYear(), Qt::DayOfWeek
+*/
+
+int QDate::dayOfWeek() const
+{
+ return (jd % 7) + 1;
+}
+
+/*!
+ Returns the day of the year (1 to 365 or 366 on leap years) for
+ this date.
+
+ \sa day(), dayOfWeek()
+*/
+
+int QDate::dayOfYear() const
+{
+ return jd - julianDayFromDate(year(), 1, 1) + 1;
+}
+
+/*!
+ Returns the number of days in the month (28 to 31) for this date.
+
+ \sa day(), daysInYear()
+*/
+
+int QDate::daysInMonth() const
+{
+ int y, m, d;
+ getDateFromJulianDay(jd, &y, &m, &d);
+ if (m == 2 && isLeapYear(y))
+ return 29;
+ else
+ return monthDays[m];
+}
+
+/*!
+ Returns the number of days in the year (365 or 366) for this date.
+
+ \sa day(), daysInMonth()
+*/
+
+int QDate::daysInYear() const
+{
+ int y, m, d;
+ getDateFromJulianDay(jd, &y, &m, &d);
+ return isLeapYear(y) ? 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.
+
+ \legalese
+ Copyright (c) 1989 The Regents of the University of California.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms are permitted
+ provided that the above copyright notice and this paragraph are
+ duplicated in all such forms and that any documentation,
+ advertising materials, and other materials related to such
+ distribution and use acknowledge that the software was developed
+ by the University of California, Berkeley. The name of the
+ University may not be used to endorse or promote products derived
+ from this software without specific prior written permission.
+ THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+ \sa isValid()
+*/
+
+int QDate::weekNumber(int *yearNumber) const
+{
+ if (!isValid())
+ return 0;
+
+ int year = QDate::year();
+ int yday = dayOfYear() - 1;
+ int wday = dayOfWeek();
+ if (wday == 7)
+ wday = 0;
+ int w;
+
+ for (;;) {
+ int len;
+ int bot;
+ int top;
+
+ len = isLeapYear(year) ? 366 : 365;
+ /*
+ ** What yday (-3 ... 3) does
+ ** the ISO year begin on?
+ */
+ bot = ((yday + 11 - wday) % 7) - 3;
+ /*
+ ** What yday does the NEXT
+ ** ISO year begin on?
+ */
+ top = bot - (len % 7);
+ if (top < -3)
+ top += 7;
+ top += len;
+ if (yday >= top) {
+ ++year;
+ w = 1;
+ break;
+ }
+ if (yday >= bot) {
+ w = 1 + ((yday - bot) / 7);
+ break;
+ }
+ --year;
+ yday += isLeapYear(year) ? 366 : 365;
+ }
+ if (yearNumber != 0)
+ *yearNumber = year;
+ return w;
+}
+
+#ifndef QT_NO_TEXTDATE
+/*!
+ \since 4.5
+
+ Returns the short name of the \a month for the representation specified
+ by \a type.
+
+ The months are enumerated using the following convention:
+
+ \list
+ \i 1 = "Jan"
+ \i 2 = "Feb"
+ \i 3 = "Mar"
+ \i 4 = "Apr"
+ \i 5 = "May"
+ \i 6 = "Jun"
+ \i 7 = "Jul"
+ \i 8 = "Aug"
+ \i 9 = "Sep"
+ \i 10 = "Oct"
+ \i 11 = "Nov"
+ \i 12 = "Dec"
+ \endlist
+
+ The month names will be localized according to the system's locale
+ settings.
+
+ \sa toString(), longMonthName(), shortDayName(), longDayName()
+*/
+
+QString QDate::shortMonthName(int month, QDate::MonthNameType type)
+{
+ if (month < 1 || month > 12) {
+ month = 1;
+ }
+ switch (type) {
+ case QDate::DateFormat:
+ return QLocale::system().monthName(month, QLocale::ShortFormat);
+ case QDate::StandaloneFormat:
+ return QLocale::system().standaloneMonthName(month, QLocale::ShortFormat);
+ default:
+ break;
+ }
+ return QString();
+}
+
+/*!
+ Returns the short version of the name of the \a month. The
+ returned name is in normal type which can be used for date formatting.
+
+ \sa toString(), longMonthName(), shortDayName(), longDayName()
+ */
+
+QString QDate::shortMonthName(int month)
+{
+ return shortMonthName(month, QDate::DateFormat);
+}
+
+/*!
+ \since 4.5
+
+ Returns the long name of the \a month for the representation specified
+ by \a type.
+
+ The months are enumerated using the following convention:
+
+ \list
+ \i 1 = "January"
+ \i 2 = "February"
+ \i 3 = "March"
+ \i 4 = "April"
+ \i 5 = "May"
+ \i 6 = "June"
+ \i 7 = "July"
+ \i 8 = "August"
+ \i 9 = "September"
+ \i 10 = "October"
+ \i 11 = "November"
+ \i 12 = "December"
+ \endlist
+
+ The month names will be localized according to the system's locale
+ settings.
+
+ \sa toString(), shortMonthName(), shortDayName(), longDayName()
+*/
+
+QString QDate::longMonthName(int month, MonthNameType type)
+{
+ if (month < 1 || month > 12) {
+ month = 1;
+ }
+ switch (type) {
+ case QDate::DateFormat:
+ return QLocale::system().monthName(month, QLocale::LongFormat);
+ case QDate::StandaloneFormat:
+ return QLocale::system().standaloneMonthName(month, QLocale::LongFormat);
+ default:
+ break;
+ }
+ return QString();
+}
+
+/*!
+ Returns the long version of the name of the \a month. The
+ returned name is in normal type which can be used for date formatting.
+
+ \sa toString(), shortMonthName(), shortDayName(), longDayName()
+ */
+
+QString QDate::longMonthName(int month)
+{
+ if (month < 1 || month > 12) {
+ month = 1;
+ }
+ return QLocale::system().monthName(month, QLocale::LongFormat);
+}
+
+/*!
+ \since 4.5
+
+ Returns the short name of the \a weekday for the representation specified
+ by \a type.
+
+ The days are enumerated using the following convention:
+
+ \list
+ \i 1 = "Mon"
+ \i 2 = "Tue"
+ \i 3 = "Wed"
+ \i 4 = "Thu"
+ \i 5 = "Fri"
+ \i 6 = "Sat"
+ \i 7 = "Sun"
+ \endlist
+
+ The day names will be localized according to the system's locale
+ settings.
+
+ \sa toString(), shortMonthName(), longMonthName(), longDayName()
+*/
+
+QString QDate::shortDayName(int weekday, MonthNameType type)
+{
+ if (weekday < 1 || weekday > 7) {
+ weekday = 1;
+ }
+ switch (type) {
+ case QDate::DateFormat:
+ return QLocale::system().dayName(weekday, QLocale::ShortFormat);
+ case QDate::StandaloneFormat:
+ return QLocale::system().standaloneDayName(weekday, QLocale::ShortFormat);
+ default:
+ break;
+ }
+ return QString();
+}
+
+/*!
+ Returns the short version of the name of the \a weekday. The
+ returned name is in normal type which can be used for date formatting.
+
+ \sa toString(), longDayName(), shortMonthName(), longMonthName()
+ */
+
+QString QDate::shortDayName(int weekday)
+{
+ if (weekday < 1 || weekday > 7) {
+ weekday = 1;
+ }
+ return QLocale::system().dayName(weekday, QLocale::ShortFormat);
+}
+
+/*!
+ \since 4.5
+
+ Returns the long name of the \a weekday for the representation specified
+ by \a type.
+
+ The days are enumerated using the following convention:
+
+ \list
+ \i 1 = "Monday"
+ \i 2 = "Tuesday"
+ \i 3 = "Wednesday"
+ \i 4 = "Thursday"
+ \i 5 = "Friday"
+ \i 6 = "Saturday"
+ \i 7 = "Sunday"
+ \endlist
+
+ The day names will be localized according to the system's locale
+ settings.
+
+ \sa toString(), shortDayName(), shortMonthName(), longMonthName()
+*/
+
+QString QDate::longDayName(int weekday, MonthNameType type)
+{
+ if (weekday < 1 || weekday > 7) {
+ weekday = 1;
+ }
+ switch (type) {
+ case QDate::DateFormat:
+ return QLocale::system().dayName(weekday, QLocale::LongFormat);
+ case QDate::StandaloneFormat:
+ return QLocale::system().standaloneDayName(weekday, QLocale::LongFormat);
+ default:
+ break;
+ }
+ return QLocale::system().dayName(weekday, QLocale::LongFormat);
+}
+
+/*!
+ Returns the long version of the name of the \a weekday. The
+ returned name is in normal type which can be used for date formatting.
+
+ \sa toString(), shortDayName(), shortMonthName(), longMonthName()
+ */
+
+QString QDate::longDayName(int weekday)
+{
+ if (weekday < 1 || weekday > 7) {
+ weekday = 1;
+ }
+ return QLocale::system().dayName(weekday, QLocale::LongFormat);
+}
+#endif //QT_NO_TEXTDATE
+
+#ifndef QT_NO_DATESTRING
+
+/*!
+ \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. 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 QLocale().toString(date,
+ QLocale::ShortFormat) or QLocale().toString(date,
+ QLocale::LongFormat).
+
+ 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 shortDayName(), shortMonthName()
+*/
+QString QDate::toString(Qt::DateFormat f) const
+{
+ if (!isValid())
+ return QString();
+ int y, m, d;
+ getDateFromJulianDay(jd, &y, &m, &d);
+ switch (f) {
+ case Qt::SystemLocaleDate:
+ case Qt::SystemLocaleShortDate:
+ case Qt::SystemLocaleLongDate:
+ return QLocale::system().toString(*this, f == Qt::SystemLocaleLongDate ? QLocale::LongFormat
+ : QLocale::ShortFormat);
+ case Qt::LocaleDate:
+ case Qt::DefaultLocaleShortDate:
+ case Qt::DefaultLocaleLongDate:
+ return QLocale().toString(*this, f == Qt::DefaultLocaleLongDate ? QLocale::LongFormat
+ : QLocale::ShortFormat);
+ default:
+#ifndef QT_NO_TEXTDATE
+ case Qt::TextDate:
+ {
+ return QString::fromLatin1("%0 %1 %2 %3")
+ .arg(shortDayName(dayOfWeek()))
+ .arg(shortMonthName(m))
+ .arg(d)
+ .arg(y);
+ }
+#endif
+ case Qt::ISODate:
+ {
+ if (year() < 0 || year() > 9999)
+ return QString();
+ QString month(QString::number(m).rightJustified(2, QLatin1Char('0')));
+ QString day(QString::number(d).rightJustified(2, QLatin1Char('0')));
+ return QString::number(y) + QLatin1Char('-') + month + QLatin1Char('-') + day;
+ }
+ }
+}
+
+/*!
+ Returns the date as a string. The \a format parameter determines
+ the format of the result string.
+
+ These expressions may be used:
+
+ \table
+ \header \i Expression \i Output
+ \row \i d \i the day as number without a leading zero (1 to 31)
+ \row \i dd \i the day as number with a leading zero (01 to 31)
+ \row \i ddd
+ \i the abbreviated localized day name (e.g. 'Mon' to 'Sun').
+ Uses QDate::shortDayName().
+ \row \i dddd
+ \i the long localized day name (e.g. 'Monday' to 'Sunday').
+ Uses QDate::longDayName().
+ \row \i M \i the month as number without a leading zero (1 to 12)
+ \row \i MM \i the month as number with a leading zero (01 to 12)
+ \row \i MMM
+ \i the abbreviated localized month name (e.g. 'Jan' to 'Dec').
+ Uses QDate::shortMonthName().
+ \row \i MMMM
+ \i the long localized month name (e.g. 'January' to 'December').
+ Uses QDate::longMonthName().
+ \row \i yy \i the year as two digit number (00 to 99)
+ \row \i yyyy \i 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 ignored. Any sequence of characters that
+ are enclosed in singlequotes will be treated as text and not be used as an
+ expression. Two consecutive singlequotes ("''") are replaced by a singlequote
+ in the output.
+
+ Example format strings (assuming that the QDate is the 20 July
+ 1969):
+
+ \table
+ \header \o Format \o Result
+ \row \o dd.MM.yyyy \o 20.07.1969
+ \row \o ddd MMMM d yy \o Sun July 20 69
+ \row \o 'The day is' dddd \o The day is Sunday
+ \endtable
+
+ 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 QDateTime::toString() QTime::toString()
+
+*/
+QString QDate::toString(const QString& format) const
+{
+ if (year() > 9999)
+ return QString();
+ return fmtDateTime(format, 0, this);
+}
+#endif //QT_NO_DATESTRING
+
+/*!
+ \obsolete
+
+ 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.
+
+ Use setDate() instead.
+*/
+
+bool QDate::setYMD(int y, int m, int d)
+{
+ if (uint(y) <= 99)
+ y += 1900;
+ return setDate(y, m, d);
+}
+
+/*!
+ \since 4.2
+
+ Sets the date's \a year, \a month, and \a day. Returns true if
+ the date is valid; otherwise returns false.
+
+ If the specified date is invalid, the QDate object is set to be
+ invalid. Any date before 2 January 4713 B.C. is considered
+ invalid.
+
+ \sa isValid()
+*/
+bool QDate::setDate(int year, int month, int day)
+{
+ if (!isValid(year, month, day)) {
+ jd = 0;
+ } else {
+ jd = julianDayFromDate(year, month, day);
+ }
+ return jd != 0;
+}
+
+/*!
+ \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.
+
+ \sa year(), month(), day(), isValid()
+*/
+void QDate::getDate(int *year, int *month, int *day)
+{
+ getDateFromJulianDay(jd, year, month, day);
+}
+
+/*!
+ Returns a QDate object containing a date \a ndays later than the
+ date of this object (or earlier if \a ndays is negative).
+
+ \sa addMonths() addYears() daysTo()
+*/
+
+QDate QDate::addDays(int ndays) const
+{
+ QDate d;
+ // this is basically "d.jd = jd + ndays" with checks for integer overflow
+ if (ndays >= 0)
+ d.jd = (jd + ndays >= jd) ? jd + ndays : 0;
+ else
+ d.jd = (jd + ndays < jd) ? jd + ndays : 0;
+ return d;
+}
+
+/*!
+ 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.
+
+ \warning QDate has a date hole around the days introducing the
+ Gregorian calendar (the days 5 to 14 October 1582, inclusive, do
+ not exist). If the calculation ends in one of those days, QDate
+ will return either October 4 or October 15.
+
+ \sa addDays() addYears()
+*/
+
+QDate QDate::addMonths(int nmonths) const
+{
+ if (!isValid())
+ return QDate();
+ if (!nmonths)
+ return *this;
+
+ int old_y, y, m, d;
+ getDateFromJulianDay(jd, &y, &m, &d);
+ 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;
+
+ // did we end up in the Gregorian/Julian conversion hole?
+ if (y == 1582 && m == 10 && d > 4 && d < 15)
+ d = increasing ? 15 : 4;
+
+ 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();
+
+ int y, m, d;
+ getDateFromJulianDay(jd, &y, &m, &d);
+
+ int old_y = y;
+ y += nyears;
+
+ // 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 += nyears > 0 ? +1 : -1;
+
+ return fixedDate(y, m, d);
+}
+
+/*!
+ Returns the number of days from this date to \a d (which is
+ negative if \a d is earlier than this date).
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 0
+
+ \sa addDays()
+*/
+
+int QDate::daysTo(const QDate &d) const
+{
+ return d.jd - jd;
+}
+
+
+/*!
+ \fn bool QDate::operator==(const QDate &d) const
+
+ Returns true if this date is equal to \a d; otherwise returns
+ false.
+
+*/
+
+/*!
+ \fn bool QDate::operator!=(const QDate &d) const
+
+ Returns true if this date is different from \a d; otherwise
+ returns false.
+*/
+
+/*!
+ \fn bool QDate::operator<(const QDate &d) const
+
+ Returns true if this date is earlier than \a d; otherwise returns
+ false.
+*/
+
+/*!
+ \fn bool QDate::operator<=(const QDate &d) const
+
+ Returns true if this date is earlier than or equal to \a d;
+ otherwise returns false.
+*/
+
+/*!
+ \fn bool QDate::operator>(const QDate &d) const
+
+ Returns true if this date is later than \a d; otherwise returns
+ false.
+*/
+
+/*!
+ \fn bool QDate::operator>=(const QDate &d) const
+
+ Returns true if this date is later than or equal to \a d;
+ otherwise returns false.
+*/
+
+/*!
+ \fn QDate::currentDate()
+ Returns the current date, as reported by the system clock.
+
+ \sa QTime::currentTime(), QDateTime::currentDateTime()
+*/
+
+#ifndef QT_NO_DATESTRING
+/*!
+ \fn QDate QDate::fromString(const QString &string, Qt::DateFormat format)
+
+ 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.
+*/
+QDate QDate::fromString(const QString& s, Qt::DateFormat f)
+{
+ if (s.isEmpty())
+ return QDate();
+
+ switch (f) {
+ case Qt::ISODate:
+ {
+ int year(s.mid(0, 4).toInt());
+ int month(s.mid(5, 2).toInt());
+ int day(s.mid(8, 2).toInt());
+ if (year && month && day)
+ return QDate(year, month, day);
+ }
+ break;
+ case Qt::SystemLocaleDate:
+ case Qt::SystemLocaleShortDate:
+ case Qt::SystemLocaleLongDate:
+ return fromString(s, QLocale::system().dateFormat(f == Qt::SystemLocaleLongDate ? QLocale::LongFormat
+ : QLocale::ShortFormat));
+ case Qt::LocaleDate:
+ case Qt::DefaultLocaleShortDate:
+ case Qt::DefaultLocaleLongDate:
+ return fromString(s, QLocale().dateFormat(f == Qt::DefaultLocaleLongDate ? QLocale::LongFormat
+ : QLocale::ShortFormat));
+ default:
+#ifndef QT_NO_TEXTDATE
+ case Qt::TextDate: {
+ QStringList parts = s.split(QLatin1Char(' '), QString::SkipEmptyParts);
+
+ if (parts.count() != 4) {
+ return QDate();
+ }
+
+ QString monthName = parts.at(1);
+ int month = -1;
+ // Assume that English monthnames are the default
+ for (int i = 0; i < 12; ++i) {
+ if (monthName == QLatin1String(qt_shortMonthNames[i])) {
+ month = i + 1;
+ break;
+ }
+ }
+ // If English names can't be found, search the localized ones
+ if (month == -1) {
+ for (int i = 1; i <= 12; ++i) {
+ if (monthName == QDate::shortMonthName(i)) {
+ month = i;
+ break;
+ }
+ }
+ }
+ if (month < 1 || month > 12) {
+ return QDate();
+ }
+
+ bool ok;
+ int day = parts.at(2).toInt(&ok);
+ if (!ok) {
+ return QDate();
+ }
+
+ int year = parts.at(3).toInt(&ok);
+ if (!ok) {
+ return QDate();
+ }
+
+ return QDate(year, month, day);
+ }
+#else
+ break;
+#endif
+ }
+ return QDate();
+}
+
+/*!
+ \fn QDate::fromString(const QString &string, const QString &format)
+
+ 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 \i Expression \i Output
+ \row \i d \i The day as a number without a leading zero (1 to 31)
+ \row \i dd \i The day as a number with a leading zero (01 to 31)
+ \row \i ddd
+ \i The abbreviated localized day name (e.g. 'Mon' to 'Sun').
+ Uses QDate::shortDayName().
+ \row \i dddd
+ \i The long localized day name (e.g. 'Monday' to 'Sunday').
+ Uses QDate::longDayName().
+ \row \i M \i The month as a number without a leading zero (1 to 12)
+ \row \i MM \i The month as a number with a leading zero (01 to 12)
+ \row \i MMM
+ \i The abbreviated localized month name (e.g. 'Jan' to 'Dec').
+ Uses QDate::shortMonthName().
+ \row \i MMMM
+ \i The long localized month name (e.g. 'January' to 'December').
+ Uses QDate::longMonthName().
+ \row \i yy \i The year as two digit number (00 to 99)
+ \row \i yyyy \i 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 doc/src/snippets/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 doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 2
+
+ For any field that is not represented in the format the following
+ defaults are used:
+
+ \table
+ \header \i Field \i Default value
+ \row \i Year \i 1900
+ \row \i Month \i 1
+ \row \i Day \i 1
+ \endtable
+
+ The following examples demonstrate the default values:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 3
+
+ \sa QDateTime::fromString(), QTime::fromString(), QDate::toString(),
+ QDateTime::toString(), QTime::toString()
+*/
+
+QDate QDate::fromString(const QString &string, const QString &format)
+{
+ QDate date;
+#ifndef QT_BOOTSTRAPPED
+ QDateTimeParser dt(QVariant::Date, QDateTimeParser::FromString);
+ if (dt.parseFormat(format))
+ dt.fromString(string, &date, 0);
+#else
+ Q_UNUSED(string);
+ Q_UNUSED(format);
+#endif
+ return date;
+}
+#endif // QT_NO_DATESTRING
+
+/*!
+ \overload
+
+ Returns true if the specified date (\a year, \a month, and \a
+ day) is valid; otherwise returns false.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 4
+
+ \sa isNull(), setDate()
+*/
+
+bool QDate::isValid(int year, int month, int day)
+{
+ if (year < FIRST_YEAR
+ || (year == FIRST_YEAR &&
+ (month < FIRST_MONTH
+ || (month == FIRST_MONTH && day < FIRST_DAY)))
+ || year == 0) // there is no year 0 in the Julian calendar
+ return false;
+
+ // passage from Julian to Gregorian calendar
+ if (year == 1582 && month == 10 && day > 4 && day < 15)
+ return 0;
+
+ return (day > 0 && month > 0 && month <= 12) &&
+ (day <= monthDays[month] || (day == 29 && month == 2 && isLeapYear(year)));
+}
+
+/*!
+ \fn bool QDate::isLeapYear(int year)
+
+ Returns true if the specified \a year is a leap year; otherwise
+ returns false.
+*/
+
+bool QDate::isLeapYear(int y)
+{
+ if (y < 1582) {
+ if ( y < 1) { // No year 0 in Julian calendar, so -1, -5, -9 etc are leap years
+ ++y;
+ }
+ return y % 4 == 0;
+ } else {
+ return (y % 4 == 0 && y % 100 != 0) || y % 400 == 0;
+ }
+}
+
+/*!
+ \internal
+
+ This function has a confusing name and shouldn't be part of the
+ API anyway, since we have toJulian() and fromJulian().
+ ### Qt 5: remove it
+*/
+uint QDate::gregorianToJulian(int y, int m, int d)
+{
+ return julianDayFromDate(y, m, d);
+}
+
+/*!
+ \internal
+
+ This function has a confusing name and shouldn't be part of the
+ API anyway, since we have toJulian() and fromJulian().
+ ### Qt 5: remove it
+*/
+void QDate::julianToGregorian(uint jd, int &y, int &m, int &d)
+{
+ getDateFromJulianDay(jd, &y, &m, &d);
+}
+
+/*! \fn static QDate QDate::fromJulianDay(int 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
+ \reentrant
+
+ \brief The QTime class provides clock time functions.
+
+
+ A QTime object contains a clock time, i.e. the number 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.
+
+ QTime uses the 24-hour clock format; it has no concept of AM/PM.
+ Unlike QDateTime, QTime knows nothing about time zones or
+ daylight savings 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.
+
+ QTime provides a full set of operators to compare two QTime
+ objects. One time is considered smaller than another if it is
+ earlier than the other.
+
+ The time a given number of seconds or milliseconds later than a
+ given time can be found using the addSecs() or addMSecs()
+ functions. Correspondingly, the number of seconds or milliseconds
+ between two times can be found using secsTo() or msecsTo().
+
+ QTime can be used to measure a span of elapsed time using the
+ start(), restart(), and elapsed() functions.
+
+ \sa QDate, QDateTime
+*/
+
+/*!
+ \fn QTime::QTime()
+
+ Constructs a null time object. A null time can be a QTime(0, 0, 0, 0)
+ (i.e., midnight) object, except that isNull() returns true and isValid()
+ returns false.
+
+ \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 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 true if the time is valid; otherwise returns 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.
+
+ \sa minute(), second(), msec()
+*/
+
+int QTime::hour() const
+{
+ return ds() / MSECS_PER_HOUR;
+}
+
+/*!
+ Returns the minute part (0 to 59) of the time.
+
+ \sa hour(), second(), msec()
+*/
+
+int QTime::minute() const
+{
+ return (ds() % MSECS_PER_HOUR) / MSECS_PER_MIN;
+}
+
+/*!
+ Returns the second part (0 to 59) of the time.
+
+ \sa hour(), minute(), msec()
+*/
+
+int QTime::second() const
+{
+ return (ds() / 1000)%SECS_PER_MIN;
+}
+
+/*!
+ Returns the millisecond part (0 to 999) of the time.
+
+ \sa hour(), minute(), second()
+*/
+
+int QTime::msec() const
+{
+ return ds() % 1000;
+}
+
+#ifndef QT_NO_DATESTRING
+/*!
+ \overload
+
+ Returns the time as a string. Milliseconds are not included. 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,
+ which is also HH:MM:SS. (However, contrary to ISO 8601, dates
+ before 15 October 1582 are handled as Julian dates, not Gregorian
+ dates. See \l{QDate G and J} {Use of Gregorian and Julian
+ Calendars}. This might change in a future version of Qt.)
+
+ 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 QLocale().toString(time,
+ QLocale::ShortFormat) or QLocale().toString(time,
+ QLocale::LongFormat).
+
+ If the time is invalid, an empty string will be returned.
+*/
+
+QString QTime::toString(Qt::DateFormat format) const
+{
+ if (!isValid())
+ return QString();
+
+ switch (format) {
+ case Qt::SystemLocaleDate:
+ case Qt::SystemLocaleShortDate:
+ case Qt::SystemLocaleLongDate:
+ return QLocale::system().toString(*this, format == Qt::SystemLocaleLongDate ? QLocale::LongFormat
+ : QLocale::ShortFormat);
+ case Qt::LocaleDate:
+ case Qt::DefaultLocaleShortDate:
+ case Qt::DefaultLocaleLongDate:
+ return QLocale().toString(*this, format == Qt::DefaultLocaleLongDate ? QLocale::LongFormat
+ : QLocale::ShortFormat);
+
+ default:
+ case Qt::ISODate:
+ case Qt::TextDate:
+ return QString::fromLatin1("%1:%2:%3")
+ .arg(hour(), 2, 10, QLatin1Char('0'))
+ .arg(minute(), 2, 10, QLatin1Char('0'))
+ .arg(second(), 2, 10, QLatin1Char('0'));
+ }
+}
+
+/*!
+ Returns the time as a string. The \a format parameter determines
+ the format of the result string.
+
+ These expressions may be used:
+
+ \table
+ \header \i Expression \i Output
+ \row \i h
+ \i the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
+ \row \i hh
+ \i the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
+ \row \i H
+ \i the hour without a leading zero (0 to 23, even with AM/PM display)
+ \row \i HH
+ \i the hour with a leading zero (00 to 23, even with AM/PM display)
+ \row \i m \i the minute without a leading zero (0 to 59)
+ \row \i mm \i the minute with a leading zero (00 to 59)
+ \row \i s \i the second without a leading zero (0 to 59)
+ \row \i ss \i the second with a leading zero (00 to 59)
+ \row \i z \i the milliseconds without leading zeroes (0 to 999)
+ \row \i zzz \i the milliseconds with leading zeroes (000 to 999)
+ \row \i AP or A
+ \i use AM/PM display. \e AP will be replaced by either "AM" or "PM".
+ \row \i ap or a
+ \i use am/pm display. \e ap will be replaced by either "am" or "pm".
+ \row \i t \i the timezone (for example "CEST")
+ \endtable
+
+ All other input characters will be ignored. Any sequence of characters that
+ are enclosed in singlequotes will be treated as text and not be used as an
+ expression. Two consecutive singlequotes ("''") are replaced by a singlequote
+ in the output.
+
+ Example format strings (assuming that the QTime is 14:13:09.042)
+
+ \table
+ \header \i Format \i Result
+ \row \i hh:mm:ss.zzz \i 14:13:09.042
+ \row \i h:m:s ap \i 2:13:9 pm
+ \row \i H:m:s a \i 14:13:9 pm
+ \endtable
+
+ If the datetime is invalid, an empty string will be returned.
+ If \a format is empty, the default format "hh:mm:ss" is used.
+
+ \sa QDate::toString() QDateTime::toString()
+*/
+QString QTime::toString(const QString& format) const
+{
+ return fmtDateTime(format, this, 0);
+}
+#endif //QT_NO_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 true if the set time is valid; otherwise returns false.
+
+ \sa isValid()
+*/
+
+bool QTime::setHMS(int h, int m, int s, int ms)
+{
+#if defined(Q_OS_WINCE)
+ startTick = NullTime;
+#endif
+ 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.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 5
+
+ \sa addMSecs(), secsTo(), QDateTime::addSecs()
+*/
+
+QTime QTime::addSecs(int s) const
+{
+ 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.
+
+ \sa addSecs(), QDateTime::secsTo()
+*/
+
+int QTime::secsTo(const QTime &t) const
+{
+ return (t.ds() - ds()) / 1000;
+}
+
+/*!
+ 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.
+
+ \sa addSecs(), msecsTo(), QDateTime::addMSecs()
+*/
+
+QTime QTime::addMSecs(int ms) const
+{
+ QTime t;
+ if (ms < 0) {
+ // % not well-defined for -ve, but / is.
+ 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;
+ }
+#if defined(Q_OS_WINCE)
+ if (startTick > NullTime)
+ t.startTick = (startTick + ms) % MSECS_PER_DAY;
+#endif
+ 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.
+
+ \sa secsTo(), addMSecs(), QDateTime::msecsTo()
+*/
+
+int QTime::msecsTo(const QTime &t) const
+{
+#if defined(Q_OS_WINCE)
+ // GetLocalTime() for Windows CE has no milliseconds resolution
+ if (t.startTick > NullTime && startTick > NullTime)
+ return t.startTick - startTick;
+ else
+#endif
+ return t.ds() - ds();
+}
+
+
+/*!
+ \fn bool QTime::operator==(const QTime &t) const
+
+ Returns true if this time is equal to \a t; otherwise returns false.
+*/
+
+/*!
+ \fn bool QTime::operator!=(const QTime &t) const
+
+ Returns true if this time is different from \a t; otherwise returns false.
+*/
+
+/*!
+ \fn bool QTime::operator<(const QTime &t) const
+
+ Returns true if this time is earlier than \a t; otherwise returns false.
+*/
+
+/*!
+ \fn bool QTime::operator<=(const QTime &t) const
+
+ Returns true if this time is earlier than or equal to \a t;
+ otherwise returns false.
+*/
+
+/*!
+ \fn bool QTime::operator>(const QTime &t) const
+
+ Returns true if this time is later than \a t; otherwise returns false.
+*/
+
+/*!
+ \fn bool QTime::operator>=(const QTime &t) const
+
+ Returns true if this time is later than or equal to \a t;
+ otherwise returns false.
+*/
+
+/*!
+ \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.
+*/
+
+#ifndef QT_NO_DATESTRING
+/*!
+ \fn QTime QTime::fromString(const QString &string, Qt::DateFormat format)
+
+ 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.
+*/
+QTime QTime::fromString(const QString& s, Qt::DateFormat f)
+{
+ if (s.isEmpty()) {
+ QTime t;
+ t.mds = NullTime;
+ return t;
+ }
+
+ switch (f) {
+ case Qt::SystemLocaleDate:
+ case Qt::SystemLocaleShortDate:
+ case Qt::SystemLocaleLongDate:
+ return fromString(s, QLocale::system().timeFormat(f == Qt::SystemLocaleLongDate ? QLocale::LongFormat
+ : QLocale::ShortFormat));
+ case Qt::LocaleDate:
+ case Qt::DefaultLocaleShortDate:
+ case Qt::DefaultLocaleLongDate:
+ return fromString(s, QLocale().timeFormat(f == Qt::DefaultLocaleLongDate ? QLocale::LongFormat
+ : QLocale::ShortFormat));
+ default:
+ {
+ bool ok = true;
+ const int hour(s.mid(0, 2).toInt(&ok));
+ if (!ok)
+ return QTime();
+ const int minute(s.mid(3, 2).toInt(&ok));
+ if (!ok)
+ return QTime();
+ const int second(s.mid(6, 2).toInt(&ok));
+ if (!ok)
+ return QTime();
+ const QString msec_s(QLatin1String("0.") + s.mid(9, 4));
+ const float msec(msec_s.toFloat(&ok));
+ if (!ok)
+ return QTime(hour, minute, second, 0);
+ return QTime(hour, minute, second, qMin(qRound(msec * 1000.0), 999));
+ }
+ }
+}
+
+/*!
+ \fn QTime::fromString(const QString &string, const QString &format)
+
+ 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 \i Expression \i Output
+ \row \i h
+ \i the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
+ \row \i hh
+ \i the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
+ \row \i m \i the minute without a leading zero (0 to 59)
+ \row \i mm \i the minute with a leading zero (00 to 59)
+ \row \i s \i the second without a leading zero (0 to 59)
+ \row \i ss \i the second with a leading zero (00 to 59)
+ \row \i z \i the milliseconds without leading zeroes (0 to 999)
+ \row \i zzz \i the milliseconds with leading zeroes (000 to 999)
+ \row \i AP
+ \i interpret as an AM/PM time. \e AP must be either "AM" or "PM".
+ \row \i ap
+ \i 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 doc/src/snippets/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 doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 7
+
+ Any field that is not represented in the format will be set to zero.
+ For example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 8
+
+ \sa QDateTime::fromString() QDate::fromString() QDate::toString()
+ QDateTime::toString() QTime::toString()
+*/
+
+QTime QTime::fromString(const QString &string, const QString &format)
+{
+ QTime time;
+#ifndef QT_BOOTSTRAPPED
+ QDateTimeParser dt(QVariant::Time, QDateTimeParser::FromString);
+ if (dt.parseFormat(format))
+ dt.fromString(string, 0, &time);
+#else
+ Q_UNUSED(string);
+ Q_UNUSED(format);
+#endif
+ return time;
+}
+
+#endif // QT_NO_DATESTRING
+
+
+/*!
+ \overload
+
+ Returns 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 doc/src/snippets/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;
+}
+
+
+/*!
+ Sets this time to the current time. This is practical for timing:
+
+ \snippet doc/src/snippets/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 savings 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 savings 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;
+}
+
+
+/*****************************************************************************
+ QDateTime member functions
+ *****************************************************************************/
+
+/*!
+ \class QDateTime
+ \reentrant
+ \brief The QDateTime class provides date and time functions.
+
+
+ A QDateTime object contains a calendar date and a clock time (a
+ "datetime"). It is a combination 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
+
+ \target QDateTime G and J
+ \section2 Use of Gregorian and Julian Calendars
+
+ QDate uses the Gregorian calendar in all locales, beginning
+ on the date 15 October 1582. For dates up to and including 4
+ October 1582, the Julian calendar is used. This means there is a
+ 10-day gap in the internal calendar between the 4th and the 15th
+ of October 1582. When you use QDateTime for dates in that epoch,
+ the day after 4 October 1582 is 15 October 1582, and the dates in
+ the gap are invalid.
+
+ The Julian to Gregorian changeover date used here is the date when
+ the Gregorian calendar was first introduced, by Pope Gregory
+ XIII. That change was not universally accepted and some localities
+ only executed it at a later date (if at all). QDateTime
+ doesn't take any of these historical facts into account. If an
+ application must support a locale-specific dating system, it must
+ do so on its own, remembering to convert the dates using the
+ Julian day.
+
+ \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 0001-01-01 is December 31st, 1 BCE.
+
+ \section2 Range of Valid Dates
+
+ The range of valid dates is from January 2nd, 4713 BCE, to
+ sometime in the year 11 million CE. The Julian Day returned by
+ QDate::toJulianDay() is a number in the contiguous range from 1 to
+ \e{overflow}, even across QDateTime's "date holes". It is suitable
+ for use in applications that must convert a QDateTime to a date in
+ another calendar system, e.g., Hebrew, Islamic or Chinese.
+
+ The Gregorian calendar was introduced in different places around
+ the world on different dates. QDateTime uses QDate to store the
+ date, so it uses the Gregorian calendar for all locales, beginning
+ on the date 15 October 1582. For dates up to and including 4
+ October 1582, QDateTime uses the Julian calendar. This means
+ there is a 10-day gap in the QDateTime calendar between the 4th
+ and the 15th of October 1582. When you use QDateTime for dates in
+ that epoch, the day after 4 October 1582 is 15 October 1582, and
+ the dates in the gap are invalid.
+
+ \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 Savings 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 and Windows CE, 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.
+
+ \sa QDate QTime QDateTimeEdit
+*/
+
+/*!
+ 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()
+ : d(new QDateTimePrivate)
+{
+}
+
+
+/*!
+ 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(new QDateTimePrivate)
+{
+ d->date = date;
+ d->time = QTime(0, 0, 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.
+*/
+
+QDateTime::QDateTime(const QDate &date, const QTime &time, Qt::TimeSpec spec)
+ : d(new QDateTimePrivate)
+{
+ d->date = date;
+ d->time = date.isValid() && !time.isValid() ? QTime(0, 0, 0) : time;
+ d->spec = (spec == Qt::UTC) ? QDateTimePrivate::UTC : QDateTimePrivate::LocalUnknown;
+}
+
+/*!
+ Constructs a copy of the \a other datetime.
+*/
+
+QDateTime::QDateTime(const QDateTime &other)
+ : d(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)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Returns true if both the date and the time are null; otherwise
+ returns false. A null datetime is invalid.
+
+ \sa QDate::isNull(), QTime::isNull(), isValid()
+*/
+
+bool QDateTime::isNull() const
+{
+ return d->date.isNull() && d->time.isNull();
+}
+
+/*!
+ Returns true if both the date and the time are valid; otherwise
+ returns false.
+
+ \sa QDate::isValid(), QTime::isValid()
+*/
+
+bool QDateTime::isValid() const
+{
+ return d->date.isValid() && d->time.isValid();
+}
+
+/*!
+ Returns the date part of the datetime.
+
+ \sa setDate(), time(), timeSpec()
+*/
+
+QDate QDateTime::date() const
+{
+ return d->date;
+}
+
+/*!
+ Returns the time part of the datetime.
+
+ \sa setTime(), date(), timeSpec()
+*/
+
+QTime QDateTime::time() const
+{
+ return d->time;
+}
+
+/*!
+ Returns the time specification of the datetime.
+
+ \sa setTimeSpec(), date(), time(), Qt::TimeSpec
+*/
+
+Qt::TimeSpec QDateTime::timeSpec() const
+{
+ switch(d->spec)
+ {
+ case QDateTimePrivate::UTC:
+ return Qt::UTC;
+ case QDateTimePrivate::OffsetFromUTC:
+ return Qt::OffsetFromUTC;
+ default:
+ return Qt::LocalTime;
+ }
+}
+
+/*!
+ Sets the date part of this datetime to \a date.
+ If no time is set, it is set to midnight.
+
+ \sa date(), setTime(), setTimeSpec()
+*/
+
+void QDateTime::setDate(const QDate &date)
+{
+ detach();
+ d->date = date;
+ if (d->spec == QDateTimePrivate::LocalStandard
+ || d->spec == QDateTimePrivate::LocalDST)
+ d->spec = QDateTimePrivate::LocalUnknown;
+ if (date.isValid() && !d->time.isValid())
+ d->time = QTime(0, 0, 0);
+}
+
+/*!
+ Sets the time part of this datetime to \a time.
+
+ \sa time(), setDate(), setTimeSpec()
+*/
+
+void QDateTime::setTime(const QTime &time)
+{
+ detach();
+ if (d->spec == QDateTimePrivate::LocalStandard
+ || d->spec == QDateTimePrivate::LocalDST)
+ d->spec = QDateTimePrivate::LocalUnknown;
+ d->time = time;
+}
+
+/*!
+ Sets the time specification used in this datetime to \a spec.
+
+ \sa timeSpec(), setDate(), setTime(), Qt::TimeSpec
+*/
+
+void QDateTime::setTimeSpec(Qt::TimeSpec spec)
+{
+ detach();
+
+ switch(spec)
+ {
+ case Qt::UTC:
+ d->spec = QDateTimePrivate::UTC;
+ break;
+ case Qt::OffsetFromUTC:
+ d->spec = QDateTimePrivate::OffsetFromUTC;
+ break;
+ default:
+ d->spec = QDateTimePrivate::LocalUnknown;
+ break;
+ }
+}
+
+qint64 toMSecsSinceEpoch_helper(qint64 jd, int msecs)
+{
+ qint64 days = jd - JULIAN_DAY_FOR_EPOCH;
+ qint64 retval = (days * MSECS_PER_DAY) + msecs;
+ return retval;
+}
+
+/*!
+ \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 toTime_t(), setMSecsSinceEpoch()
+*/
+qint64 QDateTime::toMSecsSinceEpoch() const
+{
+ QDate utcDate;
+ QTime utcTime;
+ d->getUTC(utcDate, utcTime);
+
+ return toMSecsSinceEpoch_helper(utcDate.jd, utcTime.ds());
+}
+
+/*!
+ 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, so it does not
+ support dates before 1970, but it does support dates after
+ 2038-01-19T03:14:06, which may not be valid time_t values. Be careful
+ when passing those time_t values to system functions, which could
+ interpret them as negative dates.
+
+ 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().
+
+ \sa toMSecsSinceEpoch(), setTime_t()
+*/
+
+uint QDateTime::toTime_t() const
+{
+ qint64 retval = toMSecsSinceEpoch() / 1000;
+ if (quint64(retval) >= Q_UINT64_C(0xFFFFFFFF))
+ return uint(-1);
+ return uint(retval);
+}
+
+/*!
+ \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 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(), setTime_t()
+*/
+void QDateTime::setMSecsSinceEpoch(qint64 msecs)
+{
+ detach();
+
+ QDateTimePrivate::Spec oldSpec = d->spec;
+
+ int ddays = msecs / MSECS_PER_DAY;
+ msecs %= MSECS_PER_DAY;
+ if (msecs < 0) {
+ // negative
+ --ddays;
+ msecs += MSECS_PER_DAY;
+ }
+
+ d->date = QDate(1970, 1, 1).addDays(ddays);
+ d->time = QTime().addMSecs(msecs);
+ d->spec = QDateTimePrivate::UTC;
+
+ if (oldSpec != QDateTimePrivate::UTC)
+ d->spec = d->getLocal(d->date, d->time);
+}
+
+/*!
+ \fn void QDateTime::setTime_t(uint seconds)
+
+ 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.
+
+ \sa toTime_t()
+*/
+
+void QDateTime::setTime_t(uint secsSince1Jan1970UTC)
+{
+ detach();
+
+ QDateTimePrivate::Spec oldSpec = d->spec;
+
+ d->date = QDate(1970, 1, 1).addDays(secsSince1Jan1970UTC / SECS_PER_DAY);
+ d->time = QTime().addSecs(secsSince1Jan1970UTC % SECS_PER_DAY);
+ d->spec = QDateTimePrivate::UTC;
+
+ if (oldSpec != QDateTimePrivate::UTC)
+ d->spec = d->getLocal(d->date, d->time);
+}
+
+#ifndef QT_NO_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. 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.
+
+ 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 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 QDate::toString() QTime::toString() Qt::DateFormat
+*/
+
+QString QDateTime::toString(Qt::DateFormat f) const
+{
+ QString buf;
+ if (!isValid())
+ return buf;
+
+ if (f == Qt::ISODate) {
+ buf = d->date.toString(Qt::ISODate);
+ if (buf.isEmpty())
+ return QString(); // failed to convert
+ buf += QLatin1Char('T');
+ buf += d->time.toString(Qt::ISODate);
+ }
+#ifndef QT_NO_TEXTDATE
+ else if (f == Qt::TextDate) {
+#ifndef Q_WS_WIN
+ buf = d->date.shortDayName(d->date.dayOfWeek());
+ buf += QLatin1Char(' ');
+ buf += d->date.shortMonthName(d->date.month());
+ buf += QLatin1Char(' ');
+ buf += QString::number(d->date.day());
+#else
+ wchar_t out[255];
+ GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_ILDATE, out, 255);
+ QString winstr = QString::fromWCharArray(out);
+ switch (winstr.toInt()) {
+ case 1:
+ buf = d->date.shortDayName(d->date.dayOfWeek());
+ buf += QLatin1Char(' ');
+ buf += QString::number(d->date.day());
+ buf += QLatin1String(". ");
+ buf += d->date.shortMonthName(d->date.month());
+ break;
+ default:
+ buf = d->date.shortDayName(d->date.dayOfWeek());
+ buf += QLatin1Char(' ');
+ buf += d->date.shortMonthName(d->date.month());
+ buf += QLatin1Char(' ');
+ buf += QString::number(d->date.day());
+ }
+#endif
+ buf += QLatin1Char(' ');
+ buf += d->time.toString();
+ buf += QLatin1Char(' ');
+ buf += QString::number(d->date.year());
+ }
+#endif
+ else {
+ buf = d->date.toString(f);
+ if (buf.isEmpty())
+ return QString(); // failed to convert
+ buf += QLatin1Char(' ');
+ buf += d->time.toString(f);
+ }
+
+ return buf;
+}
+
+/*!
+ 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 \i Expression \i Output
+ \row \i d \i the day as number without a leading zero (1 to 31)
+ \row \i dd \i the day as number with a leading zero (01 to 31)
+ \row \i ddd
+ \i the abbreviated localized day name (e.g. 'Mon' to 'Sun').
+ Uses QDate::shortDayName().
+ \row \i dddd
+ \i the long localized day name (e.g. 'Monday' to 'Qt::Sunday').
+ Uses QDate::longDayName().
+ \row \i M \i the month as number without a leading zero (1-12)
+ \row \i MM \i the month as number with a leading zero (01-12)
+ \row \i MMM
+ \i the abbreviated localized month name (e.g. 'Jan' to 'Dec').
+ Uses QDate::shortMonthName().
+ \row \i MMMM
+ \i the long localized month name (e.g. 'January' to 'December').
+ Uses QDate::longMonthName().
+ \row \i yy \i the year as two digit number (00-99)
+ \row \i yyyy \i the year as four digit number
+ \endtable
+
+ These expressions may be used for the time:
+
+ \table
+ \header \i Expression \i Output
+ \row \i h
+ \i the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
+ \row \i hh
+ \i the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
+ \row \i m \i the minute without a leading zero (0 to 59)
+ \row \i mm \i the minute with a leading zero (00 to 59)
+ \row \i s \i the second without a leading zero (0 to 59)
+ \row \i ss \i the second with a leading zero (00 to 59)
+ \row \i z \i the milliseconds without leading zeroes (0 to 999)
+ \row \i zzz \i the milliseconds with leading zeroes (000 to 999)
+ \row \i AP
+ \i use AM/PM display. \e AP will be replaced by either "AM" or "PM".
+ \row \i ap
+ \i use am/pm display. \e ap will be replaced by either "am" or "pm".
+ \endtable
+
+ All other input characters will be ignored. Any sequence of characters that
+ are enclosed in singlequotes will be treated as text and not be used as an
+ expression. Two consecutive singlequotes ("''") are replaced by a singlequote
+ in the output.
+
+ Example format strings (assumed that the QDateTime is 21 May 2001
+ 14:13:09):
+
+ \table
+ \header \i Format \i Result
+ \row \i dd.MM.yyyy \i 21.05.2001
+ \row \i ddd MMMM d yy \i Tue May 21 01
+ \row \i hh:mm:ss.zzz \i 14:13:09.042
+ \row \i h:m:s ap \i 2:13:9 pm
+ \endtable
+
+ If the datetime is invalid, an empty string will be returned.
+
+ \sa QDate::toString() QTime::toString()
+*/
+QString QDateTime::toString(const QString& format) const
+{
+ return fmtDateTime(format, &d->time, &d->date);
+}
+#endif //QT_NO_DATESTRING
+
+/*!
+ Returns a QDateTime object containing a datetime \a ndays days
+ later than the datetime of this object (or earlier if \a ndays is
+ negative).
+
+ \sa daysTo(), addMonths(), addYears(), addSecs()
+*/
+
+QDateTime QDateTime::addDays(int ndays) const
+{
+ return QDateTime(d->date.addDays(ndays), d->time, timeSpec());
+}
+
+/*!
+ Returns a QDateTime object containing a datetime \a nmonths months
+ later than the datetime of this object (or earlier if \a nmonths
+ is negative).
+
+ \sa daysTo(), addDays(), addYears(), addSecs()
+*/
+
+QDateTime QDateTime::addMonths(int nmonths) const
+{
+ return QDateTime(d->date.addMonths(nmonths), d->time, timeSpec());
+}
+
+/*!
+ Returns a QDateTime object containing a datetime \a nyears years
+ later than the datetime of this object (or earlier if \a nyears is
+ negative).
+
+ \sa daysTo(), addDays(), addMonths(), addSecs()
+*/
+
+QDateTime QDateTime::addYears(int nyears) const
+{
+ return QDateTime(d->date.addYears(nyears), d->time, timeSpec());
+}
+
+QDateTime QDateTimePrivate::addMSecs(const QDateTime &dt, qint64 msecs)
+{
+ QDate utcDate;
+ QTime utcTime;
+ dt.d->getUTC(utcDate, utcTime);
+
+ addMSecs(utcDate, utcTime, msecs);
+
+ return QDateTime(utcDate, utcTime, Qt::UTC).toTimeSpec(dt.timeSpec());
+}
+
+/*!
+ Adds \a msecs to utcDate and \a utcTime as appropriate. It is assumed that
+ utcDate and utcTime are adjusted to UTC.
+
+ \since 4.5
+ \internal
+ */
+void QDateTimePrivate::addMSecs(QDate &utcDate, QTime &utcTime, qint64 msecs)
+{
+ uint dd = utcDate.jd;
+ int tt = utcTime.ds();
+ int sign = 1;
+ if (msecs < 0) {
+ msecs = -msecs;
+ sign = -1;
+ }
+ if (msecs >= int(MSECS_PER_DAY)) {
+ dd += sign * (msecs / MSECS_PER_DAY);
+ msecs %= MSECS_PER_DAY;
+ }
+
+ tt += sign * msecs;
+ if (tt < 0) {
+ tt = MSECS_PER_DAY - tt - 1;
+ dd -= tt / MSECS_PER_DAY;
+ tt = tt % MSECS_PER_DAY;
+ tt = MSECS_PER_DAY - tt - 1;
+ } else if (tt >= int(MSECS_PER_DAY)) {
+ dd += tt / MSECS_PER_DAY;
+ tt = tt % MSECS_PER_DAY;
+ }
+
+ utcDate.jd = dd;
+ utcTime.mds = tt;
+}
+
+/*!
+ Returns a QDateTime object containing a datetime \a s seconds
+ later than the datetime of this object (or earlier if \a s is
+ negative).
+
+ \sa addMSecs(), secsTo(), addDays(), addMonths(), addYears()
+*/
+
+QDateTime QDateTime::addSecs(int s) const
+{
+ return d->addMSecs(*this, qint64(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).
+
+ \sa addSecs(), msecsTo(), addDays(), addMonths(), addYears()
+*/
+QDateTime QDateTime::addMSecs(qint64 msecs) const
+{
+ return d->addMSecs(*this, msecs);
+}
+
+/*!
+ Returns the number of days from this datetime to the \a other
+ datetime. If the \a other datetime is earlier than this datetime,
+ the value returned is negative.
+
+ \sa addDays(), secsTo(), msecsTo()
+*/
+
+int QDateTime::daysTo(const QDateTime &other) const
+{
+ return d->date.daysTo(other.d->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 one of the two
+ datetimes has daylight saving time (DST) and the other doesn't.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 11
+
+ \sa addSecs(), daysTo(), QTime::secsTo()
+*/
+
+int QDateTime::secsTo(const QDateTime &other) const
+{
+ QDate date1, date2;
+ QTime time1, time2;
+
+ d->getUTC(date1, time1);
+ other.d->getUTC(date2, time2);
+
+ return (date1.daysTo(date2) * SECS_PER_DAY) + time1.secsTo(time2);
+}
+
+/*!
+ 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 one of the two
+ datetimes has daylight saving time (DST) and the other doesn't.
+
+ \sa addMSecs(), daysTo(), QTime::msecsTo()
+*/
+
+qint64 QDateTime::msecsTo(const QDateTime &other) const
+{
+ QDate selfDate;
+ QDate otherDate;
+ QTime selfTime;
+ QTime otherTime;
+
+ d->getUTC(selfDate, selfTime);
+ other.d->getUTC(otherDate, otherTime);
+
+ return (static_cast<qint64>(selfDate.daysTo(otherDate)) * static_cast<qint64>(MSECS_PER_DAY))
+ + static_cast<qint64>(selfTime.msecsTo(otherTime));
+}
+
+
+/*!
+ \fn QDateTime QDateTime::toTimeSpec(Qt::TimeSpec specification) const
+
+ Returns a copy of this datetime configured to use the given time
+ \a specification.
+
+ \sa timeSpec(), toUTC(), toLocalTime()
+*/
+
+QDateTime QDateTime::toTimeSpec(Qt::TimeSpec spec) const
+{
+ if ((d->spec == QDateTimePrivate::UTC) == (spec == Qt::UTC))
+ return *this;
+
+ QDateTime ret;
+ if (spec == Qt::UTC) {
+ d->getUTC(ret.d->date, ret.d->time);
+ ret.d->spec = QDateTimePrivate::UTC;
+ } else {
+ ret.d->spec = d->getLocal(ret.d->date, ret.d->time);
+ }
+ return ret;
+}
+
+/*!
+ Returns true if this datetime is equal to the \a other datetime;
+ otherwise returns false.
+
+ \sa operator!=()
+*/
+
+bool QDateTime::operator==(const QDateTime &other) const
+{
+ if (d->spec == other.d->spec && d->utcOffset == other.d->utcOffset)
+ return d->time == other.d->time && d->date == other.d->date;
+ else {
+ QDate date1, date2;
+ QTime time1, time2;
+
+ d->getUTC(date1, time1);
+ other.d->getUTC(date2, time2);
+ return time1 == time2 && date1 == date2;
+ }
+}
+
+/*!
+ \fn bool QDateTime::operator!=(const QDateTime &other) const
+
+ Returns true if this datetime is different from the \a other
+ datetime; otherwise returns false.
+
+ Two datetimes are different if either the date, the time, or the
+ time zone components are different.
+
+ \sa operator==()
+*/
+
+/*!
+ Returns true if this datetime is earlier than the \a other
+ datetime; otherwise returns false.
+*/
+
+bool QDateTime::operator<(const QDateTime &other) const
+{
+ if (d->spec == other.d->spec && d->spec != QDateTimePrivate::OffsetFromUTC) {
+ if (d->date != other.d->date)
+ return d->date < other.d->date;
+ return d->time < other.d->time;
+ } else {
+ QDate date1, date2;
+ QTime time1, time2;
+ d->getUTC(date1, time1);
+ other.d->getUTC(date2, time2);
+ if (date1 != date2)
+ return date1 < date2;
+ return time1 < time2;
+ }
+}
+
+/*!
+ \fn bool QDateTime::operator<=(const QDateTime &other) const
+
+ Returns true if this datetime is earlier than or equal to the
+ \a other datetime; otherwise returns false.
+*/
+
+/*!
+ \fn bool QDateTime::operator>(const QDateTime &other) const
+
+ Returns true if this datetime is later than the \a other datetime;
+ otherwise returns false.
+*/
+
+/*!
+ \fn bool QDateTime::operator>=(const QDateTime &other) const
+
+ Returns true if this datetime is later than or equal to the
+ \a other datetime; otherwise returns 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()
+*/
+
+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;
+}
+
+#if defined(Q_OS_WIN)
+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.mds = msecsFromDecomposed(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
+#if defined(Q_OS_WINCE)
+ ct.startTick = GetTickCount() % MSECS_PER_DAY;
+#endif
+ 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()
+{
+ QDate d;
+ QTime t;
+ SYSTEMTIME st;
+ memset(&st, 0, sizeof(SYSTEMTIME));
+ GetSystemTime(&st);
+
+ return msecsFromDecomposed(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds) +
+ qint64(julianDayFromGregorianDate(st.wYear, st.wMonth, st.wDay)
+ - julianDayFromGregorianDate(1970, 1, 1)) * Q_INT64_C(86400000);
+}
+
+#elif defined(Q_OS_SYMBIAN)
+QDate QDate::currentDate()
+{
+ QDate d;
+ TTime localTime;
+ localTime.HomeTime();
+ TDateTime localDateTime = localTime.DateTime();
+ // months and days are zero indexed
+ d.jd = julianDayFromDate(localDateTime.Year(), localDateTime.Month() + 1, localDateTime.Day() + 1 );
+ return d;
+}
+
+QTime QTime::currentTime()
+{
+ QTime ct;
+ TTime localTime;
+ localTime.HomeTime();
+ TDateTime localDateTime = localTime.DateTime();
+ ct.mds = msecsFromDecomposed(localDateTime.Hour(), localDateTime.Minute(),
+ localDateTime.Second(), localDateTime.MicroSecond() / 1000);
+ return ct;
+}
+
+QDateTime QDateTime::currentDateTime()
+{
+ QDate d;
+ QTime ct;
+ TTime localTime;
+ localTime.HomeTime();
+ TDateTime localDateTime = localTime.DateTime();
+ // months and days are zero indexed
+ d.jd = julianDayFromDate(localDateTime.Year(), localDateTime.Month() + 1, localDateTime.Day() + 1);
+ ct.mds = msecsFromDecomposed(localDateTime.Hour(), localDateTime.Minute(),
+ localDateTime.Second(), localDateTime.MicroSecond() / 1000);
+ return QDateTime(d, ct);
+}
+
+QDateTime QDateTime::currentDateTimeUtc()
+{
+ QDate d;
+ QTime ct;
+ TTime gmTime;
+ gmTime.UniversalTime();
+ TDateTime gmtDateTime = gmTime.DateTime();
+ // months and days are zero indexed
+ d.jd = julianDayFromDate(gmtDateTime.Year(), gmtDateTime.Month() + 1, gmtDateTime.Day() + 1);
+ ct.mds = msecsFromDecomposed(gmtDateTime.Hour(), gmtDateTime.Minute(),
+ gmtDateTime.Second(), gmtDateTime.MicroSecond() / 1000);
+ return QDateTime(d, ct, Qt::UTC);
+}
+
+qint64 QDateTime::currentMSecsSinceEpoch()
+{
+ QDate d;
+ QTime ct;
+ TTime gmTime;
+ gmTime.UniversalTime();
+ TDateTime gmtDateTime = gmTime.DateTime();
+
+ // according to the documentation, the value is:
+ // "a date and time as a number of microseconds since midnight, January 1st, 0 AD nominal Gregorian"
+ qint64 value = gmTime.Int64();
+
+ // whereas 1970-01-01T00:00:00 is (in the same representation):
+ // ((1970 * 365) + (1970 / 4) - (1970 / 100) + (1970 / 400) - 13) * 86400 * 1000000
+ static const qint64 unixEpoch = Q_INT64_C(0xdcddb30f2f8000);
+
+ return (value - unixEpoch) / 1000;
+}
+
+#elif defined(Q_OS_UNIX)
+QDate QDate::currentDate()
+{
+ QDate d;
+ // posix compliant system
+ time_t ltime;
+ time(&ltime);
+ struct tm *t = 0;
+
+#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
+ // use the reentrant version of localtime() where available
+ tzset();
+ struct tm res;
+ t = localtime_r(&ltime, &res);
+#else
+ t = localtime(&ltime);
+#endif // !QT_NO_THREAD && _POSIX_THREAD_SAFE_FUNCTIONS
+
+ d.jd = julianDayFromDate(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday);
+ return d;
+}
+
+QTime QTime::currentTime()
+{
+ QTime ct;
+ // posix compliant system
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+ time_t ltime = tv.tv_sec;
+ struct tm *t = 0;
+
+#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
+ // use the reentrant version of localtime() where available
+ tzset();
+ struct tm res;
+ t = localtime_r(&ltime, &res);
+#else
+ t = localtime(&ltime);
+#endif
+ Q_CHECK_PTR(t);
+
+ ct.mds = msecsFromDecomposed(t->tm_hour, t->tm_min, t->tm_sec, tv.tv_usec / 1000);
+ return ct;
+}
+
+QDateTime QDateTime::currentDateTime()
+{
+ // posix compliant system
+ // we have milliseconds
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+ time_t ltime = tv.tv_sec;
+ struct tm *t = 0;
+
+#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
+ // use the reentrant version of localtime() where available
+ tzset();
+ struct tm res;
+ t = localtime_r(&ltime, &res);
+#else
+ t = localtime(&ltime);
+#endif
+
+ QDateTime dt;
+ dt.d->time.mds = msecsFromDecomposed(t->tm_hour, t->tm_min, t->tm_sec, tv.tv_usec / 1000);
+
+ dt.d->date.jd = julianDayFromDate(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday);
+ dt.d->spec = t->tm_isdst > 0 ? QDateTimePrivate::LocalDST :
+ t->tm_isdst == 0 ? QDateTimePrivate::LocalStandard :
+ QDateTimePrivate::LocalUnknown;
+ return dt;
+}
+
+QDateTime QDateTime::currentDateTimeUtc()
+{
+ // posix compliant system
+ // we have milliseconds
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+ time_t ltime = tv.tv_sec;
+ struct tm *t = 0;
+
+#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
+ // use the reentrant version of localtime() where available
+ struct tm res;
+ t = gmtime_r(&ltime, &res);
+#else
+ t = gmtime(&ltime);
+#endif
+
+ QDateTime dt;
+ dt.d->time.mds = msecsFromDecomposed(t->tm_hour, t->tm_min, t->tm_sec, tv.tv_usec / 1000);
+
+ dt.d->date.jd = julianDayFromDate(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday);
+ dt.d->spec = QDateTimePrivate::UTC;
+ return dt;
+}
+
+qint64 QDateTime::currentMSecsSinceEpoch()
+{
+ // 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;
+}
+
+#else
+#error "What system is this?"
+#endif
+
+/*!
+ \since 4.2
+
+ 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). On systems that do not support time zones, the time
+ will be set as if local time were Qt::UTC.
+
+ \sa toTime_t(), setTime_t()
+*/
+QDateTime QDateTime::fromTime_t(uint seconds)
+{
+ QDateTime d;
+ d.setTime_t(seconds);
+ return d;
+}
+
+/*!
+ \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). 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 toTime_t(), setTime_t()
+*/
+QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs)
+{
+ QDateTime d;
+ d.setMSecsSinceEpoch(msecs);
+ return d;
+}
+
+/*!
+ \since 4.4
+ \internal
+
+ Sets the offset from UTC to \a seconds, and also sets timeSpec() to
+ Qt::OffsetFromUTC.
+
+ The maximum and minimum offset is 14 positive or negative hours. If
+ \a seconds is larger or smaller than that, the result is undefined.
+
+ 0 as offset is identical to UTC. Therefore, if \a seconds is 0, the
+ timeSpec() will be set to Qt::UTC. Hence the UTC offset always
+ relates to UTC, and can never relate to local time.
+
+ \sa isValid(), utcOffset()
+ */
+void QDateTime::setUtcOffset(int seconds)
+{
+ detach();
+
+ /* The motivation to also setting d->spec is to ensure that the QDateTime
+ * instance stay in well-defined states all the time, instead of that
+ * we instruct the user to ensure it. */
+ if(seconds == 0)
+ d->spec = QDateTimePrivate::UTC;
+ else
+ d->spec = QDateTimePrivate::OffsetFromUTC;
+
+ /* Even if seconds is 0 we assign it to utcOffset. */
+ d->utcOffset = seconds;
+}
+
+/*!
+ \since 4.4
+ \internal
+
+ Returns the UTC offset in seconds. If the timeSpec() isn't
+ Qt::OffsetFromUTC, 0 is returned. However, since 0 is a valid UTC
+ offset the return value of this function cannot be used to determine
+ whether a utcOffset() is used or is valid, timeSpec() must be
+ checked.
+
+ Likewise, if this QDateTime() is invalid or if timeSpec() isn't
+ Qt::OffsetFromUTC, 0 is returned.
+
+ The UTC offset only applies if the timeSpec() is Qt::OffsetFromUTC.
+
+ \sa isValid(), setUtcOffset()
+ */
+int QDateTime::utcOffset() const
+{
+ if(isValid() && d->spec == QDateTimePrivate::OffsetFromUTC)
+ return d->utcOffset;
+ else
+ return 0;
+}
+
+#ifndef QT_NO_DATESTRING
+
+static int fromShortMonthName(const QString &monthName)
+{
+ // Assume that English monthnames are the default
+ for (int i = 0; i < 12; ++i) {
+ if (monthName == QLatin1String(qt_shortMonthNames[i]))
+ return i + 1;
+ }
+ // If English names can't be found, search the localized ones
+ for (int i = 1; i <= 12; ++i) {
+ if (monthName == QDate::shortMonthName(i))
+ return i;
+ }
+ return -1;
+}
+
+/*!
+ \fn QDateTime QDateTime::fromString(const QString &string, Qt::DateFormat format)
+
+ 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.
+*/
+QDateTime QDateTime::fromString(const QString& s, Qt::DateFormat f)
+{
+ if (s.isEmpty()) {
+ return QDateTime();
+ }
+
+ switch (f) {
+ case Qt::ISODate: {
+ QString tmp = s;
+ Qt::TimeSpec ts = Qt::LocalTime;
+ const QDate date = QDate::fromString(tmp.left(10), Qt::ISODate);
+ if (tmp.size() == 10)
+ return QDateTime(date);
+
+ tmp = tmp.mid(11);
+
+ // Recognize UTC specifications
+ if (tmp.endsWith(QLatin1Char('Z'))) {
+ ts = Qt::UTC;
+ tmp.chop(1);
+ }
+
+ // Recognize timezone specifications
+ QRegExp rx(QLatin1String("[+-]"));
+ if (tmp.contains(rx)) {
+ int idx = tmp.indexOf(rx);
+ QString tmp2 = tmp.mid(idx);
+ tmp = tmp.left(idx);
+ bool ok = true;
+ int ntzhour = 1;
+ int ntzminute = 3;
+ if ( tmp2.indexOf(QLatin1Char(':')) == 3 )
+ ntzminute = 4;
+ const int tzhour(tmp2.mid(ntzhour, 2).toInt(&ok));
+ const int tzminute(tmp2.mid(ntzminute, 2).toInt(&ok));
+ QTime tzt(tzhour, tzminute);
+ int utcOffset = (tzt.hour() * 60 + tzt.minute()) * 60;
+ if ( utcOffset != 0 ) {
+ ts = Qt::OffsetFromUTC;
+ QDateTime dt(date, QTime::fromString(tmp, Qt::ISODate), ts);
+ dt.setUtcOffset( utcOffset * (tmp2.startsWith(QLatin1Char('-')) ? -1 : 1) );
+ return dt;
+ }
+ }
+ return QDateTime(date, QTime::fromString(tmp, Qt::ISODate), ts);
+ }
+ case Qt::SystemLocaleDate:
+ case Qt::SystemLocaleShortDate:
+ case Qt::SystemLocaleLongDate:
+ return fromString(s, QLocale::system().dateTimeFormat(f == Qt::SystemLocaleLongDate ? QLocale::LongFormat
+ : QLocale::ShortFormat));
+ case Qt::LocaleDate:
+ case Qt::DefaultLocaleShortDate:
+ case Qt::DefaultLocaleLongDate:
+ return fromString(s, QLocale().dateTimeFormat(f == Qt::DefaultLocaleLongDate ? QLocale::LongFormat
+ : QLocale::ShortFormat));
+#if !defined(QT_NO_TEXTDATE)
+ case Qt::TextDate: {
+ QStringList parts = s.split(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 = -1, day = -1;
+ bool ok;
+
+ month = fromShortMonthName(parts.at(1));
+ if (month != -1) {
+ day = parts.at(2).toInt(&ok);
+ if (!ok)
+ day = -1;
+ }
+
+ if (month == -1 || day == -1) {
+ // first variant failed, lets try the other
+ month = fromShortMonthName(parts.at(2));
+ if (month != -1) {
+ QString dayStr = parts.at(1);
+ if (dayStr.endsWith(QLatin1Char('.'))) {
+ dayStr.chop(1);
+ day = dayStr.toInt(&ok);
+ if (!ok)
+ day = -1;
+ } else {
+ day = -1;
+ }
+ }
+ }
+
+ if (month == -1 || day == -1) {
+ // both variants failed, give up
+ return QDateTime();
+ }
+
+ int year;
+ QStringList timeParts = parts.at(3).split(QLatin1Char(':'));
+ if ((timeParts.count() == 3) || (timeParts.count() == 2)) {
+ year = parts.at(4).toInt(&ok);
+ if (!ok)
+ return QDateTime();
+ } else {
+ timeParts = parts.at(4).split(QLatin1Char(':'));
+ if ((timeParts.count() != 3) && (timeParts.count() != 2))
+ return QDateTime();
+ year = parts.at(3).toInt(&ok);
+ if (!ok)
+ 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 = (timeParts.count() > 2) ? timeParts.at(2).toInt(&ok) : 0;
+ if (!ok) {
+ return QDateTime();
+ }
+
+ QDate date(year, month, day);
+ QTime time(hour, minute, second);
+
+ if (parts.count() == 5)
+ return QDateTime(date, time, Qt::LocalTime);
+
+ QString tz = parts.at(5);
+ if (!tz.startsWith(QLatin1String("GMT"), Qt::CaseInsensitive))
+ return QDateTime();
+ QDateTime dt(date, time, Qt::UTC);
+ if (tz.length() > 3) {
+ int tzoffset = 0;
+ QChar sign = tz.at(3);
+ if ((sign != QLatin1Char('+'))
+ && (sign != QLatin1Char('-'))) {
+ return QDateTime();
+ }
+ int tzhour = tz.mid(4, 2).toInt(&ok);
+ if (!ok)
+ return QDateTime();
+ int tzminute = tz.mid(6).toInt(&ok);
+ if (!ok)
+ return QDateTime();
+ tzoffset = (tzhour*60 + tzminute) * 60;
+ if (sign == QLatin1Char('-'))
+ tzoffset = -tzoffset;
+ dt.setUtcOffset(tzoffset);
+ }
+ return dt.toLocalTime();
+ }
+#endif //QT_NO_TEXTDATE
+ }
+
+ return QDateTime();
+}
+
+/*!
+ \fn QDateTime::fromString(const QString &string, const QString &format)
+
+ 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 \i Expression \i Output
+ \row \i d \i the day as number without a leading zero (1 to 31)
+ \row \i dd \i the day as number with a leading zero (01 to 31)
+ \row \i ddd
+ \i the abbreviated localized day name (e.g. 'Mon' to 'Sun').
+ Uses QDate::shortDayName().
+ \row \i dddd
+ \i the long localized day name (e.g. 'Monday' to 'Sunday').
+ Uses QDate::longDayName().
+ \row \i M \i the month as number without a leading zero (1-12)
+ \row \i MM \i the month as number with a leading zero (01-12)
+ \row \i MMM
+ \i the abbreviated localized month name (e.g. 'Jan' to 'Dec').
+ Uses QDate::shortMonthName().
+ \row \i MMMM
+ \i the long localized month name (e.g. 'January' to 'December').
+ Uses QDate::longMonthName().
+ \row \i yy \i the year as two digit number (00-99)
+ \row \i yyyy \i 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 \i Expression \i Output
+ \row \i h
+ \i the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
+ \row \i hh
+ \i the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
+ \row \i H
+ \i the hour without a leading zero (0 to 23, even with AM/PM display)
+ \row \i HH
+ \i the hour with a leading zero (00 to 23, even with AM/PM display)
+ \row \i m \i the minute without a leading zero (0 to 59)
+ \row \i mm \i the minute with a leading zero (00 to 59)
+ \row \i s \i the second without a leading zero (0 to 59)
+ \row \i ss \i the second with a leading zero (00 to 59)
+ \row \i z \i the milliseconds without leading zeroes (0 to 999)
+ \row \i zzz \i the milliseconds with leading zeroes (000 to 999)
+ \row \i AP or A
+ \i interpret as an AM/PM time. \e AP must be either "AM" or "PM".
+ \row \i ap or a
+ \i 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 singlequotes will also be
+ treated as text and not be used as an expression.
+
+ \snippet doc/src/snippets/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 doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 13
+
+ This could have meant 1 January 00:30.00 but the M will grab
+ two digits.
+
+ For any field that is not represented in the format the following
+ defaults are used:
+
+ \table
+ \header \i Field \i Default value
+ \row \i Year \i 1900
+ \row \i Month \i 1 (January)
+ \row \i Day \i 1
+ \row \i Hour \i 0
+ \row \i Minute \i 0
+ \row \i Second \i 0
+ \endtable
+
+ For example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 14
+
+ \sa QDate::fromString() QTime::fromString() QDate::toString()
+ QDateTime::toString() QTime::toString()
+*/
+
+QDateTime QDateTime::fromString(const QString &string, const QString &format)
+{
+#ifndef QT_BOOTSTRAPPED
+ QTime time;
+ QDate date;
+
+ QDateTimeParser dt(QVariant::DateTime, QDateTimeParser::FromString);
+ if (dt.parseFormat(format) && dt.fromString(string, &date, &time))
+ return QDateTime(date, time);
+#else
+ Q_UNUSED(string);
+ Q_UNUSED(format);
+#endif
+ return QDateTime(QDate(), QTime(-1, -1, -1));
+}
+
+#endif // QT_NO_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.
+
+ \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.
+
+ \sa toTimeSpec()
+*/
+
+/*! \internal
+ */
+void QDateTime::detach()
+{
+ d.detach();
+}
+
+/*****************************************************************************
+ 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)
+{
+ return out << (quint32)(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)
+{
+ quint32 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)
+{
+ return out << quint32(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;
+ time.mds = 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)
+{
+ out << dateTime.d->date << dateTime.d->time;
+ if (out.version() >= 7)
+ out << (qint8)dateTime.d->spec;
+ 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)
+{
+ dateTime.detach();
+
+ qint8 ts = (qint8)QDateTimePrivate::LocalUnknown;
+ in >> dateTime.d->date >> dateTime.d->time;
+ if (in.version() >= 7)
+ in >> ts;
+ dateTime.d->spec = (QDateTimePrivate::Spec)ts;
+ return in;
+}
+#endif // QT_NO_DATASTREAM
+
+
+/*!
+ \fn QString QDate::monthName(int month)
+
+ Use shortMonthName() instead.
+*/
+
+/*!
+ \fn QString QDate::dayName(int weekday)
+
+ Use shortDayName() instead.
+*/
+
+/*!
+ \fn bool QDate::leapYear(int year)
+
+ Use isLeapYear() instead.
+*/
+
+/*!
+ \fn QDate QDate::currentDate(Qt::TimeSpec spec)
+
+ If \a spec is Qt::LocalTime, use the currentDate() overload that
+ takes no parameters instead; otherwise, use
+ QDateTime::currentDateTime().
+
+ \oldcode
+ QDate localDate = QDate::currentDate(Qt::LocalTime);
+ QDate utcDate = QDate::currentDate(Qt::UTC);
+ \newcode
+ QDate localDate = QDate::currentDate();
+ QDate utcDate = QDateTime::currentDateTime().toUTC().date();
+ \endcode
+
+ \sa QDateTime::toUTC()
+*/
+
+/*!
+ \fn QTime QTime::currentTime(Qt::TimeSpec specification)
+
+ Returns the current time for the given \a specification.
+
+ To replace uses of this function where the \a specification is Qt::LocalTime,
+ use the currentDate() overload that takes no parameters instead; otherwise,
+ use QDateTime::currentDateTime() and convert the result to a UTC measurement.
+
+ \oldcode
+ QTime localTime = QTime::currentTime(Qt::LocalTime);
+ QTime utcTime = QTime::currentTime(Qt::UTC);
+ \newcode
+ QTime localTime = QTime::currentTime();
+ QTime utcTime = QTimeTime::currentDateTime().toUTC().time();
+ \endcode
+
+ \sa QDateTime::toUTC()
+*/
+
+/*!
+ \fn void QDateTime::setTime_t(uint secsSince1Jan1970UTC, Qt::TimeSpec spec)
+
+ Use the single-argument overload of setTime_t() instead.
+*/
+
+/*!
+ \fn QDateTime QDateTime::currentDateTime(Qt::TimeSpec spec)
+
+ Use the currentDateTime() overload that takes no parameters
+ instead.
+*/
+
+// checks if there is an unqoted 'AP' or 'ap' in the string
+static bool hasUnquotedAP(const QString &f)
+{
+ const QLatin1Char quote('\'');
+ bool inquote = false;
+ const int max = f.size();
+ for (int i=0; i<max; ++i) {
+ if (f.at(i) == quote) {
+ inquote = !inquote;
+ } else if (!inquote && f.at(i).toUpper() == QLatin1Char('A')) {
+ return true;
+ }
+ }
+ return false;
+}
+
+#ifndef QT_NO_DATESTRING
+/*****************************************************************************
+ Some static function used by QDate, QTime and QDateTime
+*****************************************************************************/
+
+// Replaces tokens by their value. See QDateTime::toString() for a list of valid tokens
+static QString getFmtString(const QString& f, const QTime* dt = 0, const QDate* dd = 0, bool am_pm = false)
+{
+ if (f.isEmpty())
+ return QString();
+
+ QString buf = f;
+ int removed = 0;
+
+ if (dt) {
+ if (f.startsWith(QLatin1String("hh")) || f.startsWith(QLatin1String("HH"))) {
+ const bool hour12 = f.at(0) == QLatin1Char('h') && am_pm;
+ if (hour12 && dt->hour() > 12)
+ buf = QString::number(dt->hour() - 12).rightJustified(2, QLatin1Char('0'), true);
+ else if (hour12 && dt->hour() == 0)
+ buf = QLatin1String("12");
+ else
+ buf = QString::number(dt->hour()).rightJustified(2, QLatin1Char('0'), true);
+ removed = 2;
+ } else if (f.at(0) == QLatin1Char('h') || f.at(0) == QLatin1Char('H')) {
+ const bool hour12 = f.at(0) == QLatin1Char('h') && am_pm;
+ if (hour12 && dt->hour() > 12)
+ buf = QString::number(dt->hour() - 12);
+ else if (hour12 && dt->hour() == 0)
+ buf = QLatin1String("12");
+ else
+ buf = QString::number(dt->hour());
+ removed = 1;
+ } else if (f.startsWith(QLatin1String("mm"))) {
+ buf = QString::number(dt->minute()).rightJustified(2, QLatin1Char('0'), true);
+ removed = 2;
+ } else if (f.at(0) == (QLatin1Char('m'))) {
+ buf = QString::number(dt->minute());
+ removed = 1;
+ } else if (f.startsWith(QLatin1String("ss"))) {
+ buf = QString::number(dt->second()).rightJustified(2, QLatin1Char('0'), true);
+ removed = 2;
+ } else if (f.at(0) == QLatin1Char('s')) {
+ buf = QString::number(dt->second());
+ } else if (f.startsWith(QLatin1String("zzz"))) {
+ buf = QString::number(dt->msec()).rightJustified(3, QLatin1Char('0'), true);
+ removed = 3;
+ } else if (f.at(0) == QLatin1Char('z')) {
+ buf = QString::number(dt->msec());
+ removed = 1;
+ } else if (f.at(0).toUpper() == QLatin1Char('A')) {
+ const bool upper = f.at(0) == QLatin1Char('A');
+ buf = dt->hour() < 12 ? QLatin1String("am") : QLatin1String("pm");
+ if (upper)
+ buf = buf.toUpper();
+ if (f.size() > 1 && f.at(1).toUpper() == QLatin1Char('P') &&
+ f.at(0).isUpper() == f.at(1).isUpper()) {
+ removed = 2;
+ } else {
+ removed = 1;
+ }
+ }
+ }
+
+ if (dd) {
+ if (f.startsWith(QLatin1String("dddd"))) {
+ buf = dd->longDayName(dd->dayOfWeek());
+ removed = 4;
+ } else if (f.startsWith(QLatin1String("ddd"))) {
+ buf = dd->shortDayName(dd->dayOfWeek());
+ removed = 3;
+ } else if (f.startsWith(QLatin1String("dd"))) {
+ buf = QString::number(dd->day()).rightJustified(2, QLatin1Char('0'), true);
+ removed = 2;
+ } else if (f.at(0) == QLatin1Char('d')) {
+ buf = QString::number(dd->day());
+ removed = 1;
+ } else if (f.startsWith(QLatin1String("MMMM"))) {
+ buf = dd->longMonthName(dd->month());
+ removed = 4;
+ } else if (f.startsWith(QLatin1String("MMM"))) {
+ buf = dd->shortMonthName(dd->month());
+ removed = 3;
+ } else if (f.startsWith(QLatin1String("MM"))) {
+ buf = QString::number(dd->month()).rightJustified(2, QLatin1Char('0'), true);
+ removed = 2;
+ } else if (f.at(0) == QLatin1Char('M')) {
+ buf = QString::number(dd->month());
+ removed = 1;
+ } else if (f.startsWith(QLatin1String("yyyy"))) {
+ const int year = dd->year();
+ buf = QString::number(qAbs(year)).rightJustified(4, QLatin1Char('0'));
+ if(year > 0)
+ removed = 4;
+ else
+ {
+ buf.prepend(QLatin1Char('-'));
+ removed = 5;
+ }
+
+ } else if (f.startsWith(QLatin1String("yy"))) {
+ buf = QString::number(dd->year()).right(2).rightJustified(2, QLatin1Char('0'));
+ removed = 2;
+ }
+ }
+ if (removed == 0 || removed >= f.size()) {
+ return buf;
+ }
+
+ return buf + getFmtString(f.mid(removed), dt, dd, am_pm);
+}
+
+// Parses the format string and uses getFmtString to get the values for the tokens. Ret
+static QString fmtDateTime(const QString& f, const QTime* dt, const QDate* dd)
+{
+ const QLatin1Char quote('\'');
+ if (f.isEmpty())
+ return QString();
+ if (dt && !dt->isValid())
+ return QString();
+ if (dd && !dd->isValid())
+ return QString();
+
+ const bool ap = hasUnquotedAP(f);
+
+ QString buf;
+ QString frm;
+ QChar status(QLatin1Char('0'));
+
+ for (int i = 0; i < (int)f.length(); ++i) {
+ if (f.at(i) == quote) {
+ if (status == quote) {
+ if (i > 0 && f.at(i - 1) == quote)
+ buf += QLatin1Char('\'');
+ status = QLatin1Char('0');
+ } else {
+ if (!frm.isEmpty()) {
+ buf += getFmtString(frm, dt, dd, ap);
+ frm.clear();
+ }
+ status = quote;
+ }
+ } else if (status == quote) {
+ buf += f.at(i);
+ } else if (f.at(i) == status) {
+ if ((ap) && ((f.at(i) == QLatin1Char('P')) || (f.at(i) == QLatin1Char('p'))))
+ status = QLatin1Char('0');
+ frm += f.at(i);
+ } else {
+ buf += getFmtString(frm, dt, dd, ap);
+ frm.clear();
+ if ((f.at(i) == QLatin1Char('h')) || (f.at(i) == QLatin1Char('m'))
+ || (f.at(i) == QLatin1Char('H'))
+ || (f.at(i) == QLatin1Char('s')) || (f.at(i) == QLatin1Char('z'))) {
+ status = f.at(i);
+ frm += f.at(i);
+ } else if ((f.at(i) == QLatin1Char('d')) || (f.at(i) == QLatin1Char('M')) || (f.at(i) == QLatin1Char('y'))) {
+ status = f.at(i);
+ frm += f.at(i);
+ } else if ((ap) && (f.at(i) == QLatin1Char('A'))) {
+ status = QLatin1Char('P');
+ frm += f.at(i);
+ } else if((ap) && (f.at(i) == QLatin1Char('a'))) {
+ status = QLatin1Char('p');
+ frm += f.at(i);
+ } else {
+ buf += f.at(i);
+ status = QLatin1Char('0');
+ }
+ }
+ }
+
+ buf += getFmtString(frm, dt, dd, ap);
+
+ return buf;
+}
+#endif // QT_NO_DATESTRING
+
+#ifdef Q_OS_WIN
+static const int LowerYear = 1980;
+#else
+static const int LowerYear = 1970;
+#endif
+static const int UpperYear = 2037;
+
+static QDate adjustDate(QDate date)
+{
+ QDate lowerLimit(LowerYear, 1, 2);
+ QDate upperLimit(UpperYear, 12, 30);
+
+ if (date > lowerLimit && date < upperLimit)
+ return date;
+
+ int month = date.month();
+ int day = date.day();
+
+ // neither 1970 nor 2037 are leap years, so make sure date isn't Feb 29
+ if (month == 2 && day == 29)
+ --day;
+
+ if (date < lowerLimit)
+ date.setDate(LowerYear, month, day);
+ else
+ date.setDate(UpperYear, month, day);
+
+ return date;
+}
+
+static QDateTimePrivate::Spec utcToLocal(QDate &date, QTime &time)
+{
+ QDate fakeDate = adjustDate(date);
+
+ // won't overflow because of fakeDate
+ time_t secsSince1Jan1970UTC = toMSecsSinceEpoch_helper(fakeDate.toJulianDay(), QTime().msecsTo(time)) / 1000;
+ tm *brokenDown = 0;
+
+#if defined(Q_OS_WINCE)
+ tm res;
+ FILETIME utcTime = time_tToFt(secsSince1Jan1970UTC);
+ FILETIME resultTime;
+ FileTimeToLocalFileTime(&utcTime , &resultTime);
+ SYSTEMTIME sysTime;
+ FileTimeToSystemTime(&resultTime , &sysTime);
+
+ res.tm_sec = sysTime.wSecond;
+ res.tm_min = sysTime.wMinute;
+ res.tm_hour = sysTime.wHour;
+ res.tm_mday = sysTime.wDay;
+ res.tm_mon = sysTime.wMonth - 1;
+ res.tm_year = sysTime.wYear - 1900;
+ brokenDown = &res;
+#elif defined(Q_OS_SYMBIAN)
+ // months and days are zero index based
+ _LIT(KUnixEpoch, "19700000:000000.000000");
+ TTimeIntervalSeconds utcOffset = User::UTCOffset();
+ TTimeIntervalSeconds tTimeIntervalSecsSince1Jan1970UTC(secsSince1Jan1970UTC);
+ TTime epochTTime;
+ TInt err = epochTTime.Set(KUnixEpoch);
+ tm res;
+ if(err == KErrNone) {
+ TTime utcTTime = epochTTime + tTimeIntervalSecsSince1Jan1970UTC;
+ utcTTime = utcTTime + utcOffset;
+ TDateTime utcDateTime = utcTTime.DateTime();
+ res.tm_sec = utcDateTime.Second();
+ res.tm_min = utcDateTime.Minute();
+ res.tm_hour = utcDateTime.Hour();
+ res.tm_mday = utcDateTime.Day() + 1; // non-zero based index for tm struct
+ res.tm_mon = utcDateTime.Month();
+ res.tm_year = utcDateTime.Year() - 1900;
+ res.tm_isdst = 0;
+ brokenDown = &res;
+ }
+#elif !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
+ // use the reentrant version of localtime() where available
+ tzset();
+ tm res;
+ brokenDown = localtime_r(&secsSince1Jan1970UTC, &res);
+#elif defined(_MSC_VER) && _MSC_VER >= 1400
+ tm res;
+ if (!_localtime64_s(&res, &secsSince1Jan1970UTC))
+ brokenDown = &res;
+#else
+ brokenDown = localtime(&secsSince1Jan1970UTC);
+#endif
+ if (!brokenDown) {
+ date = QDate(1970, 1, 1);
+ time = QTime();
+ return QDateTimePrivate::LocalUnknown;
+ } else {
+ int deltaDays = fakeDate.daysTo(date);
+ date = QDate(brokenDown->tm_year + 1900, brokenDown->tm_mon + 1, brokenDown->tm_mday);
+ time = QTime(brokenDown->tm_hour, brokenDown->tm_min, brokenDown->tm_sec, time.msec());
+ date = date.addDays(deltaDays);
+ if (brokenDown->tm_isdst > 0)
+ return QDateTimePrivate::LocalDST;
+ else if (brokenDown->tm_isdst < 0)
+ return QDateTimePrivate::LocalUnknown;
+ else
+ return QDateTimePrivate::LocalStandard;
+ }
+}
+
+static void localToUtc(QDate &date, QTime &time, int isdst)
+{
+ if (!date.isValid())
+ return;
+
+ QDate fakeDate = adjustDate(date);
+
+ tm localTM;
+ localTM.tm_sec = time.second();
+ localTM.tm_min = time.minute();
+ localTM.tm_hour = time.hour();
+ localTM.tm_mday = fakeDate.day();
+ localTM.tm_mon = fakeDate.month() - 1;
+ localTM.tm_year = fakeDate.year() - 1900;
+ localTM.tm_isdst = (int)isdst;
+#if defined(Q_OS_WINCE) || defined(Q_OS_SYMBIAN)
+ time_t secsSince1Jan1970UTC = (toMSecsSinceEpoch_helper(fakeDate.toJulianDay(), QTime().msecsTo(time)) / 1000);
+#else
+#if defined(Q_OS_WIN)
+ _tzset();
+#endif
+ time_t secsSince1Jan1970UTC = mktime(&localTM);
+#endif
+ tm *brokenDown = 0;
+#if defined(Q_OS_WINCE)
+ tm res;
+ FILETIME localTime = time_tToFt(secsSince1Jan1970UTC);
+ SYSTEMTIME sysTime;
+ FileTimeToSystemTime(&localTime, &sysTime);
+ FILETIME resultTime;
+ LocalFileTimeToFileTime(&localTime , &resultTime);
+ FileTimeToSystemTime(&resultTime , &sysTime);
+ res.tm_sec = sysTime.wSecond;
+ res.tm_min = sysTime.wMinute;
+ res.tm_hour = sysTime.wHour;
+ res.tm_mday = sysTime.wDay;
+ res.tm_mon = sysTime.wMonth - 1;
+ res.tm_year = sysTime.wYear - 1900;
+ res.tm_isdst = (int)isdst;
+ brokenDown = &res;
+#elif defined(Q_OS_SYMBIAN)
+ // months and days are zero index based
+ _LIT(KUnixEpoch, "19700000:000000.000000");
+ TTimeIntervalSeconds utcOffset = TTimeIntervalSeconds(0 - User::UTCOffset().Int());
+ TTimeIntervalSeconds tTimeIntervalSecsSince1Jan1970UTC(secsSince1Jan1970UTC);
+ TTime epochTTime;
+ TInt err = epochTTime.Set(KUnixEpoch);
+ tm res;
+ if(err == KErrNone) {
+ TTime utcTTime = epochTTime + tTimeIntervalSecsSince1Jan1970UTC;
+ utcTTime = utcTTime + utcOffset;
+ TDateTime utcDateTime = utcTTime.DateTime();
+ res.tm_sec = utcDateTime.Second();
+ res.tm_min = utcDateTime.Minute();
+ res.tm_hour = utcDateTime.Hour();
+ res.tm_mday = utcDateTime.Day() + 1; // non-zero based index for tm struct
+ res.tm_mon = utcDateTime.Month();
+ res.tm_year = utcDateTime.Year() - 1900;
+ res.tm_isdst = (int)isdst;
+ brokenDown = &res;
+ }
+#elif !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
+ // use the reentrant version of gmtime() where available
+ tm res;
+ brokenDown = gmtime_r(&secsSince1Jan1970UTC, &res);
+#elif defined(_MSC_VER) && _MSC_VER >= 1400
+ tm res;
+ if (!_gmtime64_s(&res, &secsSince1Jan1970UTC))
+ brokenDown = &res;
+#else
+ brokenDown = gmtime(&secsSince1Jan1970UTC);
+#endif // !QT_NO_THREAD && _POSIX_THREAD_SAFE_FUNCTIONS
+ if (!brokenDown) {
+ date = QDate(1970, 1, 1);
+ time = QTime();
+ } else {
+ int deltaDays = fakeDate.daysTo(date);
+ date = QDate(brokenDown->tm_year + 1900, brokenDown->tm_mon + 1, brokenDown->tm_mday);
+ time = QTime(brokenDown->tm_hour, brokenDown->tm_min, brokenDown->tm_sec, time.msec());
+ date = date.addDays(deltaDays);
+ }
+}
+
+QDateTimePrivate::Spec QDateTimePrivate::getLocal(QDate &outDate, QTime &outTime) const
+{
+ outDate = date;
+ outTime = time;
+ if (spec == QDateTimePrivate::UTC)
+ return utcToLocal(outDate, outTime);
+ return spec;
+}
+
+void QDateTimePrivate::getUTC(QDate &outDate, QTime &outTime) const
+{
+ outDate = date;
+ outTime = time;
+ const bool isOffset = spec == QDateTimePrivate::OffsetFromUTC;
+
+ if (spec != QDateTimePrivate::UTC && !isOffset)
+ localToUtc(outDate, outTime, (int)spec);
+
+ if (isOffset)
+ addMSecs(outDate, outTime, -(qint64(utcOffset) * 1000));
+}
+
+#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_NO_DATESTRING)
+QDebug operator<<(QDebug dbg, const QDate &date)
+{
+ dbg.nospace() << "QDate(" << date.toString() << ')';
+ return dbg.space();
+}
+
+QDebug operator<<(QDebug dbg, const QTime &time)
+{
+ dbg.nospace() << "QTime(" << time.toString() << ')';
+ return dbg.space();
+}
+
+QDebug operator<<(QDebug dbg, const QDateTime &date)
+{
+ dbg.nospace() << "QDateTime(" << date.toString() << ')';
+ return dbg.space();
+}
+#endif
+
+#ifndef QT_BOOTSTRAPPED
+
+/*!
+ \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()) {
+#ifndef QT_NO_DATESTRING
+ qWarning("QDateTimeParser::getDigit() Internal error (%s %d)",
+ qPrintable(t.toString()), index);
+#else
+ qWarning("QDateTimeParser::getDigit() Internal error (%d)", index);
+#endif
+ return -1;
+ }
+ const SectionNode &node = sectionNodes.at(index);
+ switch (node.type) {
+ 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 DayOfWeekSection: return t.date().day();
+ case AmPmSection: return t.time().hour() > 11 ? 1 : 0;
+
+ default: break;
+ }
+
+#ifndef QT_NO_DATESTRING
+ qWarning("QDateTimeParser::getDigit() Internal error 2 (%s %d)",
+ qPrintable(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()) {
+#ifndef QT_NO_DATESTRING
+ qWarning("QDateTimeParser::setDigit() Internal error (%s %d %d)",
+ qPrintable(v.toString()), index, newVal);
+#else
+ qWarning("QDateTimeParser::setDigit() Internal error (%d %d)", index, newVal);
+#endif
+ return false;
+ }
+ const SectionNode &node = sectionNodes.at(index);
+
+ int year, month, day, hour, minute, second, msec;
+ year = v.date().year();
+ month = v.date().month();
+ day = v.date().day();
+ hour = v.time().hour();
+ minute = v.time().minute();
+ second = v.time().second();
+ msec = v.time().msec();
+
+ 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 DayOfWeekSection:
+ 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 AmPmSection: hour = (newVal == 0 ? hour % 12 : (hour % 12) + 12); break;
+ default:
+ qWarning("QDateTimeParser::setDigit() Internal error (%s)",
+ qPrintable(sectionName(node.type)));
+ break;
+ }
+
+ if (!(node.type & (DaySection|DayOfWeekSection))) {
+ if (day < cachedDay)
+ day = cachedDay;
+ const int max = QDate(year, month, 1).daysInMonth();
+ if (day > max) {
+ day = max;
+ }
+ }
+ if (QDate::isValid(year, month, day) && QTime::isValid(hour, minute, second, msec)) {
+ v = QDateTime(QDate(year, month, day), QTime(hour, minute, second, msec), spec);
+ return true;
+ }
+ return false;
+}
+
+
+
+/*!
+ \
+
+ Returns the absolute maximum for a section
+*/
+
+int QDateTimeParser::absoluteMax(int s, const QDateTime &cur) const
+{
+ const SectionNode &sn = sectionNode(s);
+ switch (sn.type) {
+ 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 DayOfWeekSection: return cur.isValid() ? cur.date().daysInMonth() : 31;
+ case AmPmSection: return 1;
+ default: break;
+ }
+ qWarning("QDateTimeParser::absoluteMax() Internal error (%s)",
+ qPrintable(sectionName(sn.type)));
+ return -1;
+}
+
+/*!
+ \internal
+
+ Returns the absolute minimum for a section
+*/
+
+int QDateTimeParser::absoluteMin(int s) const
+{
+ const SectionNode &sn = sectionNode(s);
+ switch (sn.type) {
+ case Hour24Section:
+ case Hour12Section:
+ case MinuteSection:
+ case SecondSection:
+ case MSecSection:
+ case YearSection2Digits:
+ case YearSection: return 0;
+ case MonthSection:
+ case DaySection:
+ case DayOfWeekSection: return 1;
+ case AmPmSection: return 0;
+ default: break;
+ }
+ qWarning("QDateTimeParser::absoluteMin() Internal error (%s, %0x)",
+ qPrintable(sectionName(sn.type)), 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 (%s)", qPrintable(sectionName(sn.type)));
+ 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 QString &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; i<max; ++i) {
+ if (str.at(i) == quote) {
+ if (status != quote) {
+ status = quote;
+ } else if (!ret.isEmpty() && str.at(i - 1) == slash) {
+ ret[ret.size() - 1] = quote;
+ } else {
+ status = zero;
+ }
+ } else {
+ ret += str.at(i);
+ }
+ }
+ return ret;
+}
+/*!
+ \internal
+
+ Parses the format \a newFormat. If successful, returns true and
+ sets up the format. Else keeps the old format and returns false.
+
+*/
+
+static inline int countRepeat(const QString &str, int index, int maxCount)
+{
+ int count = 1;
+ const QChar ch(str.at(index));
+ const int max = qMin(index + maxCount, str.size());
+ while (index + count < max && str.at(index + count) == ch) {
+ ++count;
+ }
+ return count;
+}
+
+static inline void appendSeparator(QStringList *list, const QString &string, int from, int size, int lastQuote)
+{
+ QString str(string.mid(from, size));
+ if (lastQuote >= from)
+ str = unquote(str);
+ list->append(str);
+}
+
+
+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<SectionNode> 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<max; ++i) {
+ if (newFormat.at(i) == quote) {
+ lastQuote = i;
+ ++add;
+ if (status != quote) {
+ status = quote;
+ } else if (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) };
+ 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) };
+ 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) };
+ 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 };
+ 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) };
+ 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 };
+ 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) };
+ newSectionNodes.append(sn);
+ newSeparators.append(unquote(newFormat.mid(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 SectionNode sn = { repeat >= 3 ? DayOfWeekSection : DaySection, i - add, repeat };
+ newSectionNodes.append(sn);
+ appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
+ i += sn.count - 1;
+ index = i + 1;
+ newDisplay |= sn.type;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ if (newSectionNodes.isEmpty() && context == DateTimeEdit) {
+ return false;
+ }
+
+ if ((newDisplay & (AmPmSection|Hour12Section)) == Hour12Section) {
+ const int max = newSectionNodes.size();
+ for (int i=0; i<max; ++i) {
+ SectionNode &node = newSectionNodes[i];
+ if (node.type == Hour12Section)
+ node.type = Hour24Section;
+ }
+ }
+
+ if (index < newFormat.size()) {
+ 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(); ++i) {
+// QDTPDEBUG << sectionName(sectionNodes.at(i).type) << sectionNodes.at(i).count;
+// }
+
+ QDTPDEBUG << newFormat << displayFormat;
+ QDTPDEBUGN("separators:\n'%s'", separators.join(QLatin1String("\n")).toLatin1().constData());
+
+ return true;
+}
+
+/*!
+ \internal
+
+ Returns the size of section \a s.
+*/
+
+int QDateTimeParser::sectionSize(int sectionIndex) const
+{
+ if (sectionIndex < 0)
+ return 0;
+
+ if (sectionIndex >= sectionNodes.size()) {
+ qWarning("QDateTimeParser::sectionSize Internal error (%d)", sectionIndex);
+ return -1;
+ }
+ if (sectionIndex == sectionNodes.size() - 1) {
+ return displayText().size() - 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
+{
+#ifndef QT_NO_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 DayOfWeekSection:
+#ifdef QT_NO_TEXTDATE
+ return 2;
+#else
+ mcount = 7;
+ // fall through
+#endif
+ case MonthSection:
+ if (count <= 2)
+ return 2;
+
+#ifdef QT_NO_TEXTDATE
+ return 2;
+#else
+ {
+ int ret = 0;
+ const QLocale l = locale();
+ for (int i=1; i<=mcount; ++i) {
+ const QString str = (s == MonthSection
+ ? l.monthName(i, count == 4 ? QLocale::LongFormat : QLocale::ShortFormat)
+ : l.dayName(i, count == 4 ? QLocale::LongFormat : QLocale::ShortFormat));
+ ret = qMax(str.size(), ret);
+ }
+ return ret;
+ }
+#endif
+ case MSecSection: return 3;
+ case YearSection: return 4;
+ case YearSection2Digits: return 2;
+
+ case CalendarPopupSection:
+ case Internal:
+ case TimeSectionMask:
+ case DateSectionMask:
+ qWarning("QDateTimeParser::sectionMaxSize: Invalid section %s",
+ sectionName(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);
+ switch (sn.type) {
+ case NoSectionIndex:
+ case FirstSectionIndex:
+ case LastSectionIndex:
+ return QString();
+ default: break;
+ }
+
+ return displayText().mid(sn.pos, sectionSize(sectionIndex));
+}
+
+
+#ifndef QT_NO_TEXTDATE
+/*!
+ \internal:skipToNextSection
+
+ Parses the part of \a text that corresponds to \a s and returns
+ the value of that field. Sets *stateptr to the right state if
+ stateptr != 0.
+*/
+
+int QDateTimeParser::parseSection(const QDateTime &currentValue, int sectionIndex,
+ QString &text, int &cursorPosition, int index,
+ State &state, int *usedptr) const
+{
+ state = Invalid;
+ int num = 0;
+ const SectionNode &sn = sectionNode(sectionIndex);
+ if ((sn.type & Internal) == Internal) {
+ qWarning("QDateTimeParser::parseSection Internal error (%s %d)",
+ qPrintable(sectionName(sn.type)), sectionIndex);
+ return -1;
+ }
+
+ const int sectionmaxsize = sectionMaxSize(sectionIndex);
+ QString sectiontext = text.mid(index, sectionmaxsize);
+ int sectiontextSize = sectiontext.size();
+
+ QDTPDEBUG << "sectionValue for" << sectionName(sn.type)
+ << "with text" << text << "and st" << sectiontext
+ << text.mid(index, sectionmaxsize)
+ << index;
+
+ int used = 0;
+ switch (sn.type) {
+ case AmPmSection: {
+ const int ampm = findAmPm(sectiontext, sectionIndex, &used);
+ switch (ampm) {
+ case AM: // sectiontext == AM
+ case PM: // sectiontext == PM
+ num = ampm;
+ state = Acceptable;
+ break;
+ case PossibleAM: // sectiontext => AM
+ case PossiblePM: // sectiontext => PM
+ num = ampm - 2;
+ state = Intermediate;
+ break;
+ case PossibleBoth: // sectiontext => AM|PM
+ num = 0;
+ state = Intermediate;
+ break;
+ case Neither:
+ state = Invalid;
+ QDTPDEBUG << "invalid because findAmPm(" << sectiontext << ") returned -1";
+ break;
+ default:
+ QDTPDEBUGN("This should never happen (findAmPm returned %d)", ampm);
+ break;
+ }
+ if (state != Invalid) {
+ QString str = text;
+ text.replace(index, used, sectiontext.left(used));
+ }
+ break; }
+ case MonthSection:
+ case DayOfWeekSection:
+ if (sn.count >= 3) {
+ if (sn.type == MonthSection) {
+ int min = 1;
+ const QDate minDate = getMinimum().date();
+ if (currentValue.date().year() == minDate.year()) {
+ min = minDate.month();
+ }
+ num = findMonth(sectiontext.toLower(), min, sectionIndex, &sectiontext, &used);
+ } else {
+ num = findDay(sectiontext.toLower(), 1, sectionIndex, &sectiontext, &used);
+ }
+
+ if (num != -1) {
+ state = (used == sectiontext.size() ? Acceptable : Intermediate);
+ QString str = text;
+ text.replace(index, used, sectiontext.left(used));
+ } else {
+ state = Intermediate;
+ }
+ break; }
+ // fall through
+ case DaySection:
+ case YearSection:
+ case YearSection2Digits:
+ case Hour12Section:
+ case Hour24Section:
+ case MinuteSection:
+ case SecondSection:
+ case MSecSection: {
+ if (sectiontextSize == 0) {
+ num = 0;
+ used = 0;
+ state = Intermediate;
+ } else {
+ const int absMax = absoluteMax(sectionIndex);
+ QLocale loc;
+ bool ok = true;
+ int last = -1;
+ used = -1;
+
+ QString digitsStr(sectiontext);
+ for (int i = 0; i < sectiontextSize; ++i) {
+ if (digitsStr.at(i).isSpace()) {
+ sectiontextSize = i;
+ break;
+ }
+ }
+
+ const int max = qMin(sectionmaxsize, sectiontextSize);
+ for (int digits = max; digits >= 1; --digits) {
+ digitsStr.truncate(digits);
+ int tmp = (int)loc.toUInt(digitsStr, &ok, 10);
+ if (ok && sn.type == Hour12Section) {
+ if (tmp > 12) {
+ tmp = -1;
+ ok = false;
+ } else if (tmp == 12) {
+ tmp = 0;
+ }
+ }
+ if (ok && tmp <= absMax) {
+ QDTPDEBUG << sectiontext.left(digits) << tmp << digits;
+ last = tmp;
+ used = digits;
+ break;
+ }
+ }
+
+ if (last == -1) {
+ QChar first(sectiontext.at(0));
+ if (separators.at(sectionIndex + 1).startsWith(first)) {
+ used = 0;
+ state = Intermediate;
+ } else {
+ state = Invalid;
+ QDTPDEBUG << "invalid because" << sectiontext << "can't become a uint" << last << ok;
+ }
+ } else {
+ num += last;
+ const FieldInfo fi = fieldInfo(sectionIndex);
+ const bool done = (used == sectionmaxsize);
+ if (!done && fi & Fraction) { // typing 2 in a zzz field should be .200, not .002
+ for (int i=used; i<sectionmaxsize; ++i) {
+ num *= 10;
+ }
+ }
+ const int absMin = absoluteMin(sectionIndex);
+ if (num < absMin) {
+ state = done ? Invalid : Intermediate;
+ if (done)
+ QDTPDEBUG << "invalid because" << num << "is less than absoluteMin" << absMin;
+ } else if (num > absMax) {
+ state = Intermediate;
+ } else if (!done && (fi & (FixedWidth|Numeric)) == (FixedWidth|Numeric)) {
+ if (skipToNextSection(sectionIndex, currentValue, digitsStr)) {
+ state = Acceptable;
+ const int missingZeroes = sectionmaxsize - digitsStr.size();
+ text.insert(index, QString().fill(QLatin1Char('0'), missingZeroes));
+ used = sectionmaxsize;
+ cursorPosition += missingZeroes;
+ } else {
+ state = Intermediate;;
+ }
+ } else {
+ state = Acceptable;
+ }
+ }
+ }
+ break; }
+ default:
+ qWarning("QDateTimeParser::parseSection Internal error (%s %d)",
+ qPrintable(sectionName(sn.type)), sectionIndex);
+ return -1;
+ }
+
+ if (usedptr)
+ *usedptr = used;
+
+ return (state != Invalid ? num : -1);
+}
+#endif // QT_NO_TEXTDATE
+
+#ifndef QT_NO_DATESTRING
+/*!
+ \internal
+*/
+
+QDateTimeParser::StateNode QDateTimeParser::parse(QString &input, int &cursorPosition,
+ const QDateTime &currentValue, bool fixup) const
+{
+ const QDateTime minimum = getMinimum();
+ const QDateTime maximum = getMaximum();
+
+ State state = Acceptable;
+
+ QDateTime newCurrentValue;
+ int pos = 0;
+ bool conflicts = false;
+ const int sectionNodesCount = sectionNodes.size();
+
+ QDTPDEBUG << "parse" << input;
+ {
+ int year, month, day, hour12, hour, minute, second, msec, ampm, dayofweek, year2digits;
+ getDateFromJulianDay(currentValue.date().toJulianDay(), &year, &month, &day);
+ year2digits = year % 100;
+ hour = currentValue.time().hour();
+ hour12 = -1;
+ minute = currentValue.time().minute();
+ second = currentValue.time().second();
+ msec = currentValue.time().msec();
+ dayofweek = currentValue.date().dayOfWeek();
+
+ ampm = -1;
+ Sections isSet = NoSection;
+ int num;
+ State tmpstate;
+
+ for (int index=0; state != Invalid && index<sectionNodesCount; ++index) {
+ if (QStringRef(&input, pos, separators.at(index).size()) != separators.at(index)) {
+ QDTPDEBUG << "invalid because" << input.mid(pos, separators.at(index).size())
+ << "!=" << separators.at(index)
+ << index << pos << currentSectionIndex;
+ state = Invalid;
+ goto end;
+ }
+ pos += separators.at(index).size();
+ sectionNodes[index].pos = pos;
+ int *current = 0;
+ const SectionNode sn = sectionNodes.at(index);
+ int used;
+
+ num = parseSection(currentValue, index, input, cursorPosition, pos, tmpstate, &used);
+ QDTPDEBUG << "sectionValue" << sectionName(sectionType(index)) << input
+ << "pos" << pos << "used" << used << stateName(tmpstate);
+ if (fixup && tmpstate == Intermediate && used < sn.count) {
+ const FieldInfo fi = fieldInfo(index);
+ if ((fi & (Numeric|FixedWidth)) == (Numeric|FixedWidth)) {
+ const QString newText = QString::fromLatin1("%1").arg(num, sn.count, 10, QLatin1Char('0'));
+ input.replace(pos, used, newText);
+ used = sn.count;
+ }
+ }
+ pos += qMax(0, used);
+
+ state = qMin<State>(state, tmpstate);
+ if (state == Intermediate && context == FromString) {
+ state = Invalid;
+ break;
+ }
+
+ QDTPDEBUG << index << sectionName(sectionType(index)) << "is set to"
+ << pos << "state is" << stateName(state);
+
+
+ if (state != Invalid) {
+ switch (sn.type) {
+ 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 DayOfWeekSection: current = &dayofweek; break;
+ case DaySection: current = &day; num = qMax<int>(1, num); break;
+ case AmPmSection: current = &ampm; break;
+ default:
+ qWarning("QDateTimeParser::parse Internal error (%s)",
+ qPrintable(sectionName(sn.type)));
+ break;
+ }
+ if (!current) {
+ qWarning("QDateTimeParser::parse Internal error 2");
+ return StateNode();
+ }
+ if (isSet & sn.type && *current != num) {
+ QDTPDEBUG << "CONFLICT " << sectionName(sn.type) << *current << num;
+ conflicts = true;
+ if (index != currentSectionIndex || num == -1) {
+ continue;
+ }
+ }
+ if (num != -1)
+ *current = num;
+ isSet |= sn.type;
+ }
+ }
+
+ if (state != Invalid && QStringRef(&input, pos, input.size() - pos) != separators.last()) {
+ QDTPDEBUG << "invalid because" << input.mid(pos)
+ << "!=" << separators.last() << pos;
+ state = Invalid;
+ }
+
+ if (state != Invalid) {
+ if (parserType != QVariant::Time) {
+ if (year % 100 != year2digits) {
+ switch (isSet & (YearSection2Digits|YearSection)) {
+ case YearSection2Digits:
+ year = (year / 100) * 100;
+ year += year2digits;
+ break;
+ case ((uint)YearSection2Digits|(uint)YearSection): {
+ conflicts = true;
+ const SectionNode &sn = sectionNode(currentSectionIndex);
+ if (sn.type == YearSection2Digits) {
+ year = (year / 100) * 100;
+ year += year2digits;
+ }
+ break; }
+ default:
+ break;
+ }
+ }
+
+ const QDate date(year, month, day);
+ const int diff = dayofweek - date.dayOfWeek();
+ if (diff != 0 && state == Acceptable && isSet & DayOfWeekSection) {
+ conflicts = isSet & DaySection;
+ const SectionNode &sn = sectionNode(currentSectionIndex);
+ if (sn.type == DayOfWeekSection || 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) & (DaySection|DayOfWeekSection)) {
+ 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) {
+ state = Invalid;
+ goto end;
+ }
+ if (state == Acceptable && fixday) {
+ day = qMin<int>(day, QDate(year, month, 1).daysInMonth());
+
+ const QLocale loc = locale();
+ for (int i=0; i<sectionNodesCount; ++i) {
+ if (sectionType(i) & (DaySection|DayOfWeekSection)) {
+ input.replace(sectionPos(i), sectionSize(i), loc.toString(day));
+ }
+ }
+ } else {
+ state = qMin(Intermediate, state);
+ }
+ }
+ }
+
+ 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;
+ }
+ }
+
+ }
+
+ newCurrentValue = QDateTime(QDate(year, month, day), QTime(hour, minute, second, msec), spec);
+ QDTPDEBUG << year << month << day << hour << minute << second << msec;
+ }
+ QDTPDEBUGN("'%s' => '%s'(%s)", input.toLatin1().constData(),
+ newCurrentValue.toString(QLatin1String("yyyy/MM/dd hh:mm:ss.zzz")).toLatin1().constData(),
+ stateName(state).toLatin1().constData());
+ }
+end:
+ if (newCurrentValue.isValid()) {
+ if (context != FromString && state != Invalid && newCurrentValue < minimum) {
+ const QLatin1Char space(' ');
+ if (newCurrentValue >= minimum)
+ qWarning("QDateTimeParser::parse Internal error 3 (%s %s)",
+ qPrintable(newCurrentValue.toString()), qPrintable(minimum.toString()));
+
+ bool done = false;
+ state = Invalid;
+ for (int i=0; i<sectionNodesCount && !done; ++i) {
+ const SectionNode &sn = sectionNodes.at(i);
+ QString t = sectionText(input, i, sn.pos).toLower();
+ if ((t.size() < sectionMaxSize(i) && (((int)fieldInfo(i) & (FixedWidth|Numeric)) != Numeric))
+ || t.contains(space)) {
+ switch (sn.type) {
+ case AmPmSection:
+ switch (findAmPm(t, i)) {
+ case AM:
+ case PM:
+ state = Acceptable;
+ done = true;
+ break;
+ case Neither:
+ state = Invalid;
+ done = true;
+ break;
+ case PossibleAM:
+ case PossiblePM:
+ case PossibleBoth: {
+ const QDateTime copy(newCurrentValue.addSecs(12 * 60 * 60));
+ if (copy >= minimum && copy <= maximum) {
+ state = Intermediate;
+ done = true;
+ }
+ break; }
+ }
+ case MonthSection:
+ if (sn.count >= 3) {
+ int tmp = newCurrentValue.date().month();
+ // I know the first possible month makes the date too early
+ while ((tmp = findMonth(t, tmp + 1, i)) != -1) {
+ const QDateTime copy(newCurrentValue.addMonths(tmp - newCurrentValue.date().month()));
+ if (copy >= minimum && copy <= maximum)
+ break; // break out of while
+ }
+ if (tmp == -1) {
+ break;
+ }
+ state = Intermediate;
+ done = true;
+ break;
+ }
+ // fallthrough
+ default: {
+ int toMin;
+ int toMax;
+
+ if (sn.type & TimeSectionMask) {
+ if (newCurrentValue.daysTo(minimum) != 0) {
+ break;
+ }
+ toMin = newCurrentValue.time().msecsTo(minimum.time());
+ if (newCurrentValue.daysTo(maximum) > 0) {
+ toMax = -1; // can't get to max
+ } else {
+ toMax = newCurrentValue.time().msecsTo(maximum.time());
+ }
+ } else {
+ toMin = newCurrentValue.daysTo(minimum);
+ toMax = newCurrentValue.daysTo(maximum);
+ }
+ const int maxChange = QDateTimeParser::maxChange(i);
+ if (toMin > maxChange) {
+ QDTPDEBUG << "invalid because toMin > maxChange" << toMin
+ << maxChange << t << newCurrentValue << minimum;
+ 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 (%s)",
+ qPrintable(sectionName(sn.type)));
+ state = Invalid;
+ done = true;
+ break;
+ }
+
+ int max = toMax != -1 ? getDigit(maximum, i) : absoluteMax(i, newCurrentValue);
+ int pos = cursorPosition - sn.pos;
+ if (pos < 0 || pos >= t.size())
+ pos = -1;
+ if (!potentialValue(t.simplified(), min, max, i, newCurrentValue, pos)) {
+ QDTPDEBUG << "invalid because potentialValue(" << t.simplified() << min << max
+ << sectionName(sn.type) << "returned" << toMax << toMin << pos;
+ state = Invalid;
+ done = true;
+ break;
+ }
+ state = Intermediate;
+ done = true;
+ break; }
+ }
+ }
+ }
+ } else {
+ if (context == FromString) {
+ // optimization
+ Q_ASSERT(getMaximum().date().toJulianDay() == 4642999);
+ if (newCurrentValue.date().toJulianDay() > 4642999)
+ state = Invalid;
+ } else {
+ if (newCurrentValue > getMaximum())
+ state = Invalid;
+ }
+
+ QDTPDEBUG << "not checking intermediate because newCurrentValue is" << newCurrentValue << getMinimum() << getMaximum();
+ }
+ }
+ StateNode node;
+ node.input = input;
+ node.state = state;
+ node.conflicts = conflicts;
+ node.value = newCurrentValue.toTimeSpec(spec);
+ text = input;
+ return node;
+}
+#endif // QT_NO_DATESTRING
+
+#ifndef QT_NO_TEXTDATE
+/*!
+ \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
+{
+ int bestMatch = -1;
+ int bestCount = 0;
+ if (!str1.isEmpty()) {
+ 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();
+
+ for (int month=startMonth; month<=12; ++month) {
+ QString str2 = l.monthName(month, type).toLower();
+
+ if (str1.startsWith(str2)) {
+ if (used) {
+ QDTPDEBUG << "used is set to" << str2.size();
+ *used = str2.size();
+ }
+ if (usedMonth)
+ *usedMonth = l.monthName(month, type);
+
+ return month;
+ }
+ if (context == FromString)
+ continue;
+
+ const int limit = qMin(str1.size(), str2.size());
+
+ QDTPDEBUG << "limit is" << limit << str1 << str2;
+ bool equal = true;
+ for (int i=0; i<limit; ++i) {
+ if (str1.at(i) != str2.at(i)) {
+ equal = false;
+ if (i > bestCount) {
+ bestCount = i;
+ bestMatch = month;
+ }
+ break;
+ }
+ }
+ if (equal) {
+ if (used)
+ *used = limit;
+ if (usedMonth)
+ *usedMonth = l.monthName(month, type);
+ return month;
+ }
+ }
+ if (usedMonth && bestMatch != -1)
+ *usedMonth = l.monthName(bestMatch, type);
+ }
+ if (used) {
+ QDTPDEBUG << "used is set to" << bestCount;
+ *used = bestCount;
+ }
+ return bestMatch;
+}
+
+int QDateTimeParser::findDay(const QString &str1, int startDay, int sectionIndex, QString *usedDay, int *used) const
+{
+ int bestMatch = -1;
+ int bestCount = 0;
+ if (!str1.isEmpty()) {
+ const SectionNode &sn = sectionNode(sectionIndex);
+ if (!(sn.type & (DaySection|DayOfWeekSection))) {
+ qWarning("QDateTimeParser::findDay Internal error");
+ return -1;
+ }
+ const QLocale l = locale();
+ for (int day=startDay; day<=7; ++day) {
+ const QString str2 = l.dayName(day, sn.count == 4 ? QLocale::LongFormat : QLocale::ShortFormat);
+
+ if (str1.startsWith(str2.toLower())) {
+ if (used)
+ *used = str2.size();
+ if (usedDay) {
+ *usedDay = str2;
+ }
+ return day;
+ }
+ if (context == FromString)
+ continue;
+
+ const int limit = qMin(str1.size(), str2.size());
+ bool found = true;
+ for (int i=0; i<limit; ++i) {
+ if (str1.at(i) != str2.at(i) && !str1.at(i).isSpace()) {
+ if (i > bestCount) {
+ bestCount = i;
+ bestMatch = day;
+ }
+ found = false;
+ break;
+ }
+
+ }
+ if (found) {
+ if (used)
+ *used = limit;
+ if (usedDay)
+ *usedDay = str2;
+
+ return day;
+ }
+ }
+ if (usedDay && bestMatch != -1) {
+ *usedDay = l.dayName(bestMatch, sn.count == 4 ? QLocale::LongFormat : QLocale::ShortFormat);
+ }
+ }
+ if (used)
+ *used = bestCount;
+
+ return bestMatch;
+}
+#endif // QT_NO_TEXTDATE
+
+/*!
+ \internal
+
+ returns
+ 0 if str == QDateTimeEdit::tr("AM")
+ 1 if str == QDateTimeEdit::tr("PM")
+ 2 if str can become QDateTimeEdit::tr("AM")
+ 3 if str can become QDateTimeEdit::tr("PM")
+ 4 if str can become QDateTimeEdit::tr("PM") and can become QDateTimeEdit::tr("AM")
+ -1 can't become anything sensible
+
+*/
+
+int QDateTimeParser::findAmPm(QString &str, int index, int *used) const
+{
+ const SectionNode &s = sectionNode(index);
+ if (s.type != AmPmSection) {
+ qWarning("QDateTimeParser::findAmPm Internal error");
+ return -1;
+ }
+ if (used)
+ *used = str.size();
+ if (str.trimmed().isEmpty()) {
+ return PossibleBoth;
+ }
+ const QLatin1Char space(' ');
+ int size = sectionMaxSize(index);
+
+ 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<size; ++i) {
+ if (str.at(i) != space) {
+ for (int j=0; j<2; ++j) {
+ if (!broken[j]) {
+ int index = ampm[j].indexOf(str.at(i));
+ QDTPDEBUG << "looking for" << str.at(i)
+ << "in" << ampm[j] << "and got" << index;
+ if (index == -1) {
+ if (str.at(i).category() == QChar::Letter_Uppercase) {
+ index = ampm[j].indexOf(str.at(i).toLower());
+ QDTPDEBUG << "trying with" << str.at(i).toLower()
+ << "in" << ampm[j] << "and got" << index;
+ } else if (str.at(i).category() == QChar::Letter_Lowercase) {
+ index = ampm[j].indexOf(str.at(i).toUpper());
+ QDTPDEBUG << "trying with" << str.at(i).toUpper()
+ << "in" << ampm[j] << "and got" << index;
+ }
+ if (index == -1) {
+ broken[j] = true;
+ if (broken[amindex] && broken[pmindex]) {
+ QDTPDEBUG << str << "didn't make it";
+ return Neither;
+ }
+ continue;
+ } else {
+ str[i] = ampm[j].at(index); // fix case
+ }
+ }
+ ampm[j].remove(index, 1);
+ }
+ }
+ }
+ }
+ if (!broken[pmindex] && !broken[amindex])
+ return PossibleBoth;
+ return (!broken[amindex] ? PossibleAM : PossiblePM);
+}
+
+/*!
+ \internal
+ Max number of units that can be changed by this section.
+*/
+
+int QDateTimeParser::maxChange(int index) const
+{
+ const SectionNode &sn = sectionNode(index);
+ switch (sn.type) {
+ // Time. unit is msec
+ case MSecSection: return 999;
+ case SecondSection: return 59 * 1000;
+ case MinuteSection: return 59 * 60 * 1000;
+ case Hour24Section: case Hour12Section: return 59 * 60 * 60 * 1000;
+
+ // Date. unit is day
+ case DayOfWeekSection: return 7;
+ case DaySection: return 30;
+ case MonthSection: return 365 - 31;
+ case YearSection: return 9999 * 365;
+ case YearSection2Digits: return 100 * 365;
+ default:
+ qWarning("QDateTimeParser::maxChange() Internal error (%s)",
+ qPrintable(sectionName(sectionType(index))));
+ }
+
+ return -1;
+}
+
+QDateTimeParser::FieldInfo QDateTimeParser::fieldInfo(int index) const
+{
+ FieldInfo ret = 0;
+ const SectionNode &sn = sectionNode(index);
+ const Section s = sn.type;
+ switch (s) {
+ case MSecSection:
+ ret |= Fraction;
+ // fallthrough
+ case SecondSection:
+ case MinuteSection:
+ case Hour24Section:
+ case Hour12Section:
+ case YearSection:
+ case YearSection2Digits:
+ ret |= Numeric;
+ if (s != YearSection) {
+ ret |= AllowPartial;
+ }
+ if (sn.count != 1) {
+ ret |= FixedWidth;
+ }
+ break;
+ case MonthSection:
+ case DaySection:
+ switch (sn.count) {
+ case 2:
+ ret |= FixedWidth;
+ // fallthrough
+ case 1:
+ ret |= (Numeric|AllowPartial);
+ break;
+ }
+ break;
+ case DayOfWeekSection:
+ if (sn.count == 3)
+ ret |= FixedWidth;
+ break;
+ case AmPmSection:
+ ret |= FixedWidth;
+ break;
+ default:
+ qWarning("QDateTimeParser::fieldInfo Internal error 2 (%d %s %d)",
+ index, qPrintable(sectionName(sn.type)), sn.count);
+ break;
+ }
+ return ret;
+}
+
+/*!
+ \internal Get a number that str can become which is between min
+ and max or -1 if this is not possible.
+*/
+
+
+QString QDateTimeParser::sectionFormat(int index) const
+{
+ const SectionNode &sn = sectionNode(index);
+ return sectionFormat(sn.type, sn.count);
+}
+
+QString QDateTimeParser::sectionFormat(Section s, int count) const
+{
+ QChar fillChar;
+ switch (s) {
+ case AmPmSection: return count == 1 ? QLatin1String("AP") : QLatin1String("ap");
+ case MSecSection: fillChar = QLatin1Char('z'); break;
+ case SecondSection: fillChar = QLatin1Char('s'); break;
+ case MinuteSection: fillChar = QLatin1Char('m'); break;
+ case Hour24Section: fillChar = QLatin1Char('H'); break;
+ case Hour12Section: fillChar = QLatin1Char('h'); break;
+ case DayOfWeekSection:
+ case DaySection: fillChar = QLatin1Char('d'); break;
+ case MonthSection: fillChar = QLatin1Char('M'); break;
+ case YearSection2Digits:
+ case YearSection: fillChar = QLatin1Char('y'); break;
+ default:
+ qWarning("QDateTimeParser::sectionFormat Internal error (%s)",
+ qPrintable(sectionName(s)));
+ return QString();
+ }
+ if (fillChar.isNull()) {
+ qWarning("QDateTimeParser::sectionFormat Internal error 2");
+ return QString();
+ }
+
+ QString str;
+ str.fill(fillChar, count);
+ return str;
+}
+
+
+/*! \internal Returns true if str can be modified to represent a
+ number that is within min and max.
+*/
+
+bool QDateTimeParser::potentialValue(const QString &str, int min, int max, int index,
+ const QDateTime &currentValue, int insert) const
+{
+ if (str.isEmpty()) {
+ return true;
+ }
+ const int size = sectionMaxSize(index);
+ int val = (int)locale().toUInt(str);
+ const SectionNode &sn = sectionNode(index);
+ if (sn.type == YearSection2Digits) {
+ val += currentValue.date().year() - (currentValue.date().year() % 100);
+ }
+ if (val >= 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<len; ++i) {
+ for (int j=0; j<10; ++j) {
+ if (potentialValue(str + QLatin1Char('0' + j), min, max, index, currentValue, insert)) {
+ return true;
+ } else if (insert >= 0) {
+ QString tmp = str;
+ tmp.insert(insert, QLatin1Char('0' + j));
+ if (potentialValue(tmp, min, max, index, currentValue, insert))
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool QDateTimeParser::skipToNextSection(int index, const QDateTime &current, const QString &text) const
+{
+ Q_ASSERT(current >= getMinimum() && current <= getMaximum());
+
+ const SectionNode &node = sectionNode(index);
+ Q_ASSERT(text.size() < sectionMaxSize(index));
+
+ const QDateTime maximum = getMaximum();
+ const QDateTime minimum = getMinimum();
+ QDateTime tmp = current;
+ int min = absoluteMin(index);
+ setDigit(tmp, index, min);
+ if (tmp < minimum) {
+ min = getDigit(minimum, index);
+ }
+
+ int max = absoluteMax(index, current);
+ setDigit(tmp, index, max);
+ if (tmp > maximum) {
+ max = getDigit(maximum, index);
+ }
+ int pos = cursorPosition() - node.pos;
+ if (pos < 0 || pos >= text.size())
+ pos = -1;
+
+ const bool potential = potentialValue(text, min, max, index, current, pos);
+ return !potential;
+
+ /* 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 but
+ * if you type 3 we do
+ */
+}
+
+/*!
+ \internal
+ For debugging. Returns the name of the section \a s.
+*/
+
+QString QDateTimeParser::sectionName(int s) const
+{
+ switch (s) {
+ case QDateTimeParser::AmPmSection: return QLatin1String("AmPmSection");
+ case QDateTimeParser::DaySection: return QLatin1String("DaySection");
+ case QDateTimeParser::DayOfWeekSection: return QLatin1String("DayOfWeekSection");
+ 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::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(s);
+ }
+}
+
+/*!
+ \internal
+ For debugging. Returns the name of the state \a s.
+*/
+
+QString QDateTimeParser::stateName(int 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);
+ }
+}
+
+#ifndef QT_NO_DATESTRING
+bool QDateTimeParser::fromString(const QString &t, QDate *date, QTime *time) const
+{
+ QDateTime val(QDate(1900, 1, 1), QDATETIMEEDIT_TIME_MIN);
+ QString text = t;
+ int copy = -1;
+ const StateNode tmp = parse(text, copy, 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 // QT_NO_DATESTRING
+
+QDateTime QDateTimeParser::getMinimum() const
+{
+ return QDateTime(QDATETIMEEDIT_DATE_MIN, QDATETIMEEDIT_TIME_MIN, spec);
+}
+
+QDateTime QDateTimeParser::getMaximum() const
+{
+ return QDateTime(QDATETIMEEDIT_DATE_MAX, QDATETIMEEDIT_TIME_MAX, spec);
+}
+
+QString QDateTimeParser::getAmPmText(AmPm ap, Case cs) const
+{
+ if (ap == AmText) {
+ return (cs == UpperCase ? QLatin1String("AM") : QLatin1String("am"));
+ } else {
+ return (cs == UpperCase ? QLatin1String("PM") : QLatin1String("pm"));
+ }
+}
+
+/*
+ \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);
+}
+
+#ifdef Q_OS_SYMBIAN
+const static TTime UnixEpochOffset(I64LIT(0xdcddb30f2f8000));
+const static TInt64 MinimumMillisecondTime(KMinTInt64 / 1000);
+const static TInt64 MaximumMillisecondTime(KMaxTInt64 / 1000);
+QDateTime qt_symbian_TTime_To_QDateTime(const TTime& time)
+{
+ TTimeIntervalMicroSeconds absolute = time.MicroSecondsFrom(UnixEpochOffset);
+
+ return QDateTime::fromMSecsSinceEpoch(absolute.Int64() / 1000);
+}
+
+TTime qt_symbian_QDateTime_To_TTime(const QDateTime& datetime)
+{
+ qint64 absolute = datetime.toMSecsSinceEpoch();
+ if(absolute > MaximumMillisecondTime)
+ return TTime(KMaxTInt64);
+ if(absolute < MinimumMillisecondTime)
+ return TTime(KMinTInt64);
+ return TTime(absolute * 1000);
+}
+
+time_t qt_symbian_TTime_To_time_t(const TTime& time)
+{
+ TTimeIntervalSeconds interval;
+ TInt err = time.SecondsFrom(UnixEpochOffset, interval);
+ if (err || interval.Int() < 0)
+ return (time_t) 0;
+ return (time_t) interval.Int();
+}
+
+TTime qt_symbian_time_t_To_TTime(time_t time)
+{
+ return UnixEpochOffset + TTimeIntervalSeconds(time);
+}
+#endif //Q_OS_SYMBIAN
+
+#endif // QT_BOOTSTRAPPED
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qdatetime.h b/src/corelib/tools/qdatetime.h
new file mode 100644
index 0000000000..432c906372
--- /dev/null
+++ b/src/corelib/tools/qdatetime.h
@@ -0,0 +1,340 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDATETIME_H
+#define QDATETIME_H
+
+#include <QtCore/qstring.h>
+#include <QtCore/qnamespace.h>
+#include <QtCore/qsharedpointer.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class Q_CORE_EXPORT QDate
+{
+public:
+ enum MonthNameType {
+ DateFormat = 0,
+ StandaloneFormat
+ };
+public:
+ QDate() { jd = 0; }
+ QDate(int y, int m, int d);
+
+ bool isNull() const { return jd == 0; }
+ bool isValid() const;
+
+ 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 = 0) const;
+
+#ifndef QT_NO_TEXTDATE
+#ifdef QT3_SUPPORT
+ static QT3_SUPPORT QString monthName(int month) { return shortMonthName(month); }
+ static QT3_SUPPORT QString dayName(int weekday) { return shortDayName(weekday); }
+#endif
+ // ### Qt 5: merge these functions.
+ static QString shortMonthName(int month);
+ static QString shortMonthName(int month, MonthNameType type);
+ static QString shortDayName(int weekday);
+ static QString shortDayName(int weekday, MonthNameType type);
+ static QString longMonthName(int month);
+ static QString longMonthName(int month, MonthNameType type);
+ static QString longDayName(int weekday);
+ static QString longDayName(int weekday, MonthNameType type);
+#endif // QT_NO_TEXTDATE
+#ifndef QT_NO_DATESTRING
+ QString toString(Qt::DateFormat f = Qt::TextDate) const;
+ QString toString(const QString &format) const;
+#endif
+ bool setYMD(int y, int m, int d);
+ bool setDate(int year, int month, int day);
+
+ void getDate(int *year, int *month, int *day);
+
+ QDate addDays(int days) const;
+ QDate addMonths(int months) const;
+ QDate addYears(int years) const;
+ int daysTo(const QDate &) const;
+
+ bool operator==(const QDate &other) const { return jd == other.jd; }
+ bool operator!=(const QDate &other) const { return jd != other.jd; }
+ bool operator<(const QDate &other) const { return jd < other.jd; }
+ bool operator<=(const QDate &other) const { return jd <= other.jd; }
+ bool operator>(const QDate &other) const { return jd > other.jd; }
+ bool operator>=(const QDate &other) const { return jd >= other.jd; }
+
+ static QDate currentDate();
+#ifndef QT_NO_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);
+#ifdef QT3_SUPPORT
+ inline static QT3_SUPPORT bool leapYear(int year) { return isLeapYear(year); }
+#endif
+
+ // ### Qt 5: remove these two functions
+ static uint gregorianToJulian(int y, int m, int d);
+ static void julianToGregorian(uint jd, int &y, int &m, int &d);
+
+#ifdef QT3_SUPPORT
+ static QT3_SUPPORT QDate currentDate(Qt::TimeSpec spec);
+#endif
+
+ static inline QDate fromJulianDay(int jd) { QDate d; d.jd = jd; return d; }
+ inline int toJulianDay() const { return jd; }
+
+private:
+ uint 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
+{
+public:
+ QTime(): mds(NullTime)
+#if defined(Q_OS_WINCE)
+ , startTick(NullTime)
+#endif
+ {}
+ QTime(int h, int m, int s = 0, int ms = 0);
+
+ bool isNull() const { return mds == NullTime; }
+ bool isValid() const;
+
+ int hour() const;
+ int minute() const;
+ int second() const;
+ int msec() const;
+#ifndef QT_NO_DATESTRING
+ QString toString(Qt::DateFormat f = Qt::TextDate) const;
+ QString toString(const QString &format) const;
+#endif
+ bool setHMS(int h, int m, int s, int ms = 0);
+
+ QTime addSecs(int secs) const;
+ int secsTo(const QTime &) const;
+ QTime addMSecs(int ms) const;
+ int msecsTo(const QTime &) const;
+
+ bool operator==(const QTime &other) const { return mds == other.mds; }
+ bool operator!=(const QTime &other) const { return mds != other.mds; }
+ bool operator<(const QTime &other) const { return mds < other.mds; }
+ bool operator<=(const QTime &other) const { return mds <= other.mds; }
+ bool operator>(const QTime &other) const { return mds > other.mds; }
+ bool operator>=(const QTime &other) const { return mds >= other.mds; }
+
+ static QTime currentTime();
+#ifndef QT_NO_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);
+
+#ifdef QT3_SUPPORT
+ static QT3_SUPPORT QTime currentTime(Qt::TimeSpec spec);
+#endif
+
+ void start();
+ int restart();
+ int elapsed() const;
+private:
+ enum TimeFlag { NullTime = -1 };
+ inline int ds() const { return mds == -1 ? 0 : mds; }
+ int mds;
+#if defined(Q_OS_WINCE)
+ int startTick;
+#endif
+
+ 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
+{
+public:
+ QDateTime();
+ explicit QDateTime(const QDate &);
+ QDateTime(const QDate &, const QTime &, Qt::TimeSpec spec = Qt::LocalTime);
+ QDateTime(const QDateTime &other);
+ ~QDateTime();
+
+ QDateTime &operator=(const QDateTime &other);
+
+ bool isNull() const;
+ bool isValid() const;
+
+ QDate date() const;
+ QTime time() const;
+ Qt::TimeSpec timeSpec() const;
+ qint64 toMSecsSinceEpoch() const;
+ uint toTime_t() const;
+ void setDate(const QDate &date);
+ void setTime(const QTime &time);
+ void setTimeSpec(Qt::TimeSpec spec);
+ void setMSecsSinceEpoch(qint64 msecs);
+ void setTime_t(uint secsSince1Jan1970UTC);
+#ifndef QT_NO_DATESTRING
+ QString toString(Qt::DateFormat f = Qt::TextDate) const;
+ QString toString(const QString &format) const;
+#endif
+ QDateTime addDays(int days) const;
+ QDateTime addMonths(int months) const;
+ QDateTime addYears(int years) const;
+ QDateTime addSecs(int secs) const;
+ 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); }
+ int daysTo(const QDateTime &) const;
+ int 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); }
+
+ void setUtcOffset(int seconds);
+ int utcOffset() const;
+
+ static QDateTime currentDateTime();
+ static QDateTime currentDateTimeUtc();
+#ifndef QT_NO_DATESTRING
+ static QDateTime fromString(const QString &s, Qt::DateFormat f = Qt::TextDate);
+ static QDateTime fromString(const QString &s, const QString &format);
+#endif
+ static QDateTime fromTime_t(uint secsSince1Jan1970UTC);
+ static QDateTime fromMSecsSinceEpoch(qint64 msecs);
+ static qint64 currentMSecsSinceEpoch();
+
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT void setTime_t(uint secsSince1Jan1970UTC, Qt::TimeSpec spec) {
+ setTime_t(secsSince1Jan1970UTC);
+ if (spec == Qt::UTC)
+ *this = toUTC();
+ }
+ static inline QT3_SUPPORT QDateTime currentDateTime(Qt::TimeSpec spec) {
+ if (spec == Qt::LocalTime)
+ return currentDateTime();
+ else
+ return currentDateTime().toUTC();
+ }
+
+#endif
+
+private:
+ friend class QDateTimePrivate;
+ void detach();
+ QExplicitlySharedDataPointer<QDateTimePrivate> d;
+
+#ifndef QT_NO_DATASTREAM
+ friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QDateTime &);
+ friend Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QDateTime &);
+#endif
+};
+Q_DECLARE_TYPEINFO(QDateTime, Q_MOVABLE_TYPE);
+
+#ifdef QT3_SUPPORT
+inline QDate QDate::currentDate(Qt::TimeSpec spec)
+{
+ if (spec == Qt::LocalTime)
+ return currentDate();
+ else
+ return QDateTime::currentDateTime().toUTC().date();
+}
+
+inline QTime QTime::currentTime(Qt::TimeSpec spec)
+{
+ if (spec == Qt::LocalTime)
+ return currentTime();
+ else
+ return QDateTime::currentDateTime().toUTC().time();
+}
+#endif
+
+#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) && !defined(QT_NO_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
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDATETIME_H
diff --git a/src/corelib/tools/qdatetime_p.h b/src/corelib/tools/qdatetime_p.h
new file mode 100644
index 0000000000..ad4055db51
--- /dev/null
+++ b/src/corelib/tools/qdatetime_p.h
@@ -0,0 +1,289 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $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 "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"
+
+
+#define QDATETIMEEDIT_TIME_MIN QTime(0, 0, 0, 0)
+#define QDATETIMEEDIT_TIME_MAX QTime(23, 59, 59, 999)
+#define QDATETIMEEDIT_DATE_MIN QDate(100, 1, 1)
+#define QDATETIMEEDIT_COMPAT_DATE_MIN QDate(1752, 9, 14)
+#define QDATETIMEEDIT_DATE_MAX QDate(7999, 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
+
+class QDateTimePrivate
+{
+public:
+ enum Spec { LocalUnknown = -1, LocalStandard = 0, LocalDST = 1, UTC = 2, OffsetFromUTC = 3};
+
+ QDateTimePrivate() : spec(LocalUnknown), utcOffset(0) {}
+ QDateTimePrivate(const QDateTimePrivate &other)
+ : date(other.date), time(other.time), spec(other.spec), utcOffset(other.utcOffset)
+ {}
+
+ QAtomicInt ref;
+ QDate date;
+ QTime time;
+ Spec spec;
+ /*!
+ \internal
+ \since 4.4
+
+ The offset in seconds. Applies only when timeSpec() is OffsetFromUTC.
+ */
+ int utcOffset;
+
+ Spec getLocal(QDate &outDate, QTime &outTime) const;
+ void getUTC(QDate &outDate, QTime &outTime) const;
+ static QDateTime addMSecs(const QDateTime &dt, qint64 msecs);
+ static void addMSecs(QDate &utcDate, QTime &utcTime, qint64 msecs);
+};
+
+#ifndef QT_BOOTSTRAPPED
+
+class Q_CORE_EXPORT QDateTimeParser
+{
+public:
+ enum Context {
+ FromString,
+ DateTimeEdit
+ };
+ QDateTimeParser(QVariant::Type t, Context ctx)
+ : currentSectionIndex(-1), display(0), cachedDay(-1), parserType(t),
+ fixday(false), spec(Qt::LocalTime), context(ctx)
+ {
+ defaultLocale = QLocale::system();
+ first.type = FirstSection;
+ first.pos = -1;
+ first.count = -1;
+ last.type = FirstSection;
+ last.pos = -1;
+ last.count = -1;
+ none.type = NoSection;
+ none.pos = -1;
+ none.count = -1;
+ }
+ virtual ~QDateTimeParser() {}
+ enum {
+ Neither = -1,
+ AM = 0,
+ PM = 1,
+ PossibleAM = 2,
+ PossiblePM = 3,
+ PossibleBoth = 4
+ };
+
+ enum Section {
+ NoSection = 0x00000,
+ AmPmSection = 0x00001,
+ MSecSection = 0x00002,
+ SecondSection = 0x00004,
+ MinuteSection = 0x00008,
+ Hour12Section = 0x00010,
+ Hour24Section = 0x00020,
+ TimeSectionMask = (AmPmSection|MSecSection|SecondSection|MinuteSection|Hour12Section|Hour24Section),
+ Internal = 0x10000,
+ DaySection = 0x00100,
+ MonthSection = 0x00200,
+ YearSection = 0x00400,
+ YearSection2Digits = 0x00800,
+ DayOfWeekSection = 0x01000,
+ DateSectionMask = (DaySection|MonthSection|YearSection|YearSection2Digits|DayOfWeekSection),
+ FirstSection = 0x02000|Internal,
+ LastSection = 0x04000|Internal,
+ CalendarPopupSection = 0x08000|Internal,
+
+ NoSectionIndex = -1,
+ FirstSectionIndex = -2,
+ LastSectionIndex = -3,
+ CalendarPopupIndex = -4
+ }; // duplicated from qdatetimeedit.h
+ Q_DECLARE_FLAGS(Sections, Section)
+
+ struct SectionNode {
+ Section type;
+ mutable int pos;
+ int count;
+ };
+
+ enum State { // duplicated from QValidator
+ Invalid,
+ Intermediate,
+ Acceptable
+ };
+
+ struct StateNode {
+ StateNode() : state(Invalid), conflicts(false) {}
+ QString input;
+ State state;
+ bool conflicts;
+ QDateTime value;
+ };
+
+ enum AmPm {
+ AmText,
+ PmText
+ };
+
+ enum Case {
+ UpperCase,
+ LowerCase
+ };
+
+#ifndef QT_NO_DATESTRING
+ StateNode parse(QString &input, int &cursorPosition, const QDateTime &currentValue, bool fixup) const;
+#endif
+ int sectionMaxSize(int index) const;
+ int sectionSize(int index) const;
+ int sectionMaxSize(Section s, int count) const;
+ int sectionPos(int index) const;
+ int sectionPos(const SectionNode &sn) const;
+
+ const SectionNode &sectionNode(int index) const;
+ Section sectionType(int index) const;
+ QString sectionText(int sectionIndex) const;
+ QString sectionText(const QString &text, int sectionIndex, int index) const;
+ int getDigit(const QDateTime &dt, int index) const;
+ bool setDigit(QDateTime &t, int index, int newval) const;
+ int parseSection(const QDateTime &currentValue, int sectionIndex, QString &txt, int &cursorPosition,
+ int index, QDateTimeParser::State &state, int *used = 0) const;
+ int absoluteMax(int index, const QDateTime &value = QDateTime()) const;
+ int absoluteMin(int index) const;
+ bool parseFormat(const QString &format);
+#ifndef QT_NO_DATESTRING
+ bool fromString(const QString &text, QDate *date, QTime *time) const;
+#endif
+
+#ifndef QT_NO_TEXTDATE
+ int findMonth(const QString &str1, int monthstart, int sectionIndex,
+ QString *monthName = 0, int *used = 0) const;
+ int findDay(const QString &str1, int intDaystart, int sectionIndex,
+ QString *dayName = 0, int *used = 0) const;
+#endif
+ int findAmPm(QString &str1, int index, int *used = 0) const;
+ int maxChange(int s) const;
+ bool potentialValue(const QString &str, int min, int max, int index,
+ const QDateTime &currentValue, int insert) const;
+ bool skipToNextSection(int section, const QDateTime &current, const QString &sectionText) const;
+ QString sectionName(int s) const;
+ QString stateName(int s) const;
+
+ QString sectionFormat(int index) const;
+ QString sectionFormat(Section s, int count) const;
+
+ enum FieldInfoFlag {
+ Numeric = 0x01,
+ FixedWidth = 0x02,
+ AllowPartial = 0x04,
+ Fraction = 0x08
+ };
+ Q_DECLARE_FLAGS(FieldInfo, FieldInfoFlag)
+
+ FieldInfo fieldInfo(int index) const;
+
+ virtual QDateTime getMinimum() const;
+ virtual QDateTime getMaximum() const;
+ virtual int cursorPosition() const { return -1; }
+ virtual QString displayText() const { return text; }
+ virtual QString getAmPmText(AmPm ap, Case cs) const;
+ virtual QLocale locale() const { return defaultLocale; }
+
+ mutable int currentSectionIndex;
+ Sections display;
+ mutable int cachedDay;
+ mutable QString text;
+ QVector<SectionNode> 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_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)
+
+#ifdef Q_OS_SYMBIAN
+QDateTime qt_symbian_TTime_To_QDateTime(const TTime& time);
+TTime qt_symbian_QDateTime_To_TTime(const QDateTime& datetime);
+time_t qt_symbian_TTime_To_time_t(const TTime& time);
+TTime qt_symbian_time_t_To_TTime(time_t time);
+#endif //Q_OS_SYMBIAN
+
+#endif // QT_BOOTSTRAPPED
+
+QT_END_NAMESPACE
+
+#endif // QDATETIME_P_H
diff --git a/src/corelib/tools/qeasingcurve.cpp b/src/corelib/tools/qeasingcurve.cpp
new file mode 100644
index 0000000000..7daf95abe1
--- /dev/null
+++ b/src/corelib/tools/qeasingcurve.cpp
@@ -0,0 +1,937 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+
+| *property* | *Used for type* |
+| period | QEasingCurve::{In,Out,InOut,OutIn}Elastic |
+| amplitude | QEasingCurve::{In,Out,InOut,OutIn}Bounce, QEasingCurve::{In,Out,InOut,OutIn}Elastic |
+| overshoot | QEasingCurve::{In,Out,InOut,OutIn}Back |
+
+*/
+
+
+
+
+/*!
+ \class QEasingCurve
+ \since 4.6
+ \ingroup animation
+ \brief The QEasingCurve class provides easing curves for controlling animation.
+
+ Easing curves describe a function that controls how the speed of the interpolation
+ between 0 and 1 should be. Easing curves allow transitions from
+ one value to another to appear more natural than a simple constant speed would allow.
+ The QEasingCurve class is usually used in conjunction with the QVariantAnimation and
+ QPropertyAnimation classes but can be used on its own. It is usually used to accelerate
+ the interpolation from zero velocity (ease in) or decelerate to zero velocity (ease out).
+ Ease in and ease out can also be combined in the same easing curve.
+
+ To calculate the speed of the interpolation, the easing curve provides the function
+ valueForProgress(), where the \a progress argument specifies the progress of the
+ interpolation: 0 is the start value of the interpolation, 1 is the end value of the
+ interpolation. The returned value is the effective progress of the interpolation.
+ If the returned value is the same as the input value for all input values the easing
+ curve is a linear curve. This is the default behaviour.
+
+ For example,
+ \code
+ QEasingCurve easing(QEasingCurve::InOutQuad);
+
+ for(qreal t = 0.0; t < 1.0; t+=0.1)
+ qWarning() << "Effective progress" << t << " is
+ << easing.valueForProgress(t);
+ \endcode
+ will print the effective progress of the interpolation between 0 and 1.
+
+ When using a QPropertyAnimation, the associated easing curve will be used to control the
+ progress of the interpolation between startValue and endValue:
+ \code
+ QPropertyAnimation animation;
+ animation.setStartValue(0);
+ animation.setEndValue(1000);
+ animation.setDuration(1000);
+ animation.setEasingCurve(QEasingCurve::InOutQuad);
+ \endcode
+
+ The ability to set an amplitude, overshoot, or period depends on
+ the QEasingCurve type. Amplitude access is available to curves
+ that behave as springs such as elastic and bounce curves. Changing
+ the amplitude changes the height of the curve. Period access is
+ only available to elastic curves and setting a higher period slows
+ the rate of bounce. Only curves that have "boomerang" behaviors
+ such as the InBack, OutBack, InOutBack, and OutInBack have
+ overshoot settings. These curves will interpolate beyond the end
+ points and return to the end point, acting similar to a boomerang.
+
+ The \l{Easing Curves Example} contains samples of QEasingCurve
+ types and lets you change the curve settings.
+
+ */
+
+/*!
+ \enum QEasingCurve::Type
+
+ The type of easing curve.
+
+ \value Linear \inlineimage qeasingcurve-linear.png
+ \br
+ Easing curve for a linear (t) function:
+ velocity is constant.
+ \value InQuad \inlineimage qeasingcurve-inquad.png
+ \br
+ Easing curve for a quadratic (t^2) function:
+ accelerating from zero velocity.
+ \value OutQuad \inlineimage qeasingcurve-outquad.png
+ \br
+ Easing curve for a quadratic (t^2) function:
+ decelerating to zero velocity.
+ \value InOutQuad \inlineimage qeasingcurve-inoutquad.png
+ \br
+ Easing curve for a quadratic (t^2) function:
+ acceleration until halfway, then deceleration.
+ \value OutInQuad \inlineimage qeasingcurve-outinquad.png
+ \br
+ Easing curve for a quadratic (t^2) function:
+ deceleration until halfway, then acceleration.
+ \value InCubic \inlineimage qeasingcurve-incubic.png
+ \br
+ Easing curve for a cubic (t^3) function:
+ accelerating from zero velocity.
+ \value OutCubic \inlineimage qeasingcurve-outcubic.png
+ \br
+ Easing curve for a cubic (t^3) function:
+ decelerating to zero velocity.
+ \value InOutCubic \inlineimage qeasingcurve-inoutcubic.png
+ \br
+ Easing curve for a cubic (t^3) function:
+ acceleration until halfway, then deceleration.
+ \value OutInCubic \inlineimage qeasingcurve-outincubic.png
+ \br
+ Easing curve for a cubic (t^3) function:
+ deceleration until halfway, then acceleration.
+ \value InQuart \inlineimage qeasingcurve-inquart.png
+ \br
+ Easing curve for a quartic (t^4) function:
+ accelerating from zero velocity.
+ \value OutQuart \inlineimage qeasingcurve-outquart.png
+ \br
+ Easing curve for a quartic (t^4) function:
+ decelerating to zero velocity.
+ \value InOutQuart \inlineimage qeasingcurve-inoutquart.png
+ \br
+ Easing curve for a quartic (t^4) function:
+ acceleration until halfway, then deceleration.
+ \value OutInQuart \inlineimage qeasingcurve-outinquart.png
+ \br
+ Easing curve for a quartic (t^4) function:
+ deceleration until halfway, then acceleration.
+ \value InQuint \inlineimage qeasingcurve-inquint.png
+ \br
+ Easing curve for a quintic (t^5) easing
+ in: accelerating from zero velocity.
+ \value OutQuint \inlineimage qeasingcurve-outquint.png
+ \br
+ Easing curve for a quintic (t^5) function:
+ decelerating to zero velocity.
+ \value InOutQuint \inlineimage qeasingcurve-inoutquint.png
+ \br
+ Easing curve for a quintic (t^5) function:
+ acceleration until halfway, then deceleration.
+ \value OutInQuint \inlineimage qeasingcurve-outinquint.png
+ \br
+ Easing curve for a quintic (t^5) function:
+ deceleration until halfway, then acceleration.
+ \value InSine \inlineimage qeasingcurve-insine.png
+ \br
+ Easing curve for a sinusoidal (sin(t)) function:
+ accelerating from zero velocity.
+ \value OutSine \inlineimage qeasingcurve-outsine.png
+ \br
+ Easing curve for a sinusoidal (sin(t)) function:
+ decelerating from zero velocity.
+ \value InOutSine \inlineimage qeasingcurve-inoutsine.png
+ \br
+ Easing curve for a sinusoidal (sin(t)) function:
+ acceleration until halfway, then deceleration.
+ \value OutInSine \inlineimage qeasingcurve-outinsine.png
+ \br
+ Easing curve for a sinusoidal (sin(t)) function:
+ deceleration until halfway, then acceleration.
+ \value InExpo \inlineimage qeasingcurve-inexpo.png
+ \br
+ Easing curve for an exponential (2^t) function:
+ accelerating from zero velocity.
+ \value OutExpo \inlineimage qeasingcurve-outexpo.png
+ \br
+ Easing curve for an exponential (2^t) function:
+ decelerating from zero velocity.
+ \value InOutExpo \inlineimage qeasingcurve-inoutexpo.png
+ \br
+ Easing curve for an exponential (2^t) function:
+ acceleration until halfway, then deceleration.
+ \value OutInExpo \inlineimage qeasingcurve-outinexpo.png
+ \br
+ Easing curve for an exponential (2^t) function:
+ deceleration until halfway, then acceleration.
+ \value InCirc \inlineimage qeasingcurve-incirc.png
+ \br
+ Easing curve for a circular (sqrt(1-t^2)) function:
+ accelerating from zero velocity.
+ \value OutCirc \inlineimage qeasingcurve-outcirc.png
+ \br
+ Easing curve for a circular (sqrt(1-t^2)) function:
+ decelerating from zero velocity.
+ \value InOutCirc \inlineimage qeasingcurve-inoutcirc.png
+ \br
+ Easing curve for a circular (sqrt(1-t^2)) function:
+ acceleration until halfway, then deceleration.
+ \value OutInCirc \inlineimage qeasingcurve-outincirc.png
+ \br
+ Easing curve for a circular (sqrt(1-t^2)) function:
+ deceleration until halfway, then acceleration.
+ \value InElastic \inlineimage qeasingcurve-inelastic.png
+ \br
+ Easing curve for an elastic
+ (exponentially decaying sine wave) function:
+ accelerating from zero velocity. The peak amplitude
+ can be set with the \e amplitude parameter, and the
+ period of decay by the \e period parameter.
+ \value OutElastic \inlineimage qeasingcurve-outelastic.png
+ \br
+ Easing curve for an elastic
+ (exponentially decaying sine wave) function:
+ decelerating from zero velocity. The peak amplitude
+ can be set with the \e amplitude parameter, and the
+ period of decay by the \e period parameter.
+ \value InOutElastic \inlineimage qeasingcurve-inoutelastic.png
+ \br
+ Easing curve for an elastic
+ (exponentially decaying sine wave) function:
+ acceleration until halfway, then deceleration.
+ \value OutInElastic \inlineimage qeasingcurve-outinelastic.png
+ \br
+ Easing curve for an elastic
+ (exponentially decaying sine wave) function:
+ deceleration until halfway, then acceleration.
+ \value InBack \inlineimage qeasingcurve-inback.png
+ \br
+ Easing curve for a back (overshooting
+ cubic function: (s+1)*t^3 - s*t^2) easing in:
+ accelerating from zero velocity.
+ \value OutBack \inlineimage qeasingcurve-outback.