summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/doc/snippets/qversionnumber/main.cpp109
-rw-r--r--src/corelib/tools/qversionnumber.cpp484
-rw-r--r--src/corelib/tools/qversionnumber.h201
-rw-r--r--src/corelib/tools/tools.pri6
-rw-r--r--src/testlib/qtest.h6
-rw-r--r--src/testlib/qtestcase.cpp7
-rw-r--r--tests/auto/corelib/tools/qversionnumber/qversionnumber.pro4
-rw-r--r--tests/auto/corelib/tools/qversionnumber/tst_qversionnumber.cpp577
-rw-r--r--tests/auto/corelib/tools/tools.pro4
9 files changed, 1395 insertions, 3 deletions
diff --git a/src/corelib/doc/snippets/qversionnumber/main.cpp b/src/corelib/doc/snippets/qversionnumber/main.cpp
new file mode 100644
index 0000000000..ba72a52816
--- /dev/null
+++ b/src/corelib/doc/snippets/qversionnumber/main.cpp
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Keith Gardner <kreios4004@gmail.com>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
+** of its contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QVersionNumber>
+
+class Object
+{
+public:
+ static void genericExample();
+ static void equalityExample();
+ static void isPrefixOf();
+ static void parse();
+ static void equivalent();
+};
+
+void Object::genericExample()
+{
+ //! [0]
+ QVersionNumber version(1, 2, 3); // 1.2.3
+ //! [0]
+}
+
+void Object::equalityExample()
+{
+ //! [1]
+ QVersionNumber v1(1, 2);
+ QVersionNumber v2(1, 2, 0);
+ int compare = QVersionNumber::compare(v1, v2); // compare == -1
+ //! [1]
+}
+
+void Object::isPrefixOf()
+{
+ //! [2]
+ QVersionNumber v1(5, 3);
+ QVersionNumber v2(5, 3, 1);
+ bool value = v1.isPrefixOf(v2); // true
+ //! [2]
+}
+
+void QObject::parse()
+{
+ //! [3]
+ QString string("5.4.0-alpha");
+ int suffixIndex;
+ QVersionNumber version = QVersionNumber::fromString(string, &suffixIndex);
+ // version is 5.4.0
+ // suffixIndex is 5
+ //! [3]
+}
+
+void Object::equivalent()
+{
+ //! [4]
+ QVersionNumber v1(5, 4);
+ QVersionNumber v2(5, 4, 0);
+ bool equivalent = v1.normalized() == v2.normalized();
+ bool equal = v1 == v2;
+ // equivalent is true
+ // equal is false
+ //! [4]
+}
+
+int main()
+{
+ Object::genericExample();
+ Object::equalityExample();
+ Object::isPrefixOf();
+ Object::parse();
+ Object::equivalent();
+}
diff --git a/src/corelib/tools/qversionnumber.cpp b/src/corelib/tools/qversionnumber.cpp
new file mode 100644
index 0000000000..933f7fa6b3
--- /dev/null
+++ b/src/corelib/tools/qversionnumber.cpp
@@ -0,0 +1,484 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Keith Gardner <kreios4004@gmail.com>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qversionnumber.h>
+#include <QtCore/qhash.h>
+#include <QtCore/private/qlocale_tools_p.h>
+#include <QtCore/qcollator.h>
+
+#ifndef QT_NO_DATASTREAM
+# include <QtCore/qdatastream.h>
+#endif
+
+#ifndef QT_NO_DEBUG_STREAM
+# include <QtCore/qdebug.h>
+#endif
+
+#include <algorithm>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QVersionNumber
+ \inmodule QtCore
+ \since 5.4
+ \brief The QVersionNumber class contains a version number with an arbitrary
+ number of segments.
+
+ \snippet qversionnumber/main.cpp 0
+*/
+
+/*!
+ \fn QVersionNumber::QVersionNumber()
+
+ Produces a null version.
+
+ \sa isNull()
+*/
+
+/*!
+ \fn QVersionNumber::QVersionNumber(int maj)
+
+ Constructs a QVersionNumber consisting of just the major version number \a maj.
+*/
+
+/*!
+ \fn QVersionNumber::QVersionNumber(int maj, int min)
+
+ Constructs a QVersionNumber consisting of the major and minor
+ version numbers \a maj and \a min, respectively.
+*/
+
+/*!
+ \fn QVersionNumber::QVersionNumber(int maj, int min, int mic)
+
+ Constructs a QVersionNumber consisting of the major, minor, and
+ micro version numbers \a maj, \a min and \a mic, respectively.
+*/
+
+/*!
+ \fn QVersionNumber::QVersionNumber(const QVector<int> &seg)
+
+ Constructs a version number from the list of numbers contained in \a seg.
+*/
+
+/*!
+ \fn QVersionNumber::QVersionNumber(QVector<int> &&seg)
+
+ Move-constructs a version number from the list of numbers contained in \a seg.
+
+ This constructor is only enabled if the compiler supports C++11 move semantics.
+*/
+
+/*!
+ \fn QVersionNumber::QVersionNumber(std::initializer_list<int> args)
+
+ Construct a version number from the std::initializer_list specified by
+ \a args.
+
+ This constructor is only enabled if the compiler supports C++11 initializer
+ lists.
+*/
+
+/*!
+ \fn bool QVersionNumber::isNull() const
+
+ Returns \c true if there are zero numerical segments, otherwise returns
+ \c false.
+
+ \sa segments()
+*/
+
+/*!
+ \fn bool QVersionNumber::isNormalized() const
+
+ Returns \c true if the version number does not contain any trailing zeros,
+ otherwise returns \c false.
+
+ \sa normalized()
+*/
+
+/*!
+ \fn int QVersionNumber::majorVersion() const
+
+ Returns the major version number, that is, the first segment.
+ This function is equivalent to segmentAt(0). If this QVersionNumber object
+ is null, this function returns 0.
+
+ \sa isNull(), segmentAt()
+*/
+
+/*!
+ \fn int QVersionNumber::minorVersion() const
+
+ Returns the minor version number, that is, the second segment.
+ This function is equivalent to segmentAt(1). If this QVersionNumber object
+ does not contain a minor number, this function returns 0.
+
+ \sa isNull(), segmentAt()
+*/
+
+/*!
+ \fn int QVersionNumber::microVersion() const
+
+ Returns the micro version number, that is, the third segment.
+ This function is equivalent to segmentAt(2). If this QVersionNumber object
+ does not contain a micro number, this function returns 0.
+
+ \sa isNull(), segmentAt()
+*/
+
+/*!
+ \fn const QVector<int>& QVersionNumber::segments() const
+
+ Returns all of the numerical segments.
+
+ \sa majorVersion(), minorVersion(), microVersion()
+*/
+
+/*!
+ \fn int QVersionNumber::segmentAt(int index) const
+
+ Returns the segement value at \a index. If the index does not exist,
+ returns 0.
+
+ \sa segments(), segmentCount()
+*/
+
+/*!
+ \fn int QVersionNumber::segmentCount() const
+
+ Returns the number of integers stored in segments().
+
+ \sa segments()
+*/
+
+/*!
+ \fn QVersionNumber QVersionNumber::normalized() const
+
+ Returns an equivalent version number but with all trailing zeros removed.
+
+ To check if two numbers are equivalent, use normalized() on both version
+ numbers before perforing the compare.
+
+ \snippet qversionnumber/main.cpp 4
+ */
+
+/*!
+ \fn bool QVersionNumber::isPrefixOf(const QVersionNumber &other) const
+
+ Returns \c true if the current version number is contained in the \a other
+ version number, otherwise returns \c false.
+
+ \snippet qversionnumber/main.cpp 2
+
+ \sa commonPrefix()
+*/
+bool QVersionNumber::isPrefixOf(const QVersionNumber &other) const Q_DECL_NOTHROW
+{
+ return m_segments.size() <= other.m_segments.size() &&
+ std::equal(m_segments.begin(), m_segments.end(), other.m_segments.begin());
+}
+
+/*!
+ \fn int QVersionNumber::compare(const QVersionNumber &v1,
+ const QVersionNumber &v2)
+
+ Compares \a v1 with \a v2 and returns an integer less than, equal to, or
+ greater than zero, depending on whether \a v1 is less than, equal to, or
+ greater than \a v2, respectively.
+
+ Comparisons are performed by comparing the segments of \a v1 and \a v2
+ starting at index 0 and working towards the end of the longer list.
+
+ \snippet qversionnumber/main.cpp 1
+*/
+int QVersionNumber::compare(const QVersionNumber &v1, const QVersionNumber &v2) Q_DECL_NOTHROW
+{
+ QVector<int>::const_iterator i1 = v1.m_segments.constBegin();
+ const QVector<int>::const_iterator e1 = v1.m_segments.constEnd();
+ QVector<int>::const_iterator i2 = v2.m_segments.constBegin();
+ const QVector<int>::const_iterator e2 = v2.m_segments.constEnd();
+
+ while (i1 != e1 && i2 != e2) {
+ if (*i1 != *i2)
+ return (*i1 - *i2);
+ ++i1;
+ ++i2;
+ }
+
+ // ran out of segments in v1 and/or v2 and need to check the first trailing
+ // segment to finish the compare
+ if (i1 != e1) {
+ // v1 is longer
+ if (*i1 != 0)
+ return *i1;
+ else
+ return 1;
+ } else if (i2 != e2) {
+ // v2 is longer
+ if (*i2 != 0)
+ return -*i2;
+ else
+ return -1;
+ }
+
+ // the two version numbers are the same
+ return 0;
+}
+
+/*!
+ QVersionNumber QVersionNumber::commonPrefix(const QVersionNumber &v1,
+ const QVersionNumber &v2)
+
+ Returns a version number that is a parent version of both \a v1 and \a v2.
+
+ \sa isPrefixOf()
+*/
+QVersionNumber QVersionNumber::commonPrefix(const QVersionNumber &v1,
+ const QVersionNumber &v2)
+{
+ int min = qMin(v1.m_segments.size(), v2.m_segments.size());
+ QVector<int>::const_iterator i1 = v1.m_segments.begin();
+ QVector<int>::const_iterator e1;
+ e1 = std::mismatch(i1,
+ v1.m_segments.begin() + min,
+ v2.m_segments.begin()).first;
+ return QVersionNumber(v1.m_segments.mid(0, e1 - i1));
+}
+
+/*!
+ \fn bool operator<(const QVersionNumber &lhs, const QVersionNumber &rhs)
+ \relates QVersionNumber
+
+ Returns \c true if \a lhs is less than \a rhs; otherwise returns \c false.
+
+ \sa QVersionNumber::compare()
+*/
+
+/*!
+ \fn bool operator<=(const QVersionNumber &lhs, const QVersionNumber &rhs)
+ \relates QVersionNumber
+
+ Returns \c true if \a lhs is less than or equal to \a rhs; otherwise
+ returns \c false.
+
+ \sa QVersionNumber::compare()
+*/
+
+/*!
+ \fn bool operator>(const QVersionNumber &lhs, const QVersionNumber &rhs)
+ \relates QVersionNumber
+
+ Returns \c true if \a lhs is greater than \a rhs; otherwise returns \c
+ false.
+
+ \sa QVersionNumber::compare()
+*/
+
+/*!
+ \fn bool operator>=(const QVersionNumber &lhs, const QVersionNumber &rhs)
+ \relates QVersionNumber
+
+ Returns \c true if \a lhs is greater than or equal to \a rhs; otherwise
+ returns \c false.
+
+ \sa QVersionNumber::compare()
+*/
+
+/*!
+ \fn bool operator==(const QVersionNumber &lhs, const QVersionNumber &rhs)
+ \relates QVersionNumber
+
+ Returns \c true if \a lhs is equal to \a rhs; otherwise returns \c false.
+
+ \sa QVersionNumber::compare()
+*/
+
+/*!
+ \fn bool operator!=(const QVersionNumber &lhs, const QVersionNumber &rhs)
+ \relates QVersionNumber
+
+ Returns \c true if \a lhs is not equal to \a rhs; otherwise returns
+ \c false.
+
+ \sa QVersionNumber::compare()
+*/
+
+/*!
+ \fn QString QVersionNumber::toString() const
+
+ Returns a string with all of the segments delimited by a '.'.
+
+ \sa majorVersion(), minorVersion(), microVersion(), segments()
+*/
+QString QVersionNumber::toString() const
+{
+ QString version;
+ version.reserve(qMax(m_segments.size() * 2 - 1, 0));
+ bool first = true;
+ for (QVector<int>::const_iterator it = m_segments.begin(), end = m_segments.end(); it != end; ++it) {
+ if (!first)
+ version += QLatin1Char('.');
+ version += QString::number(*it);
+ first = false;
+ }
+ return version;
+}
+
+/*!
+ \fn QVersionNumber QVersionNumber::fromString(const QString &string,
+ int *suffixIndex)
+
+ Constructs a QVersionNumber from a specially formatted \a string of
+ non-negative decimal numbers delimited by '.'.
+
+ Once the numerical segments have been parsed, the remainder of the string
+ is considered to be the suffix string. The start index of that string will be
+ stored in \a suffixIndex if it is not null.
+
+ \snippet qversionnumber/main.cpp 3
+
+ \sa isNull()
+*/
+QVersionNumber QVersionNumber::fromString(const QString &string, int *suffixIndex)
+{
+ QVector<int> seg;
+
+ const QByteArray cString(string.toLatin1());
+
+ const char *start = cString.constData();
+ const char *end = start;
+ const char *lastGoodEnd = start;
+ const char *endOfString = cString.constData() + cString.size();
+ int value;
+
+ do {
+ bool ok = false;
+ value = int(qstrtoull(start, &end, 10, &ok));
+ if (!ok)
+ break;
+ seg.append(value);
+ start = end + 1;
+ lastGoodEnd = end;
+ } while (start < endOfString && (end < endOfString && *end == '.'));
+
+ if (suffixIndex)
+ *suffixIndex = int(lastGoodEnd - cString.constData());
+
+ return QVersionNumber(qMove(seg));
+}
+
+/*!
+ \fn QVersionNumber QVersionNumber::normalizedImpl(QVector<int> &segs)
+
+ Implementation of the normalized() function. Takes the movable list \a segs
+ and normalizes them.
+
+ \internal
+ */
+QVersionNumber QVersionNumber::normalizedImpl(QVector<int> &segs)
+{
+ while (segs.size() && segs.last() == 0)
+ segs.pop_back();
+ return QVersionNumber(qMove(segs));
+}
+
+#ifndef QT_NO_DATASTREAM
+/*!
+ \fn QDataStream& operator<<(QDataStream &out,
+ const QVersionNumber &version)
+ \relates QVersionNumber
+
+ Writes the version number \a version to stream \a out.
+
+ Note that this has nothing to do with QDataStream::version().
+ */
+QDataStream& operator<<(QDataStream &out, const QVersionNumber &version)
+{
+ out << version.segments();
+ return out;
+}
+
+/*!
+ \fn QDataStream& operator>>(QDataStream &in, QVersionNumber &version)
+ \relates QVersionNumber
+
+ Reads a version number from stream \a in and stores it in \a version.
+
+ Note that this has nothing to do with QDataStream::version().
+ */
+QDataStream& operator>>(QDataStream &in, QVersionNumber &version)
+{
+ in >> version.m_segments;
+ return in;
+}
+#endif
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug debug, const QVersionNumber &version)
+{
+ debug.noquote() << version.toString();
+ return debug.quote();
+}
+#endif
+
+/*!
+ \fn uint qHash(const QVersionNumber &key, uint seed)
+ \relates QHash
+ \since 5.4
+
+ Returns the hash value for the \a key, using \a seed to seed the
+ calculation.
+*/
+uint qHash(const QVersionNumber &key, uint seed)
+{
+ uint hash = seed;
+ for (QVector<int>::const_iterator it = key.m_segments.begin(), end = key.m_segments.end(); it != end; ++it) {
+ // used to preserve order
+ // see N3876 for more information
+ hash ^= qHash(*it) + 0x9e3779b9 + (hash << 6) + (hash >> 2);
+ }
+ return hash;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qversionnumber.h b/src/corelib/tools/qversionnumber.h
new file mode 100644
index 0000000000..a951b2f1a0
--- /dev/null
+++ b/src/corelib/tools/qversionnumber.h
@@ -0,0 +1,201 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Keith Gardner <kreios4004@gmail.com>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QVERSIONNUMBER_H
+#define QVERSIONNUMBER_H
+
+#include <QtCore/qnamespace.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qvector.h>
+#include <QtCore/qmetatype.h>
+#include <QtCore/qtypeinfo.h>
+
+QT_BEGIN_NAMESPACE
+
+class QVersionNumber;
+Q_CORE_EXPORT uint qHash(const QVersionNumber &key, uint seed = 0);
+
+#ifndef QT_NO_DATASTREAM
+Q_CORE_EXPORT QDataStream& operator<<(QDataStream &out, const QVersionNumber &version);
+Q_CORE_EXPORT QDataStream& operator>>(QDataStream &in, QVersionNumber &version);
+#endif
+
+class Q_CORE_EXPORT QVersionNumber
+{
+public:
+ inline QVersionNumber() Q_DECL_NOTHROW
+ : m_segments()
+ {}
+ // compiler-generated copy/move ctor/assignment operators are ok
+
+ inline explicit QVersionNumber(const QVector<int> &seg) Q_DECL_NOTHROW
+ : m_segments(seg)
+ {}
+#ifdef Q_COMPILER_RVALUE_REFS
+ inline explicit QVersionNumber(QVector<int> &&seg) Q_DECL_NOTHROW
+ : m_segments(qMove(seg))
+ {}
+#endif
+#ifdef Q_COMPILER_INITIALIZER_LISTS
+ inline QVersionNumber(std::initializer_list<int> args)
+ : m_segments(args)
+ {}
+#endif
+
+ inline explicit QVersionNumber(int maj)
+ { m_segments.reserve(1); m_segments << maj; }
+
+ inline explicit QVersionNumber(int maj, int min)
+ { m_segments.reserve(2); m_segments << maj << min; }
+
+ inline explicit QVersionNumber(int maj, int min, int mic)
+ { m_segments.reserve(3); m_segments << maj << min << mic; }
+
+ inline bool isNull() const Q_DECL_NOTHROW Q_REQUIRED_RESULT
+ { return m_segments.isEmpty(); }
+
+ inline bool isNormalized() const Q_DECL_NOTHROW Q_REQUIRED_RESULT
+ { return isNull() || m_segments.last() != 0; }
+
+ inline int majorVersion() const Q_DECL_NOTHROW Q_REQUIRED_RESULT
+ { return segmentAt(0); }
+
+ inline int minorVersion() const Q_DECL_NOTHROW Q_REQUIRED_RESULT
+ { return segmentAt(1); }
+
+ inline int microVersion() const Q_DECL_NOTHROW Q_REQUIRED_RESULT
+ { return segmentAt(2); }
+
+#if defined(Q_COMPILER_REF_QUALIFIERS)
+# if defined(Q_CC_GNU)
+ // required due to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61941
+# pragma push_macro("Q_REQUIRED_RESULT")
+# undef Q_REQUIRED_RESULT
+# define Q_REQUIRED_RESULT
+# define Q_REQUIRED_RESULT_pushed
+# endif
+ inline QVersionNumber normalized() const & Q_REQUIRED_RESULT
+ {
+ QVector<int> segs(m_segments);
+ return normalizedImpl(segs);
+ }
+
+ inline QVersionNumber normalized() && Q_REQUIRED_RESULT
+ {
+ return normalizedImpl(m_segments);
+ }
+
+ inline QVector<int> segments() const & Q_DECL_NOTHROW Q_REQUIRED_RESULT
+ { return m_segments; }
+
+ inline QVector<int> segments() && Q_DECL_NOTHROW Q_REQUIRED_RESULT
+ { return qMove(m_segments); }
+
+# ifdef Q_REQUIRED_RESULT_pushed
+# pragma pop_macro("Q_REQUIRED_RESULT")
+# endif
+#else
+ inline QVersionNumber normalized() const Q_REQUIRED_RESULT
+ {
+ QVector<int> segs(m_segments);
+ return normalizedImpl(segs);
+ }
+
+ inline QVector<int> segments() const Q_DECL_NOTHROW Q_REQUIRED_RESULT
+ { return m_segments; }
+#endif
+
+ inline int segmentAt(int index) const Q_DECL_NOTHROW Q_REQUIRED_RESULT
+ { return (m_segments.size() > index) ? m_segments.at(index) : 0; }
+
+ inline int segmentCount() const Q_DECL_NOTHROW Q_REQUIRED_RESULT
+ { return m_segments.size(); }
+
+ bool isPrefixOf(const QVersionNumber &other) const Q_DECL_NOTHROW Q_REQUIRED_RESULT;
+
+ static int compare(const QVersionNumber &v1, const QVersionNumber &v2) Q_DECL_NOTHROW Q_REQUIRED_RESULT;
+
+ static Q_DECL_PURE_FUNCTION QVersionNumber commonPrefix(const QVersionNumber &v1, const QVersionNumber &v2) Q_REQUIRED_RESULT;
+
+ QString toString() const Q_REQUIRED_RESULT;
+ static Q_DECL_PURE_FUNCTION QVersionNumber fromString(const QString &string, int *suffixIndex = 0) Q_REQUIRED_RESULT;
+
+private:
+ static QVersionNumber normalizedImpl(QVector<int> &segs) Q_REQUIRED_RESULT;
+
+#ifndef QT_NO_DATASTREAM
+ friend Q_CORE_EXPORT QDataStream& operator>>(QDataStream &in, QVersionNumber &version);
+#endif
+ friend Q_CORE_EXPORT uint qHash(const QVersionNumber &key, uint seed);
+
+ QVector<int> m_segments;
+};
+
+Q_DECLARE_TYPEINFO(QVersionNumber, Q_MOVABLE_TYPE);
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_CORE_EXPORT QDebug operator<<(QDebug, const QVersionNumber &version);
+#endif
+
+Q_REQUIRED_RESULT inline bool operator> (const QVersionNumber &lhs, const QVersionNumber &rhs) Q_DECL_NOTHROW
+{ return QVersionNumber::compare(lhs, rhs) > 0; }
+
+Q_REQUIRED_RESULT inline bool operator>=(const QVersionNumber &lhs, const QVersionNumber &rhs) Q_DECL_NOTHROW
+{ return QVersionNumber::compare(lhs, rhs) >= 0; }
+
+Q_REQUIRED_RESULT inline bool operator< (const QVersionNumber &lhs, const QVersionNumber &rhs) Q_DECL_NOTHROW
+{ return QVersionNumber::compare(lhs, rhs) < 0; }
+
+Q_REQUIRED_RESULT inline bool operator<=(const QVersionNumber &lhs, const QVersionNumber &rhs) Q_DECL_NOTHROW
+{ return QVersionNumber::compare(lhs, rhs) <= 0; }
+
+Q_REQUIRED_RESULT inline bool operator==(const QVersionNumber &lhs, const QVersionNumber &rhs) Q_DECL_NOTHROW
+{ return QVersionNumber::compare(lhs, rhs) == 0; }
+
+Q_REQUIRED_RESULT inline bool operator!=(const QVersionNumber &lhs, const QVersionNumber &rhs) Q_DECL_NOTHROW
+{ return QVersionNumber::compare(lhs, rhs) != 0; }
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QVersionNumber)
+
+#endif //QVERSIONNUMBER_H
diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri
index d1208a1fe6..467f870249 100644
--- a/src/corelib/tools/tools.pri
+++ b/src/corelib/tools/tools.pri
@@ -69,7 +69,8 @@ HEADERS += \
tools/qunicodetables_p.h \
tools/qunicodetools_p.h \
tools/qvarlengtharray.h \
- tools/qvector.h
+ tools/qvector.h \
+ tools/qversionnumber.h
SOURCES += \
@@ -113,7 +114,8 @@ SOURCES += \
tools/qtimezoneprivate.cpp \
tools/qunicodetools.cpp \
tools/qvector.cpp \
- tools/qvsnprintf.cpp
+ tools/qvsnprintf.cpp \
+ tools/qversionnumber.cpp
NO_PCH_SOURCES = tools/qstring_compat.cpp
msvc: NO_PCH_SOURCES += tools/qvector_msvc.cpp
diff --git a/src/testlib/qtest.h b/src/testlib/qtest.h
index 7d2f3cea72..8a18ea7541 100644
--- a/src/testlib/qtest.h
+++ b/src/testlib/qtest.h
@@ -54,6 +54,7 @@
#include <QtCore/qobject.h>
#include <QtCore/qvariant.h>
#include <QtCore/qurl.h>
+#include <QtCore/qversionnumber.h>
#include <QtCore/qpoint.h>
#include <QtCore/qsize.h>
@@ -171,6 +172,11 @@ template<> inline char *toString(const QVariant &v)
return qstrdup(vstring.constData());
}
+template<> inline char *toString(const QVersionNumber &version)
+{
+ return toString(version.toString());
+}
+
template<>
inline bool qCompare(QString const &t1, QLatin1String const &t2, const char *actual,
const char *expected, const char *file, int line)
diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp
index 703e547f6b..739d341233 100644
--- a/src/testlib/qtestcase.cpp
+++ b/src/testlib/qtestcase.cpp
@@ -1034,6 +1034,13 @@ QT_BEGIN_NAMESPACE
Returns a textual representation of the given \a variant.
*/
+/*!
+ \fn char *QTest::toString(const QVersionNumber &version)
+ \overload
+
+ Returns a textual representation of the given \a version.
+*/
+
/*! \fn void QTest::qWait(int ms)
Waits for \a ms milliseconds. While waiting, events will be processed and
diff --git a/tests/auto/corelib/tools/qversionnumber/qversionnumber.pro b/tests/auto/corelib/tools/qversionnumber/qversionnumber.pro
new file mode 100644
index 0000000000..08ee0dd3d9
--- /dev/null
+++ b/tests/auto/corelib/tools/qversionnumber/qversionnumber.pro
@@ -0,0 +1,4 @@
+CONFIG += testcase parallel_test
+TARGET = tst_qversionnumber
+QT = core testlib
+SOURCES = tst_qversionnumber.cpp
diff --git a/tests/auto/corelib/tools/qversionnumber/tst_qversionnumber.cpp b/tests/auto/corelib/tools/qversionnumber/tst_qversionnumber.cpp
new file mode 100644
index 0000000000..a43bb3ee68
--- /dev/null
+++ b/tests/auto/corelib/tools/qversionnumber/tst_qversionnumber.cpp
@@ -0,0 +1,577 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Keith Gardner <kreios4004@gmail.com>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <qversionnumber.h>
+
+class tst_QVersionNumber : public QObject
+{
+ Q_OBJECT
+
+private:
+ void singleInstanceData();
+ void comparisonData();
+
+private slots:
+ void initTestCase();
+ void constructorDefault();
+ void constructorVersioned_data();
+ void constructorVersioned();
+ void constructorExplicit();
+ void constructorCopy_data();
+ void constructorCopy();
+ void compareGreater_data();
+ void compareGreater();
+ void compareGreaterEqual_data();
+ void compareGreaterEqual();
+ void compareLess_data();
+ void compareLess();
+ void compareLessEqual_data();
+ void compareLessEqual();
+ void compareEqual_data();
+ void compareEqual();
+ void compareNotEqual_data();
+ void compareNotEqual();
+ void compare_data();
+ void compare();
+ void isPrefixOf_data();
+ void isPrefixOf();
+ void commonPrefix_data();
+ void commonPrefix();
+ void normalized_data();
+ void normalized();
+ void isNormalized_data();
+ void isNormalized();
+ void assignment_data();
+ void assignment();
+ void fromString_data();
+ void fromString();
+ void toString_data();
+ void toString();
+ void isNull_data();
+ void isNull();
+ void serialize_data();
+ void serialize();
+ void moveSemantics();
+};
+
+void tst_QVersionNumber::singleInstanceData()
+{
+ QTest::addColumn<QVector<int> >("segments");
+ QTest::addColumn<QVersionNumber>("expectedVersion");
+ QTest::addColumn<QString>("expectedString");
+ QTest::addColumn<QString>("constructionString");
+ QTest::addColumn<int>("suffixIndex");
+ QTest::addColumn<bool>("isNull");
+
+ // segments expectedVersion expectedString constructionString suffixIndex null
+ QTest::newRow("null") << QVector<int>() << QVersionNumber(QVector<int>()) << QString() << QString() << 0 << true;
+ QTest::newRow("text") << QVector<int>() << QVersionNumber(QVector<int>()) << QString() << QStringLiteral("text") << 0 << true;
+ QTest::newRow(" text") << QVector<int>() << QVersionNumber(QVector<int>()) << QString() << QStringLiteral(" text") << 0 << true;
+ QTest::newRow("Empty String") << QVector<int>() << QVersionNumber(QVector<int>()) << QString() << QStringLiteral("Empty String") << 0 << true;
+ QTest::newRow("-1.-2") << (QVector<int>()) << QVersionNumber() << QStringLiteral("") << QStringLiteral("-1.-2") << 0 << true;
+ QTest::newRow("1.-2-3") << (QVector<int>() << 1) << QVersionNumber(QVector<int>() << 1) << QStringLiteral("1") << QStringLiteral("1.-2-3") << 1 << false;
+ QTest::newRow("1.2-3") << (QVector<int>() << 1 << 2) << QVersionNumber(QVector<int>() << 1 << 2) << QStringLiteral("1.2") << QStringLiteral("1.2-3") << 3 << false;
+ QTest::newRow("0") << (QVector<int>() << 0) << QVersionNumber(QVector<int>() << 0) << QStringLiteral("0") << QStringLiteral("0") << 1 << false;
+ QTest::newRow("0.1") << (QVector<int>() << 0 << 1) << QVersionNumber(QVector<int>() << 0 << 1) << QStringLiteral("0.1") << QStringLiteral("0.1") << 3 << false;
+ QTest::newRow("0.1.2") << (QVector<int>() << 0 << 1 << 2) << QVersionNumber(0, 1, 2) << QStringLiteral("0.1.2") << QStringLiteral("0.1.2") << 5 << false;
+ QTest::newRow("0.1.2alpha") << (QVector<int>() << 0 << 1 << 2) << QVersionNumber(0, 1, 2) << QStringLiteral("0.1.2") << QStringLiteral("0.1.2alpha") << 5 << false;
+ QTest::newRow("0.1.2-alpha") << (QVector<int>() << 0 << 1 << 2) << QVersionNumber(0, 1, 2) << QStringLiteral("0.1.2") << QStringLiteral("0.1.2-alpha") << 5 << false;
+ QTest::newRow("0.1.2.alpha") << (QVector<int>() << 0 << 1 << 2) << QVersionNumber(0, 1, 2) << QStringLiteral("0.1.2") << QStringLiteral("0.1.2.alpha") << 5 << false;
+ QTest::newRow("0.1.2.3.4.alpha") << (QVector<int>() << 0 << 1 << 2 << 3 << 4) << QVersionNumber(QVector<int>() << 0 << 1 << 2 << 3 << 4) << QStringLiteral("0.1.2.3.4") << QStringLiteral("0.1.2.3.4.alpha") << 9 << false;
+ QTest::newRow("0.1.2.3.4 alpha") << (QVector<int>() << 0 << 1 << 2 << 3 << 4) << QVersionNumber(QVector<int>() << 0 << 1 << 2 << 3 << 4) << QStringLiteral("0.1.2.3.4") << QStringLiteral("0.1.2.3.4 alpha") << 9 << false;
+ QTest::newRow("0.1.2.3.4 alp ha") << (QVector<int>() << 0 << 1 << 2 << 3 << 4) << QVersionNumber(QVector<int>() << 0 << 1 << 2 << 3 << 4) << QStringLiteral("0.1.2.3.4") << QStringLiteral("0.1.2.3.4 alp ha") << 9 << false;
+ QTest::newRow("0.1.2.3.4alp ha") << (QVector<int>() << 0 << 1 << 2 << 3 << 4) << QVersionNumber(QVector<int>() << 0 << 1 << 2 << 3 << 4) << QStringLiteral("0.1.2.3.4") << QStringLiteral("0.1.2.3.4alp ha") << 9 << false;
+ QTest::newRow("0.1.2.3.4alpha ") << (QVector<int>() << 0 << 1 << 2 << 3 << 4) << QVersionNumber(QVector<int>() << 0 << 1 << 2 << 3 << 4) << QStringLiteral("0.1.2.3.4") << QStringLiteral("0.1.2.3.4alpha ") << 9 << false;
+ QTest::newRow("10.09") << (QVector<int>() << 10 << 9) << QVersionNumber(QVector<int>() << 10 << 9) << QStringLiteral("10.9") << QStringLiteral("10.09") << 5 << false;
+ QTest::newRow("10.0x") << (QVector<int>() << 10 << 0) << QVersionNumber(QVector<int>() << 10 << 0) << QStringLiteral("10.0") << QStringLiteral("10.0x") << 4 << false;
+ QTest::newRow("10.0xTest") << (QVector<int>() << 10 << 0) << QVersionNumber(QVector<int>() << 10 << 0) << QStringLiteral("10.0") << QStringLiteral("10.0xTest") << 4 << false;
+}
+
+void tst_QVersionNumber::comparisonData()
+{
+ QTest::addColumn<QVersionNumber>("lhs");
+ QTest::addColumn<QVersionNumber>("rhs");
+ QTest::addColumn<bool>("equal");
+ QTest::addColumn<bool>("notEqual");
+ QTest::addColumn<bool>("lessThan");
+ QTest::addColumn<bool>("lessThanOrEqual");
+ QTest::addColumn<bool>("greaterThan");
+ QTest::addColumn<bool>("greaterThanOrEqual");
+ QTest::addColumn<int>("compareResult");
+ QTest::addColumn<bool>("isPrefix");
+ QTest::addColumn<QVersionNumber>("common");
+
+ // LHS RHS == != < <= > >= compareResult isPrefixOf commonPrefix
+ QTest::newRow("null, null") << QVersionNumber() << QVersionNumber() << true << false << false << true << false << true << 0 << true << QVersionNumber();
+ QTest::newRow("null, 0") << QVersionNumber() << QVersionNumber(0) << false << true << true << true << false << false << -1 << true << QVersionNumber();
+ QTest::newRow("0, null") << QVersionNumber(0) << QVersionNumber() << false << true << false << false << true << true << 1 << false << QVersionNumber();
+ QTest::newRow("0, 0") << QVersionNumber(0) << QVersionNumber(0) << true << false << false << true << false << true << 0 << true << QVersionNumber(0);
+ QTest::newRow("1.0, 1.0") << QVersionNumber(1, 0) << QVersionNumber(1, 0) << true << false << false << true << false << true << 0 << true << QVersionNumber(1, 0);
+ QTest::newRow("1, 1.0") << QVersionNumber(1) << QVersionNumber(1, 0) << false << true << true << true << false << false << -1 << true << QVersionNumber(1);
+ QTest::newRow("1.0, 1") << QVersionNumber(1, 0) << QVersionNumber(1) << false << true << false << false << true << true << 1 << false << QVersionNumber(1);
+ QTest::newRow("0.1.2, 0.1") << QVersionNumber(0, 1, 2) << QVersionNumber(0, 1) << false << true << false << false << true << true << 2 << false << QVersionNumber(0, 1);
+ QTest::newRow("0.1, 0.1.2") << QVersionNumber(0, 1) << QVersionNumber(0, 1, 2) << false << true << true << true << false << false << -2 << true << QVersionNumber(0, 1);
+ QTest::newRow("0.1.2, 0.1.2") << QVersionNumber(0, 1, 2) << QVersionNumber(0, 1, 2) << true << false << false << true << false << true << 0 << true << QVersionNumber(0, 1, 2);
+ QTest::newRow("0.1.2, 1.1.2") << QVersionNumber(0, 1, 2) << QVersionNumber(1, 1, 2) << false << true << true << true << false << false << -1 << false << QVersionNumber();
+ QTest::newRow("1.1.2, 0.1.2") << QVersionNumber(1, 1, 2) << QVersionNumber(0, 1, 2) << false << true << false << false << true << true << 1 << false << QVersionNumber();
+ QTest::newRow("1, -1") << QVersionNumber(1) << QVersionNumber(-1) << false << true << false << false << true << true << 2 << false << QVersionNumber();
+ QTest::newRow("-1, 1") << QVersionNumber(-1) << QVersionNumber(1) << false << true << true << true << false << false << -2 << false << QVersionNumber();
+ QTest::newRow("0.1, 0.-1") << QVersionNumber(0, 1) << QVersionNumber(0, -1) << false << true << false << false << true << true << 2 << false << QVersionNumber(0);
+ QTest::newRow("0.-1, 0.1") << QVersionNumber(0, -1) << QVersionNumber(0, 1) << false << true << true << true << false << false << -2 << false << QVersionNumber(0);
+ QTest::newRow("0.-1, 0") << QVersionNumber(0, -1) << QVersionNumber(0) << false << true << true << true << false << false << -1 << false << QVersionNumber(0);
+ QTest::newRow("0, 0.-1") << QVersionNumber(0) << QVersionNumber(0, -1) << false << true << false << false << true << true << 1 << true << QVersionNumber(0);
+}
+
+void tst_QVersionNumber::initTestCase()
+{
+ qRegisterMetaType<QVector<int> >();
+}
+
+void tst_QVersionNumber::constructorDefault()
+{
+ QVersionNumber version;
+
+ QCOMPARE(version.majorVersion(), 0);
+ QCOMPARE(version.minorVersion(), 0);
+ QCOMPARE(version.microVersion(), 0);
+ QCOMPARE(version.segments(), QVector<int>());
+}
+
+void tst_QVersionNumber::constructorVersioned_data()
+{
+ singleInstanceData();
+}
+
+void tst_QVersionNumber::constructorVersioned()
+{
+ QFETCH(QVector<int>, segments);
+ QFETCH(QVersionNumber, expectedVersion);
+
+ QVersionNumber version(segments);
+ QCOMPARE(version.majorVersion(), expectedVersion.majorVersion());
+ QCOMPARE(version.minorVersion(), expectedVersion.minorVersion());
+ QCOMPARE(version.microVersion(), expectedVersion.microVersion());
+ QCOMPARE(version.segments(), expectedVersion.segments());
+}
+
+void tst_QVersionNumber::constructorExplicit()
+{
+ QVersionNumber v1(1);
+ QVersionNumber v2(QVector<int>() << 1);
+
+ QCOMPARE(v1.segments(), v2.segments());
+
+ QVersionNumber v3(1, 2);
+ QVersionNumber v4(QVector<int>() << 1 << 2);
+
+ QCOMPARE(v3.segments(), v4.segments());
+
+ QVersionNumber v5(1, 2, 3);
+ QVersionNumber v6(QVector<int>() << 1 << 2 << 3);
+
+ QCOMPARE(v5.segments(), v6.segments());
+
+#ifdef Q_COMPILER_INITIALIZER_LISTS
+ QVersionNumber v7(4, 5, 6);
+ QVersionNumber v8 = {4, 5, 6};
+
+ QCOMPARE(v7.segments(), v8.segments());
+#endif
+}
+
+void tst_QVersionNumber::constructorCopy_data()
+{
+ singleInstanceData();
+}
+
+void tst_QVersionNumber::constructorCopy()
+{
+ QFETCH(QVector<int>, segments);
+ QFETCH(QVersionNumber, expectedVersion);
+
+ QVersionNumber original(segments);
+ QVersionNumber version(original);
+
+ QCOMPARE(version.majorVersion(), expectedVersion.majorVersion());
+ QCOMPARE(version.minorVersion(), expectedVersion.minorVersion());
+ QCOMPARE(version.microVersion(), expectedVersion.microVersion());
+ QCOMPARE(version.segments(), expectedVersion.segments());
+}
+
+void tst_QVersionNumber::compareGreater_data()
+{
+ comparisonData();
+}
+
+void tst_QVersionNumber::compareGreater()
+{
+ QFETCH(QVersionNumber, lhs);
+ QFETCH(QVersionNumber, rhs);
+ QFETCH(bool, greaterThan);
+
+ QCOMPARE(lhs > rhs, greaterThan);
+}
+
+void tst_QVersionNumber::compareGreaterEqual_data()
+{
+ comparisonData();
+}
+
+void tst_QVersionNumber::compareGreaterEqual()
+{
+ QFETCH(QVersionNumber, lhs);
+ QFETCH(QVersionNumber, rhs);
+ QFETCH(bool, greaterThanOrEqual);
+
+ QCOMPARE(lhs >= rhs, greaterThanOrEqual);
+}
+
+void tst_QVersionNumber::compareLess_data()
+{
+ comparisonData();
+}
+
+void tst_QVersionNumber::compareLess()
+{
+ QFETCH(QVersionNumber, lhs);
+ QFETCH(QVersionNumber, rhs);
+ QFETCH(bool, lessThan);
+
+ QCOMPARE(lhs < rhs, lessThan);
+}
+
+void tst_QVersionNumber::compareLessEqual_data()
+{
+ comparisonData();
+}
+
+void tst_QVersionNumber::compareLessEqual()
+{
+ QFETCH(QVersionNumber, lhs);
+ QFETCH(QVersionNumber, rhs);
+ QFETCH(bool, lessThanOrEqual);
+
+ QCOMPARE(lhs <= rhs, lessThanOrEqual);
+}
+
+void tst_QVersionNumber::compareEqual_data()
+{
+ comparisonData();
+}
+
+void tst_QVersionNumber::compareEqual()
+{
+ QFETCH(QVersionNumber, lhs);
+ QFETCH(QVersionNumber, rhs);
+ QFETCH(bool, equal);
+
+ QCOMPARE(lhs == rhs, equal);
+}
+
+void tst_QVersionNumber::compareNotEqual_data()
+{
+ comparisonData();
+}
+
+void tst_QVersionNumber::compareNotEqual()
+{
+ QFETCH(QVersionNumber, lhs);
+ QFETCH(QVersionNumber, rhs);
+ QFETCH(bool, notEqual);
+
+ QCOMPARE(lhs != rhs, notEqual);
+}
+
+void tst_QVersionNumber::compare_data()
+{
+ comparisonData();
+}
+
+void tst_QVersionNumber::compare()
+{
+ QFETCH(QVersionNumber, lhs);
+ QFETCH(QVersionNumber, rhs);
+ QFETCH(int, compareResult);
+
+ QCOMPARE(QVersionNumber::compare(lhs, rhs), compareResult);
+}
+
+void tst_QVersionNumber::isPrefixOf_data()
+{
+ comparisonData();
+}
+
+void tst_QVersionNumber::isPrefixOf()
+{
+ QFETCH(QVersionNumber, lhs);
+ QFETCH(QVersionNumber, rhs);
+ QFETCH(bool, isPrefix);
+
+ QCOMPARE(lhs.isPrefixOf(rhs), isPrefix);
+}
+
+void tst_QVersionNumber::commonPrefix_data()
+{
+ comparisonData();
+}
+
+void tst_QVersionNumber::commonPrefix()
+{
+ QFETCH(QVersionNumber, lhs);
+ QFETCH(QVersionNumber, rhs);
+ QFETCH(QVersionNumber, common);
+
+ QVersionNumber calculatedPrefix = QVersionNumber::commonPrefix(lhs, rhs);
+ QCOMPARE(calculatedPrefix, common);
+ QCOMPARE(calculatedPrefix.segments(), common.segments());
+}
+
+void tst_QVersionNumber::normalized_data()
+{
+ QTest::addColumn<QVersionNumber>("version");
+ QTest::addColumn<QVersionNumber>("expected");
+
+ QTest::newRow("0") << QVersionNumber(0) << QVersionNumber();
+ QTest::newRow("1") << QVersionNumber(1) << QVersionNumber(1);
+ QTest::newRow("1.2") << QVersionNumber(1, 2) << QVersionNumber(1, 2);
+ QTest::newRow("1.0") << QVersionNumber(1, 0) << QVersionNumber(1);
+ QTest::newRow("1.0.0") << QVersionNumber(1, 0, 0) << QVersionNumber(1);
+ QTest::newRow("1.0.1") << QVersionNumber(1, 0, 1) << QVersionNumber(1, 0, 1);
+ QTest::newRow("1.0.1.0") << QVersionNumber(QVector<int>() << 1 << 0 << 1 << 0) << QVersionNumber(1, 0, 1);
+ QTest::newRow("0.0.1.0") << QVersionNumber(QVector<int>() << 0 << 0 << 1 << 0) << QVersionNumber(0, 0, 1);
+}
+
+void tst_QVersionNumber::normalized()
+{
+ QFETCH(QVersionNumber, version);
+ QFETCH(QVersionNumber, expected);
+
+ QCOMPARE(version.normalized(), expected);
+ QCOMPARE(qMove(version).normalized(), expected);
+}
+
+void tst_QVersionNumber::isNormalized_data()
+{
+ QTest::addColumn<QVersionNumber>("version");
+ QTest::addColumn<bool>("expected");
+
+ QTest::newRow("null") << QVersionNumber() << true;
+ QTest::newRow("0") << QVersionNumber(0) << false;
+ QTest::newRow("1") << QVersionNumber(1) << true;
+ QTest::newRow("1.2") << QVersionNumber(1, 2) << true;
+ QTest::newRow("1.0") << QVersionNumber(1, 0) << false;
+ QTest::newRow("1.0.0") << QVersionNumber(1, 0, 0) << false;
+ QTest::newRow("1.0.1") << QVersionNumber(1, 0, 1) << true;
+}
+
+void tst_QVersionNumber::isNormalized()
+{
+ QFETCH(QVersionNumber, version);
+ QFETCH(bool, expected);
+
+ QCOMPARE(version.isNormalized(), expected);
+}
+
+void tst_QVersionNumber::assignment_data()
+{
+ singleInstanceData();
+}
+
+void tst_QVersionNumber::assignment()
+{
+ QFETCH(QVector<int>, segments);
+ QFETCH(QVersionNumber, expectedVersion);
+
+ QVersionNumber original(segments);
+ QVersionNumber version;
+ version = original;
+
+ QCOMPARE(version.majorVersion(), expectedVersion.majorVersion());
+ QCOMPARE(version.minorVersion(), expectedVersion.minorVersion());
+ QCOMPARE(version.microVersion(), expectedVersion.microVersion());
+ QCOMPARE(version.segments(), expectedVersion.segments());
+}
+
+void tst_QVersionNumber::fromString_data()
+{
+ singleInstanceData();
+}
+
+void tst_QVersionNumber::fromString()
+{
+ QFETCH(QString, constructionString);
+ QFETCH(QVersionNumber, expectedVersion);
+ QFETCH(int, suffixIndex);
+
+ int index;
+ QCOMPARE(QVersionNumber::fromString(constructionString), expectedVersion);
+ QCOMPARE(QVersionNumber::fromString(constructionString, &index), expectedVersion);
+ QCOMPARE(index, suffixIndex);
+}
+
+void tst_QVersionNumber::toString_data()
+{
+ singleInstanceData();
+
+ // segments expectedVersion expectedString constructionString suffixIndex null
+ QTest::newRow("-1") << (QVector<int>() << -1) << QVersionNumber(-1) << QString("-1") << QString() << 0 << true;
+ QTest::newRow("-1.0") << (QVector<int>() << -1 << 0) << QVersionNumber(-1, 0) << QString("-1.0") << QString() << 0 << true;
+ QTest::newRow("1.-2") << (QVector<int>() << 1 << -2) << QVersionNumber(1, -2) << QString("1.-2") << QString() << 0 << true;
+}
+
+void tst_QVersionNumber::toString()
+{
+ QFETCH(QVersionNumber, expectedVersion);
+ QFETCH(QString, expectedString);
+
+ QCOMPARE(expectedVersion.toString(), expectedString);
+}
+
+void tst_QVersionNumber::isNull_data()
+{
+ singleInstanceData();
+}
+
+void tst_QVersionNumber::isNull()
+{
+ QFETCH(QVector<int>, segments);
+ QFETCH(bool, isNull);
+
+ QVersionNumber version(segments);
+
+ QCOMPARE(version.isNull(), isNull);
+}
+
+void tst_QVersionNumber::serialize_data()
+{
+ singleInstanceData();
+}
+
+void tst_QVersionNumber::serialize()
+{
+ QFETCH(QVector<int>, segments);
+
+ QVersionNumber original(segments);
+ QVersionNumber version;
+
+ QByteArray buffer;
+ {
+ QDataStream ostream(&buffer, QIODevice::WriteOnly);
+ ostream << original;
+ }
+ {
+ QDataStream istream(buffer);
+ istream >> version;
+ }
+
+ QCOMPARE(version.majorVersion(), original.majorVersion());
+ QCOMPARE(version.minorVersion(), original.minorVersion());
+ QCOMPARE(version.microVersion(), original.microVersion());
+ QCOMPARE(version.segments(), original.segments());
+}
+
+void tst_QVersionNumber::moveSemantics()
+{
+#if defined(_MSC_VER) && _MSC_VER == 1600
+# define Q_MSVC_2010
+#endif
+#if defined(Q_COMPILER_RVALUE_REFS) && !defined(Q_MSVC_2010)
+ // QVersionNumber(QVersionNumber &&)
+ {
+ QVersionNumber v1(1, 2, 3);
+ QVersionNumber v2 = qMove(v1);
+ QCOMPARE(v2, QVersionNumber(1, 2, 3));
+ }
+ // QVersionNumber &operator=(QVersionNumber &&)
+ {
+ QVersionNumber v1(1, 2, 3);
+ QVersionNumber v2;
+ v2 = qMove(v1);
+ QCOMPARE(v2, QVersionNumber(1, 2, 3));
+ }
+ // QVersionNumber(QVector<int> &&)
+ {
+ QVector<int> segments = QVector<int>() << 1 << 2 << 3;
+ QVersionNumber v1(segments);
+ QVersionNumber v2(qMove(segments));
+ QVERIFY(!v1.isNull());
+ QVERIFY(!v2.isNull());
+ QCOMPARE(v1, v2);
+ }
+#endif
+#if defined(Q_COMPILER_REF_QUALIFIERS) && !defined(Q_MSVC_2010)
+ // normalized()
+ {
+ QVersionNumber v(1, 0, 0);
+ QVERIFY(!v.isNull());
+ QVersionNumber nv;
+ nv = v.normalized();
+ QVERIFY(!v.isNull());
+ QVERIFY(!nv.isNull());
+ QVERIFY(nv.isNormalized());
+ nv = qMove(v).normalized();
+ QVERIFY(!nv.isNull());
+ QVERIFY(nv.isNormalized());
+ }
+ // segments()
+ {
+ QVersionNumber v(1, 2, 3);
+ QVERIFY(!v.isNull());
+ QVector<int> segments;
+ segments = v.segments();
+ QVERIFY(!v.isNull());
+ QVERIFY(!segments.empty());
+ segments = qMove(v).segments();
+ QVERIFY(!segments.empty());
+ }
+#endif
+#if !defined(Q_COMPILER_RVALUE_REFS) && !defined(Q_COMPILER_REF_QUALIFIERS) && !defined(Q_MSVC_2010)
+ QSKIP("This test requires C++11 move semantics support in the compiler.");
+#elif defined(Q_MSVC_2010)
+ QSKIP("This test requires compiler generated move constructors and operators.");
+#endif
+}
+
+QTEST_APPLESS_MAIN(tst_QVersionNumber)
+
+#include "tst_qversionnumber.moc"
diff --git a/tests/auto/corelib/tools/tools.pro b/tests/auto/corelib/tools/tools.pro
index 352cf88d44..19cb060960 100644
--- a/tests/auto/corelib/tools/tools.pro
+++ b/tests/auto/corelib/tools/tools.pro
@@ -59,4 +59,6 @@ SUBDIRS=\
qtimeline \
qvarlengtharray \
qvector \
- qvector_strictiterators
+ qvector_strictiterators \
+ qversionnumber
+