summaryrefslogtreecommitdiffstats
path: root/src/corelib/tools
diff options
context:
space:
mode:
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.png
+ \br
+ Easing curve for a back (overshooting
+ cubic function: (s+1)*t^3 - s*t^2) easing out:
+ decelerating to zero velocity.
+ \value InOutBack \inlineimage qeasingcurve-inoutback.png
+ \br
+ Easing curve for a back (overshooting
+ cubic function: (s+1)*t^3 - s*t^2) easing in/out:
+ acceleration until halfway, then deceleration.
+ \value OutInBack \inlineimage qeasingcurve-outinback.png
+ \br
+ Easing curve for a back (overshooting
+ cubic easing: (s+1)*t^3 - s*t^2) easing out/in:
+ deceleration until halfway, then acceleration.