Long live QStringIterator!
UCS-4 iterator over a QString. Kept private for now so we can still work on the API. Done-with: Thiago Change-Id: I377f8bb1921e591ee3292c08c3e097fb6bc7f0c4 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>bb10
parent
b9fe8e30cb
commit
8cbe52d581
|
|
@ -0,0 +1,72 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.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 <QString>
|
||||
#include <QStringIterator>
|
||||
#include <QDebug>
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
{
|
||||
//! [0]
|
||||
QString string(QStringLiteral("a string"));
|
||||
QStringIterator i(string);
|
||||
//! [0]
|
||||
|
||||
//! [1]
|
||||
// will print 97, 32, 115, 116, etc.;
|
||||
// that is, the decimal value of the code points in the Unicode string "a string"
|
||||
while (i.hasNext())
|
||||
qDebug() << i.next();
|
||||
//! [1]
|
||||
}
|
||||
|
||||
{
|
||||
//! [2]
|
||||
QString string(QStringLiteral("𝄞 is the G clef"));
|
||||
QStringIterator i(string);
|
||||
qDebug() << hex << i.next(); // will print 1d11e (U+1D11E, MUSICAL SYMBOL G CLEF)
|
||||
qDebug() << hex << i.next(); // will print 20 (U+0020, SPACE)
|
||||
qDebug() << hex << i.next(); // will print 69 (U+0069, LATIN SMALL LETTER I)
|
||||
//! [2]
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,328 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.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$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
\class QStringIterator
|
||||
\since 5.3
|
||||
\inmodule QtCore
|
||||
\ingroup tools
|
||||
|
||||
\internal
|
||||
|
||||
\brief The QStringIterator class provides a Unicode-aware iterator over QString.
|
||||
|
||||
\reentrant
|
||||
|
||||
QStringIterator is a Java-like, bidirectional, const iterator over the contents of a
|
||||
QString. Unlike QString's own iterators, which manage the individual UTF-16 code units,
|
||||
QStringIterator is Unicode-aware: it will transparently handle the \e{surrogate pairs}
|
||||
that may be present in a QString, and return the individual Unicode code points.
|
||||
|
||||
You can create a QStringIterator that iterates over a given
|
||||
QString by passing the string to the QStringIterator's constructor:
|
||||
|
||||
\snippet code/src_corelib_tools_qstringiterator.cpp 0
|
||||
|
||||
A newly created QStringIterator will point before the first position in the
|
||||
string. It is possible to check whether the iterator can be advanced by
|
||||
calling hasNext(), and actually advance it (and obtain the next code point)
|
||||
by calling next():
|
||||
|
||||
\snippet code/src_corelib_tools_qstringiterator.cpp 1
|
||||
|
||||
Similarly, the hasPrevious() and previous() functions can be used to iterate backwards.
|
||||
|
||||
The peekNext() and peekPrevious() functions will return the code point
|
||||
respectively after and behind the iterator's current position, but unlike
|
||||
next() and previous() they will not move the iterator.
|
||||
Similarly, the advance() and recede() functions will move the iterator
|
||||
respectively after and behind the iterator's current position, but they
|
||||
will not return the code point the iterator has moved through.
|
||||
|
||||
\section1 Unicode handling
|
||||
|
||||
QString and all of its functions work in terms of UTF-16 code units. Unicode code points
|
||||
that fall outside the Basic Multilingual Plane (U+10000 to U+10FFFF) will therefore
|
||||
be represented by \e{surrogate pairs} in a QString, that is, a sequence of two
|
||||
UTF-16 code units that encode a single code point.
|
||||
|
||||
QStringIterator will automatically handle surrogate pairs inside a QString,
|
||||
and return the correctly decoded code point, while also moving the iterator by
|
||||
the right amount of code units to match the decoded code points.
|
||||
|
||||
For instance:
|
||||
|
||||
\snippet code/src_corelib_tools_qstringiterator.cpp 2
|
||||
|
||||
If the iterator is not able to decode the next code point (or the previous
|
||||
one, when iterating backwards), then it will return \c{0xFFFD}, that is,
|
||||
Unicode's replacement character (see QChar::ReplacementCharacter).
|
||||
It is possible to make QStringIterator return another value when it encounters
|
||||
a decoding problem; please refer to the each function documentation for
|
||||
more details.
|
||||
|
||||
\section1 Unchecked iteration
|
||||
|
||||
It is possible to optimize iterating over a QString contents by skipping
|
||||
some checks. This is in general not safe to do, because a QString is allowed
|
||||
to contain malformed UTF-16 data; however, if we can trust a given QString,
|
||||
then we can use the optimized \e{unchecked} functions.
|
||||
|
||||
QStringIterator provides the \e{unchecked} counterparts for next(),
|
||||
peekNext(), advance(), previous(), peekPrevious(), and recede():
|
||||
they're called, respectively,
|
||||
nextUnchecked(), peekNextUnchecked(), advanceUnchecked(),
|
||||
previousUnchecked(), peekPreviousUnchecked(), recedeUnchecked().
|
||||
The counterparts work exactly like the original ones,
|
||||
but they're faster as they're allowed to make certain assumptions about
|
||||
the string contents.
|
||||
|
||||
\note please be extremely careful when using QStringIterator's unchecked functions,
|
||||
as using them on a string containing malformed data leads to undefined behavior.
|
||||
|
||||
\sa QString, QChar
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QStringIterator::QStringIterator(const QString &string)
|
||||
|
||||
Constructs an iterator over the contents of \a string. The iterator will point
|
||||
before the first position in the string.
|
||||
|
||||
The string \a string must remain valid while the iterator is being used.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QStringIterator::QStringIterator(const QChar *begin, const QChar *end)
|
||||
|
||||
Constructs an iterator which iterates over the range from \a begin to \a end.
|
||||
The iterator will point before \a begin.
|
||||
|
||||
The range from \a begin to \a end must remain valid while the iterator is being used.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QString::const_iterator QStringIterator::position() const
|
||||
|
||||
Returns the current position of the iterator.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void QStringIterator::setPosition(QString::const_iterator position)
|
||||
|
||||
Sets the iterator's current position to \a position, which must be inside
|
||||
of the iterable range.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn bool QStringIterator::hasNext() const
|
||||
|
||||
Returns true if the iterator has not reached the end of the valid iterable range
|
||||
and therefore can move forward; false otherwise.
|
||||
|
||||
\sa next()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void QStringIterator::advance()
|
||||
|
||||
Advances the iterator by one Unicode code point.
|
||||
|
||||
\note calling this function when the iterator is past the end of the iterable range
|
||||
leads to undefined behavior.
|
||||
|
||||
\sa next(), hasNext()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void QStringIterator::advanceUnchecked()
|
||||
|
||||
Advances the iterator by one Unicode code point.
|
||||
|
||||
\note calling this function when the iterator is past the end of the iterable range
|
||||
or on a QString containing malformed UTF-16 data leads to undefined behavior.
|
||||
|
||||
\sa advance(), next(), hasNext()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn uint QStringIterator::peekNextUnchecked() const
|
||||
|
||||
Returns the Unicode code point that is immediately after the iterator's current
|
||||
position. The current position is not changed.
|
||||
|
||||
\note calling this function when the iterator is past the end of the iterable range
|
||||
or on a QString containing malformed UTF-16 data leads to undefined behavior.
|
||||
|
||||
\sa peekNext(), next(), hasNext()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn uint QStringIterator::peekNext(uint invalidAs = QChar::ReplacementCharacter) const
|
||||
|
||||
Returns the Unicode code point that is immediately after the iterator's current
|
||||
position. The current position is not changed.
|
||||
|
||||
If the iterator is not able to decode the UTF-16 data after the iterator's current
|
||||
position, this function returns \a invalidAs (by default, QChar::ReplacementCharacter,
|
||||
which corresponds to \c{U+FFFD}).
|
||||
|
||||
\note calling this function when the iterator is past the end of the iterable range
|
||||
leads to undefined behavior.
|
||||
|
||||
\sa next(), hasNext()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn uint QStringIterator::nextUnchecked()
|
||||
|
||||
Advances the iterator's current position by one Unicode code point,
|
||||
and returns the Unicode code point that gets pointed by the iterator.
|
||||
|
||||
\note calling this function when the iterator is past the end of the iterable range
|
||||
or on a QString containing malformed UTF-16 data leads to undefined behavior.
|
||||
|
||||
\sa next(), hasNext()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn uint QStringIterator::next(uint invalidAs = QChar::ReplacementCharacter)
|
||||
|
||||
Advances the iterator's current position by one Unicode code point,
|
||||
and returns the Unicode code point that gets pointed by the iterator.
|
||||
|
||||
If the iterator is not able to decode the UTF-16 data at the iterator's current
|
||||
position, this function returns \a invalidAs (by default, QChar::ReplacementCharacter,
|
||||
which corresponds to \c{U+FFFD}).
|
||||
|
||||
\note calling this function when the iterator is past the end of the iterable range
|
||||
leads to undefined behavior.
|
||||
|
||||
\sa peekNext(), hasNext()
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\fn bool QStringIterator::hasPrevious() const
|
||||
|
||||
Returns true if the iterator is after the beginning of the valid iterable range
|
||||
and therefore can move backwards; false otherwise.
|
||||
|
||||
\sa previous()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void QStringIterator::recede()
|
||||
|
||||
Moves the iterator back by one Unicode code point.
|
||||
|
||||
\note calling this function when the iterator is before the beginning of the iterable range
|
||||
leads to undefined behavior.
|
||||
|
||||
\sa previous(), hasPrevious()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void QStringIterator::recedeUnchecked()
|
||||
|
||||
Moves the iterator back by one Unicode code point.
|
||||
|
||||
\note calling this function when the iterator is before the beginning of the iterable range
|
||||
or on a QString containing malformed UTF-16 data leads to undefined behavior.
|
||||
|
||||
\sa recede(), previous(), hasPrevious()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn uint QStringIterator::peekPreviousUnchecked() const
|
||||
|
||||
Returns the Unicode code point that is immediately before the iterator's current
|
||||
position. The current position is not changed.
|
||||
|
||||
\note calling this function when the iterator is before the beginning of the iterable range
|
||||
or on a QString containing malformed UTF-16 data leads to undefined behavior.
|
||||
|
||||
\sa previous(), hasPrevious()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn uint QStringIterator::peekPrevious(uint invalidAs = QChar::ReplacementCharacter) const
|
||||
|
||||
Returns the Unicode code point that is immediately before the iterator's current
|
||||
position. The current position is not changed.
|
||||
|
||||
If the iterator is not able to decode the UTF-16 data before the iterator's current
|
||||
position, this function returns \a invalidAs (by default, QChar::ReplacementCharacter,
|
||||
which corresponds to \c{U+FFFD}).
|
||||
|
||||
\note calling this function when the iterator is before the beginning of the iterable range
|
||||
leads to undefined behavior.
|
||||
|
||||
\sa previous(), hasPrevious()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn uint QStringIterator::previousUnchecked()
|
||||
|
||||
Moves the iterator's current position back by one Unicode code point,
|
||||
and returns the Unicode code point that gets pointed by the iterator.
|
||||
|
||||
\note calling this function when the iterator is before the beginning of the iterable range
|
||||
or on a QString containing malformed UTF-16 data leads to undefined behavior.
|
||||
|
||||
\sa previous(), hasPrevious()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn uint QStringIterator::previous(uint invalidAs = QChar::ReplacementCharacter)
|
||||
|
||||
Moves the iterator's current position back by one Unicode code point,
|
||||
and returns the Unicode code point that gets pointed by the iterator.
|
||||
|
||||
If the iterator is not able to decode the UTF-16 data at the iterator's current
|
||||
position, this function returns \a invalidAs (by default, QChar::ReplacementCharacter,
|
||||
which corresponds to \c{U+FFFD}).
|
||||
|
||||
\note calling this function when the iterator is before the beginning of the iterable range
|
||||
leads to undefined behavior.
|
||||
|
||||
\sa peekPrevious(), hasPrevious()
|
||||
*/
|
||||
|
|
@ -0,0 +1,233 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.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 QSTRINGITERATOR_H
|
||||
#define QSTRINGITERATOR_H
|
||||
|
||||
#include <QtCore/qstring.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QStringIterator
|
||||
{
|
||||
QString::const_iterator i, pos, e;
|
||||
|
||||
public:
|
||||
inline explicit QStringIterator(const QString &string)
|
||||
: i(string.constBegin()),
|
||||
pos(string.constBegin()),
|
||||
e(string.constEnd())
|
||||
{
|
||||
}
|
||||
|
||||
inline explicit QStringIterator(const QChar *begin, const QChar *end)
|
||||
: i(begin),
|
||||
pos(begin),
|
||||
e(end)
|
||||
{
|
||||
}
|
||||
|
||||
inline QString::const_iterator position() const
|
||||
{
|
||||
return pos;
|
||||
}
|
||||
|
||||
inline void setPosition(QString::const_iterator position)
|
||||
{
|
||||
Q_ASSERT_X(i <= position && position <= e, Q_FUNC_INFO, "position out of bounds");
|
||||
pos = position;
|
||||
}
|
||||
|
||||
// forward iteration
|
||||
|
||||
inline bool hasNext() const
|
||||
{
|
||||
return pos < e;
|
||||
}
|
||||
|
||||
inline void advance()
|
||||
{
|
||||
Q_ASSERT_X(hasNext(), Q_FUNC_INFO, "iterator hasn't a next item");
|
||||
|
||||
if (Q_UNLIKELY((pos++)->isHighSurrogate())) {
|
||||
if (Q_LIKELY(pos != e && pos->isLowSurrogate()))
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
|
||||
inline void advanceUnchecked()
|
||||
{
|
||||
Q_ASSERT_X(hasNext(), Q_FUNC_INFO, "iterator hasn't a next item");
|
||||
|
||||
if (Q_UNLIKELY((pos++)->isHighSurrogate()))
|
||||
++pos;
|
||||
}
|
||||
|
||||
inline uint peekNextUnchecked() const
|
||||
{
|
||||
Q_ASSERT_X(hasNext(), Q_FUNC_INFO, "iterator hasn't a next item");
|
||||
|
||||
if (Q_UNLIKELY(pos->isHighSurrogate()))
|
||||
return QChar::surrogateToUcs4(pos[0], pos[1]);
|
||||
|
||||
return pos->unicode();
|
||||
}
|
||||
|
||||
inline uint peekNext(uint invalidAs = QChar::ReplacementCharacter) const
|
||||
{
|
||||
Q_ASSERT_X(hasNext(), Q_FUNC_INFO, "iterator hasn't a next item");
|
||||
|
||||
if (Q_UNLIKELY(pos->isSurrogate())) {
|
||||
if (Q_LIKELY(pos->isHighSurrogate())) {
|
||||
const QChar *low = pos + 1;
|
||||
if (Q_LIKELY(low != e && low->isLowSurrogate()))
|
||||
return QChar::surrogateToUcs4(*pos, *low);
|
||||
}
|
||||
return invalidAs;
|
||||
}
|
||||
|
||||
return pos->unicode();
|
||||
}
|
||||
|
||||
inline uint nextUnchecked()
|
||||
{
|
||||
Q_ASSERT_X(hasNext(), Q_FUNC_INFO, "iterator hasn't a next item");
|
||||
|
||||
const QChar cur = *pos++;
|
||||
if (Q_UNLIKELY(cur.isHighSurrogate()))
|
||||
return QChar::surrogateToUcs4(cur, *pos++);
|
||||
return cur.unicode();
|
||||
}
|
||||
|
||||
inline uint next(uint invalidAs = QChar::ReplacementCharacter)
|
||||
{
|
||||
Q_ASSERT_X(hasNext(), Q_FUNC_INFO, "iterator hasn't a next item");
|
||||
|
||||
const QChar uc = *pos++;
|
||||
if (Q_UNLIKELY(uc.isSurrogate())) {
|
||||
if (Q_LIKELY(uc.isHighSurrogate() && pos < e && pos->isLowSurrogate()))
|
||||
return QChar::surrogateToUcs4(uc, *pos++);
|
||||
return invalidAs;
|
||||
}
|
||||
|
||||
return uc.unicode();
|
||||
}
|
||||
|
||||
// backwards iteration
|
||||
|
||||
inline bool hasPrevious() const
|
||||
{
|
||||
return pos > i;
|
||||
}
|
||||
|
||||
inline void recede()
|
||||
{
|
||||
Q_ASSERT_X(hasPrevious(), Q_FUNC_INFO, "iterator hasn't a previous item");
|
||||
|
||||
if (Q_UNLIKELY((--pos)->isLowSurrogate())) {
|
||||
const QChar *high = pos - 1;
|
||||
if (Q_LIKELY(high != i - 1 && high->isHighSurrogate()))
|
||||
--pos;
|
||||
}
|
||||
}
|
||||
|
||||
inline void recedeUnchecked()
|
||||
{
|
||||
Q_ASSERT_X(hasPrevious(), Q_FUNC_INFO, "iterator hasn't a previous item");
|
||||
|
||||
if (Q_UNLIKELY((--pos)->isLowSurrogate()))
|
||||
--pos;
|
||||
}
|
||||
|
||||
inline uint peekPreviousUnchecked() const
|
||||
{
|
||||
Q_ASSERT_X(hasPrevious(), Q_FUNC_INFO, "iterator hasn't a previous item");
|
||||
|
||||
if (Q_UNLIKELY(pos[-1].isLowSurrogate()))
|
||||
return QChar::surrogateToUcs4(pos[-2], pos[-1]);
|
||||
return pos[-1].unicode();
|
||||
}
|
||||
|
||||
inline uint peekPrevious(uint invalidAs = QChar::ReplacementCharacter) const
|
||||
{
|
||||
Q_ASSERT_X(hasPrevious(), Q_FUNC_INFO, "iterator hasn't a previous item");
|
||||
|
||||
if (Q_UNLIKELY(pos[-1].isSurrogate())) {
|
||||
if (Q_LIKELY(pos[-1].isLowSurrogate())) {
|
||||
const QChar *high = pos - 2;
|
||||
if (Q_LIKELY(high != i - 1 && high->isHighSurrogate()))
|
||||
return QChar::surrogateToUcs4(*high, pos[-1]);
|
||||
}
|
||||
return invalidAs;
|
||||
}
|
||||
|
||||
return pos[-1].unicode();
|
||||
}
|
||||
|
||||
inline uint previousUnchecked()
|
||||
{
|
||||
Q_ASSERT_X(hasPrevious(), Q_FUNC_INFO, "iterator hasn't a previous item");
|
||||
|
||||
const QChar cur = *--pos;
|
||||
if (Q_UNLIKELY(cur.isLowSurrogate()))
|
||||
return QChar::surrogateToUcs4(*--pos, cur);
|
||||
return cur.unicode();
|
||||
}
|
||||
|
||||
inline uint previous(uint invalidAs = QChar::ReplacementCharacter)
|
||||
{
|
||||
Q_ASSERT_X(hasPrevious(), Q_FUNC_INFO, "iterator hasn't a previous item");
|
||||
|
||||
const QChar uc = *--pos;
|
||||
if (Q_UNLIKELY(uc.isSurrogate())) {
|
||||
if (Q_LIKELY(uc.isLowSurrogate() && pos > i && pos[-1].isHighSurrogate()))
|
||||
return QChar::surrogateToUcs4(*--pos, uc);
|
||||
return invalidAs;
|
||||
}
|
||||
|
||||
return uc.unicode();
|
||||
}
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QSTRINGITERATOR_H
|
||||
|
|
@ -56,6 +56,7 @@ HEADERS += \
|
|||
tools/qstack.h \
|
||||
tools/qstring.h \
|
||||
tools/qstringbuilder.h \
|
||||
tools/qstringiterator_p.h \
|
||||
tools/qstringlist.h \
|
||||
tools/qstringmatcher.h \
|
||||
tools/qtextboundaryfinder.h \
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
CONFIG += testcase parallel_test
|
||||
TARGET = tst_qstringiterator
|
||||
QT = core core-private testlib
|
||||
SOURCES = tst_qstringiterator.cpp
|
||||
|
||||
|
|
@ -0,0 +1,675 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.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 <QtTest/QtTest>
|
||||
#include <QtCore/QString>
|
||||
#include <private/qstringiterator_p.h>
|
||||
|
||||
class tst_QStringIterator : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
private slots:
|
||||
void sweep_data();
|
||||
void sweep();
|
||||
|
||||
void position();
|
||||
};
|
||||
|
||||
void tst_QStringIterator::sweep_data()
|
||||
{
|
||||
QTest::addColumn<QString>("string");
|
||||
QTest::addColumn<bool>("valid");
|
||||
QTest::addColumn<int>("count");
|
||||
|
||||
QTest::newRow("sweep_00") << QString::fromUtf8("", 0) << true << 0;
|
||||
QTest::newRow("sweep_01") << QString::fromUtf8("a", 1) << true << 1;
|
||||
QTest::newRow("sweep_02") << QString::fromUtf8("a string", 8) << true << 8;
|
||||
QTest::newRow("sweep_03") << QString::fromUtf8("\xc3\xa0\xc3\xa8\xc3\xac\xc3\xb2\xc3\xb9", 10) << true << 5;
|
||||
QTest::newRow("sweep_04") << QString::fromUtf8("\xc3\x9f\xe2\x80\x94\xc2\xa1", 7) << true << 3;
|
||||
QTest::newRow("sweep_05") << QString::fromUtf8("\xe6\xb0\xb4\xe6\xb0\xb5\xe6\xb0\xb6\xe6\xb0\xb7\xe6\xb0\xb8\xe6\xb0\xb9", 18) << true << 6;
|
||||
QTest::newRow("sweep_06") << QString::fromUtf8("\xf0\x9f\x98\x81\xf0\x9f\x98\x82\x61\x62\x63\xf0\x9f\x98\x83\xc4\x91\xc3\xa8\xef\xac\x80\xf0\x9f\x98\x84\xf0\x9f\x98\x85", 30) << true << 11;
|
||||
QTest::newRow("sweep_07") << QString::fromUtf8("\xf0\x9f\x82\xaa\xf0\x9f\x82\xab\xf0\x9f\x82\xad\xf0\x9f\x82\xae\xf0\x9f\x82\xa1\x20\x52\x4f\x59\x41\x4c\x20\x46\x4c\x55\x53\x48\x20\x4f\x46\x20\x53\x50\x41\x44\x45\x53", 42) << true << 27;
|
||||
QTest::newRow("sweep_08") << QString::fromUtf8("abc\0def", 7) << true << 7;
|
||||
QTest::newRow("sweep_09") << QString::fromUtf8("\xc3\xa0\xce\xb2\xc3\xa7\xf0\x9f\x80\xb9\xf0\x9f\x80\xb8\x00\xf0\x9f\x80\xb1\x00\xf0\x9f\x80\xb3\xf0\x9f\x81\x85\xe1\xb8\x8a\xc4\x99\xc6\x92", 35) << true << 13;
|
||||
|
||||
QTest::newRow("sweep_invalid_00") << QString(QChar(0xd800)) << false << 1;
|
||||
QTest::newRow("sweep_invalid_01") << QString(QChar(0xdc00)) << false << 1;
|
||||
QTest::newRow("sweep_invalid_02") << QString(QChar(0xdbff)) << false << 1;
|
||||
QTest::newRow("sweep_invalid_03") << QString(QChar(0xdfff)) << false << 1;
|
||||
|
||||
#define QSTRING_FROM_QCHARARRAY(x) (QString((x), sizeof(x)/sizeof((x)[0])))
|
||||
|
||||
static const QChar invalid_04[] = {
|
||||
QLatin1Char('i'), QLatin1Char('n'), QLatin1Char('v'),
|
||||
QLatin1Char('a'), QLatin1Char('l'), QLatin1Char('i'),
|
||||
QLatin1Char('d'), QChar(0xd800)
|
||||
};
|
||||
QTest::newRow("sweep_invalid_04") << QSTRING_FROM_QCHARARRAY(invalid_04) << false << 8;
|
||||
|
||||
static const QChar invalid_05[] = {
|
||||
QLatin1Char('i'), QLatin1Char('n'), QLatin1Char('v'),
|
||||
QLatin1Char('a'), QLatin1Char('l'), QLatin1Char('i'),
|
||||
QLatin1Char('d'), QChar(0xd800), QLatin1Char('x')
|
||||
};
|
||||
QTest::newRow("sweep_invalid_05") << QSTRING_FROM_QCHARARRAY(invalid_05) << false << 9;
|
||||
|
||||
static const QChar invalid_06[] = {
|
||||
QLatin1Char('i'), QLatin1Char('n'), QLatin1Char('v'),
|
||||
QLatin1Char('a'), QLatin1Char('l'), QLatin1Char('i'),
|
||||
QLatin1Char('d'), QChar(0xdc00)
|
||||
};
|
||||
QTest::newRow("sweep_invalid_06") << QSTRING_FROM_QCHARARRAY(invalid_06) << false << 8;
|
||||
|
||||
static const QChar invalid_07[] = {
|
||||
QLatin1Char('i'), QLatin1Char('n'), QLatin1Char('v'),
|
||||
QLatin1Char('a'), QLatin1Char('l'), QLatin1Char('i'),
|
||||
QLatin1Char('d'), QChar(0xdc00), QLatin1Char('x')
|
||||
};
|
||||
QTest::newRow("sweep_invalid_07") << QSTRING_FROM_QCHARARRAY(invalid_07) << false << 9;
|
||||
|
||||
static const QChar invalid_08[] = {
|
||||
QChar(0xd800),
|
||||
QLatin1Char('i'), QLatin1Char('n'), QLatin1Char('v'),
|
||||
QLatin1Char('a'), QLatin1Char('l'), QLatin1Char('i'),
|
||||
QLatin1Char('d')
|
||||
};
|
||||
QTest::newRow("sweep_invalid_08") << QSTRING_FROM_QCHARARRAY(invalid_08) << false << 8;
|
||||
|
||||
static const QChar invalid_09[] = {
|
||||
QChar(0xdc00),
|
||||
QLatin1Char('i'), QLatin1Char('n'), QLatin1Char('v'),
|
||||
QLatin1Char('a'), QLatin1Char('l'), QLatin1Char('i'),
|
||||
QLatin1Char('d')
|
||||
};
|
||||
QTest::newRow("sweep_invalid_09") << QSTRING_FROM_QCHARARRAY(invalid_09) << false << 8;
|
||||
|
||||
static const QChar invalid_10[] = {
|
||||
QChar(0xd800), QChar(0xd800),
|
||||
QLatin1Char('i'), QLatin1Char('n'), QLatin1Char('v'),
|
||||
QLatin1Char('a'), QLatin1Char('l'), QLatin1Char('i'),
|
||||
QLatin1Char('d')
|
||||
};
|
||||
QTest::newRow("sweep_invalid_10") << QSTRING_FROM_QCHARARRAY(invalid_10) << false << 9;
|
||||
|
||||
static const QChar invalid_11[] = {
|
||||
QChar(0xdc00), QChar(0xd800),
|
||||
QLatin1Char('i'), QLatin1Char('n'), QLatin1Char('v'),
|
||||
QLatin1Char('a'), QLatin1Char('l'), QLatin1Char('i'),
|
||||
QLatin1Char('d')
|
||||
};
|
||||
QTest::newRow("sweep_invalid_11") << QSTRING_FROM_QCHARARRAY(invalid_11) << false << 9;
|
||||
|
||||
static const QChar invalid_12[] = {
|
||||
QChar(0xdc00), QChar(0xdc00),
|
||||
QLatin1Char('i'), QLatin1Char('n'), QLatin1Char('v'),
|
||||
QLatin1Char('a'), QLatin1Char('l'), QLatin1Char('i'),
|
||||
QLatin1Char('d')
|
||||
};
|
||||
QTest::newRow("sweep_invalid_12") << QSTRING_FROM_QCHARARRAY(invalid_12) << false << 9;
|
||||
|
||||
static const QChar invalid_13[] = {
|
||||
QLatin1Char('i'), QLatin1Char('n'), QLatin1Char('v'),
|
||||
QChar(0xd800), QChar(0xdf00), // U+10300 OLD ITALIC LETTER A
|
||||
QLatin1Char('a'), QLatin1Char('l'), QLatin1Char('i'),
|
||||
QLatin1Char('d'), QChar(0xd800)
|
||||
};
|
||||
QTest::newRow("sweep_invalid_13") << QSTRING_FROM_QCHARARRAY(invalid_13) << false << 9;
|
||||
|
||||
static const QChar invalid_14[] = {
|
||||
QLatin1Char('i'), QLatin1Char('n'), QLatin1Char('v'),
|
||||
QChar(0xd800), QChar(0xdf00), // U+10300 OLD ITALIC LETTER A
|
||||
QLatin1Char('a'), QLatin1Char('l'), QLatin1Char('i'),
|
||||
QLatin1Char('d'), QChar(0xd800), QLatin1Char('x')
|
||||
};
|
||||
QTest::newRow("sweep_invalid_14") << QSTRING_FROM_QCHARARRAY(invalid_14) << false << 10;
|
||||
|
||||
static const QChar invalid_15[] = {
|
||||
QLatin1Char('i'), QLatin1Char('n'), QLatin1Char('v'),
|
||||
QChar(0xd800), QChar(0xdf00), // U+10300 OLD ITALIC LETTER A
|
||||
QLatin1Char('a'), QLatin1Char('l'), QLatin1Char('i'),
|
||||
QLatin1Char('d'), QChar(0xdc00)
|
||||
};
|
||||
QTest::newRow("sweep_invalid_15") << QSTRING_FROM_QCHARARRAY(invalid_15) << false << 9;
|
||||
|
||||
static const QChar invalid_16[] = {
|
||||
QLatin1Char('i'), QLatin1Char('n'), QLatin1Char('v'),
|
||||
QChar(0xd800), QChar(0xdf00), // U+10300 OLD ITALIC LETTER A
|
||||
QLatin1Char('a'), QLatin1Char('l'), QLatin1Char('i'),
|
||||
QLatin1Char('d'), QChar(0xdc00), QLatin1Char('x')
|
||||
};
|
||||
QTest::newRow("sweep_invalid_16") << QSTRING_FROM_QCHARARRAY(invalid_16) << false << 10;
|
||||
|
||||
static const QChar invalid_17[] = {
|
||||
QChar(0xd800),
|
||||
QLatin1Char('i'), QLatin1Char('n'), QLatin1Char('v'),
|
||||
QChar(0xd800), QChar(0xdf00), // U+10300 OLD ITALIC LETTER A
|
||||
QLatin1Char('a'), QLatin1Char('l'), QLatin1Char('i'),
|
||||
QLatin1Char('d')
|
||||
};
|
||||
QTest::newRow("sweep_invalid_17") << QSTRING_FROM_QCHARARRAY(invalid_17) << false << 9;
|
||||
|
||||
static const QChar invalid_18[] = {
|
||||
QChar(0xdc00),
|
||||
QLatin1Char('i'), QLatin1Char('n'), QLatin1Char('v'),
|
||||
QChar(0xd800), QChar(0xdf00), // U+10300 OLD ITALIC LETTER A
|
||||
QLatin1Char('a'), QLatin1Char('l'), QLatin1Char('i'),
|
||||
QLatin1Char('d')
|
||||
};
|
||||
QTest::newRow("sweep_invalid_18") << QSTRING_FROM_QCHARARRAY(invalid_18) << false << 9;
|
||||
|
||||
#undef QSTRING_FROM_QCHARARRAY
|
||||
}
|
||||
|
||||
void tst_QStringIterator::sweep()
|
||||
{
|
||||
QFETCH(QString, string);
|
||||
QFETCH(bool, valid);
|
||||
|
||||
QStringIterator i(string);
|
||||
int count = 0;
|
||||
QString rebuiltString;
|
||||
|
||||
while (i.hasNext()) {
|
||||
const uint peekedCodePoint = i.peekNext(~0u);
|
||||
const uint codePoint = i.next(~0u);
|
||||
|
||||
QVERIFY(peekedCodePoint == codePoint);
|
||||
|
||||
if (codePoint == ~0u)
|
||||
rebuiltString += *(i.position() - 1);
|
||||
else
|
||||
rebuiltString += QString::fromUcs4(&codePoint, 1);
|
||||
|
||||
++count;
|
||||
}
|
||||
|
||||
QTEST(count, "count");
|
||||
QTEST(rebuiltString, "string");
|
||||
rebuiltString.clear();
|
||||
|
||||
while (i.hasPrevious()) {
|
||||
const uint peekedCodePoint = i.peekPrevious(~0u);
|
||||
const uint codePoint = i.previous(~0u);
|
||||
|
||||
QVERIFY(peekedCodePoint == codePoint);
|
||||
|
||||
--count;
|
||||
}
|
||||
|
||||
QCOMPARE(count, 0);
|
||||
|
||||
while (i.hasNext()) {
|
||||
i.advance();
|
||||
++count;
|
||||
}
|
||||
|
||||
QTEST(count, "count");
|
||||
|
||||
while (i.hasPrevious()) {
|
||||
i.recede();
|
||||
--count;
|
||||
}
|
||||
|
||||
QCOMPARE(count, 0);
|
||||
|
||||
if (valid) {
|
||||
while (i.hasNext()) {
|
||||
const uint peekedCodePoint = i.peekNextUnchecked();
|
||||
const uint codePoint = i.nextUnchecked();
|
||||
|
||||
QVERIFY(peekedCodePoint == codePoint);
|
||||
QVERIFY(codePoint <= 0x10FFFFu);
|
||||
rebuiltString += QString::fromUcs4(&codePoint, 1);
|
||||
++count;
|
||||
}
|
||||
|
||||
QTEST(count, "count");
|
||||
QTEST(rebuiltString, "string");
|
||||
|
||||
while (i.hasPrevious()) {
|
||||
const uint peekedCodePoint = i.peekPreviousUnchecked();
|
||||
const uint codePoint = i.previousUnchecked();
|
||||
|
||||
QVERIFY(peekedCodePoint == codePoint);
|
||||
|
||||
--count;
|
||||
}
|
||||
|
||||
QCOMPARE(count, 0);
|
||||
|
||||
while (i.hasNext()) {
|
||||
i.advanceUnchecked();
|
||||
++count;
|
||||
}
|
||||
|
||||
QTEST(count, "count");
|
||||
|
||||
while (i.hasPrevious()) {
|
||||
i.recedeUnchecked();
|
||||
--count;
|
||||
}
|
||||
|
||||
QCOMPARE(count, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QStringIterator::position()
|
||||
{
|
||||
static const QChar stringData[] =
|
||||
{
|
||||
// codeunit count: 0
|
||||
QLatin1Char('a'), QLatin1Char('b'), QLatin1Char('c'),
|
||||
// codeunit count: 3
|
||||
QChar(0x00A9), // U+00A9 COPYRIGHT SIGN
|
||||
// codeunit count: 4
|
||||
QChar(0x00AE), // U+00AE REGISTERED SIGN
|
||||
// codeunit count: 5
|
||||
QLatin1Char('d'), QLatin1Char('e'), QLatin1Char('f'),
|
||||
// codeunit count: 8
|
||||
QLatin1Char('\0'),
|
||||
// codeunit count: 9
|
||||
QLatin1Char('g'), QLatin1Char('h'), QLatin1Char('i'),
|
||||
// codeunit count: 12
|
||||
QChar(0xD834), QChar(0xDD1E), // U+1D11E MUSICAL SYMBOL G CLEF
|
||||
// codeunit count: 14
|
||||
QChar(0xD834), QChar(0xDD21), // U+1D121 MUSICAL SYMBOL C CLEF
|
||||
// codeunit count: 16
|
||||
QLatin1Char('j'),
|
||||
// codeunit count: 17
|
||||
QChar(0xD800), // stray high surrogate
|
||||
// codeunit count: 18
|
||||
QLatin1Char('k'),
|
||||
// codeunit count: 19
|
||||
QChar(0xDC00), // stray low surrogate
|
||||
// codeunit count: 20
|
||||
QLatin1Char('l'),
|
||||
// codeunit count: 21
|
||||
QChar(0xD800), QChar(0xD800), // two high surrogates
|
||||
// codeunit count: 23
|
||||
QLatin1Char('m'),
|
||||
// codeunit count: 24
|
||||
QChar(0xDC00), QChar(0xDC00), // two low surrogates
|
||||
// codeunit count: 26
|
||||
QLatin1Char('n'),
|
||||
// codeunit count: 27
|
||||
QChar(0xD800), QChar(0xD800), QChar(0xDC00), // stray high surrogate followed by valid pair
|
||||
// codeunit count: 30
|
||||
QLatin1Char('o'),
|
||||
// codeunit count: 31
|
||||
QChar(0xDC00), QChar(0xD800), QChar(0xDC00), // stray low surrogate followed by valid pair
|
||||
// codeunit count: 34
|
||||
QLatin1Char('p')
|
||||
// codeunit count: 35
|
||||
};
|
||||
|
||||
const QString string(stringData, sizeof(stringData) / sizeof(stringData[0]));
|
||||
QStringIterator i(string);
|
||||
|
||||
QCOMPARE(i.position(), string.constBegin());
|
||||
QVERIFY(i.hasNext());
|
||||
QVERIFY(!i.hasPrevious());
|
||||
|
||||
i.setPosition(string.constEnd());
|
||||
QCOMPARE(i.position(), string.constEnd());
|
||||
QVERIFY(!i.hasNext());
|
||||
QVERIFY(i.hasPrevious());
|
||||
|
||||
#define QCHAR_UNICODE_VALUE(x) ((uint)(QChar(x).unicode()))
|
||||
|
||||
const QString::const_iterator begin = string.constBegin();
|
||||
i.setPosition(begin);
|
||||
QCOMPARE(i.position(), begin);
|
||||
QCOMPARE(i.peekNext(), QCHAR_UNICODE_VALUE(QLatin1Char('a')));
|
||||
QCOMPARE(i.next(), QCHAR_UNICODE_VALUE(QLatin1Char('a')));
|
||||
|
||||
QCOMPARE(i.position(), begin + 1);
|
||||
|
||||
i.setPosition(begin + 2);
|
||||
QCOMPARE(i.position(), begin + 2);
|
||||
QCOMPARE(i.peekNext(), QCHAR_UNICODE_VALUE(QLatin1Char('c')));
|
||||
QCOMPARE(i.next(), QCHAR_UNICODE_VALUE(QLatin1Char('c')));
|
||||
|
||||
QCOMPARE(i.position(), begin + 3);
|
||||
QCOMPARE(i.peekNext(), QCHAR_UNICODE_VALUE(0x00A9));
|
||||
QCOMPARE(i.next(), QCHAR_UNICODE_VALUE(0x00A9));
|
||||
|
||||
QCOMPARE(i.position(), begin + 4);
|
||||
QCOMPARE(i.peekNext(), QCHAR_UNICODE_VALUE(0x00AE));
|
||||
QCOMPARE(i.next(), QCHAR_UNICODE_VALUE(0x00AE));
|
||||
|
||||
QCOMPARE(i.position(), begin + 5);
|
||||
QCOMPARE(i.peekPrevious(), QCHAR_UNICODE_VALUE(0x00AE));
|
||||
QCOMPARE(i.previous(), QCHAR_UNICODE_VALUE(0x00AE));
|
||||
|
||||
QCOMPARE(i.position(), begin + 4);
|
||||
QCOMPARE(i.peekPrevious(), QCHAR_UNICODE_VALUE(0x00A9));
|
||||
QCOMPARE(i.previous(), QCHAR_UNICODE_VALUE(0x00A9));
|
||||
|
||||
QCOMPARE(i.position(), begin + 3);
|
||||
|
||||
i.setPosition(begin + 8);
|
||||
QCOMPARE(i.position(), begin + 8);
|
||||
QCOMPARE(i.peekNext(), QCHAR_UNICODE_VALUE(QLatin1Char('\0')));
|
||||
QCOMPARE(i.next(), QCHAR_UNICODE_VALUE(QLatin1Char('\0')));
|
||||
|
||||
QCOMPARE(i.position(), begin + 9);
|
||||
QCOMPARE(i.peekNext(), QCHAR_UNICODE_VALUE(QLatin1Char('g')));
|
||||
QCOMPARE(i.next(), QCHAR_UNICODE_VALUE(QLatin1Char('g')));
|
||||
|
||||
QCOMPARE(i.position(), begin + 10);
|
||||
QCOMPARE(i.peekPrevious(), QCHAR_UNICODE_VALUE(QLatin1Char('g')));
|
||||
QCOMPARE(i.previous(), QCHAR_UNICODE_VALUE(QLatin1Char('g')));
|
||||
|
||||
QCOMPARE(i.position(), begin + 9);
|
||||
QCOMPARE(i.peekPrevious(), QCHAR_UNICODE_VALUE(QLatin1Char('\0')));
|
||||
QCOMPARE(i.previous(), QCHAR_UNICODE_VALUE(QLatin1Char('\0')));
|
||||
|
||||
QCOMPARE(i.position(), begin + 8);
|
||||
QCOMPARE(i.peekPrevious(), QCHAR_UNICODE_VALUE(QLatin1Char('f')));
|
||||
QCOMPARE(i.previous(), QCHAR_UNICODE_VALUE(QLatin1Char('f')));
|
||||
|
||||
QCOMPARE(i.position(), begin + 7);
|
||||
|
||||
i.advanceUnchecked();
|
||||
i.advanceUnchecked();
|
||||
i.advanceUnchecked();
|
||||
i.advanceUnchecked();
|
||||
i.advanceUnchecked();
|
||||
|
||||
QCOMPARE(i.position(), begin + 12);
|
||||
QCOMPARE(i.peekNext(), 0x1D11Eu);
|
||||
QCOMPARE(i.next(), 0x1D11Eu);
|
||||
|
||||
QCOMPARE(i.position(), begin + 14);
|
||||
QCOMPARE(i.peekNext(), 0x1D121u);
|
||||
QCOMPARE(i.next(), 0x1D121u);
|
||||
|
||||
QCOMPARE(i.position(), begin + 16);
|
||||
QCOMPARE(i.peekNext(), QCHAR_UNICODE_VALUE(QLatin1Char('j')));
|
||||
QCOMPARE(i.next(), QCHAR_UNICODE_VALUE(QLatin1Char('j')));
|
||||
|
||||
QCOMPARE(i.position(), begin + 17);
|
||||
QCOMPARE(i.peekPrevious(), QCHAR_UNICODE_VALUE(QLatin1Char('j')));
|
||||
QCOMPARE(i.previous(), QCHAR_UNICODE_VALUE(QLatin1Char('j')));
|
||||
|
||||
QCOMPARE(i.position(), begin + 16);
|
||||
QCOMPARE(i.peekPrevious(), 0x1D121u);
|
||||
QCOMPARE(i.previous(), 0x1D121u);
|
||||
|
||||
QCOMPARE(i.position(), begin + 14);
|
||||
QCOMPARE(i.peekPrevious(), 0x1D11Eu);
|
||||
QCOMPARE(i.previous(), 0x1D11Eu);
|
||||
|
||||
QCOMPARE(i.position(), begin + 12);
|
||||
|
||||
|
||||
i.setPosition(begin + 13);
|
||||
QCOMPARE(i.position(), begin + 13);
|
||||
|
||||
QCOMPARE(i.peekNext(), 0xFFFDu);
|
||||
QCOMPARE(i.next(), 0xFFFDu);
|
||||
|
||||
QCOMPARE(i.position(), begin + 14);
|
||||
QCOMPARE(i.peekNext(), 0x1D121u);
|
||||
QCOMPARE(i.next(), 0x1D121u);
|
||||
|
||||
QCOMPARE(i.position(), begin + 16);
|
||||
|
||||
|
||||
i.setPosition(begin + 15);
|
||||
QCOMPARE(i.position(), begin + 15);
|
||||
|
||||
QCOMPARE(i.peekPrevious(), 0xFFFDu);
|
||||
QCOMPARE(i.previous(), 0xFFFDu);
|
||||
|
||||
QCOMPARE(i.position(), begin + 14);
|
||||
QCOMPARE(i.peekPrevious(), 0x1D11Eu);
|
||||
QCOMPARE(i.previous(), 0x1D11Eu);
|
||||
|
||||
QCOMPARE(i.position(), begin + 12);
|
||||
|
||||
i.advanceUnchecked();
|
||||
i.advanceUnchecked();
|
||||
|
||||
QCOMPARE(i.position(), begin + 16);
|
||||
QCOMPARE(i.peekNext(), QCHAR_UNICODE_VALUE(QLatin1Char('j')));
|
||||
QCOMPARE(i.next(), QCHAR_UNICODE_VALUE(QLatin1Char('j')));
|
||||
|
||||
QCOMPARE(i.position(), begin + 17);
|
||||
QCOMPARE(i.peekNext(), 0xFFFDu);
|
||||
QCOMPARE(i.next(), 0xFFFDu);
|
||||
|
||||
QCOMPARE(i.position(), begin + 18);
|
||||
QCOMPARE(i.peekNext(), QCHAR_UNICODE_VALUE(QLatin1Char('k')));
|
||||
QCOMPARE(i.next(), QCHAR_UNICODE_VALUE(QLatin1Char('k')));
|
||||
|
||||
QCOMPARE(i.position(), begin + 19);
|
||||
QCOMPARE(i.peekNext(), 0xFFFDu);
|
||||
QCOMPARE(i.next(), 0xFFFDu);
|
||||
|
||||
QCOMPARE(i.position(), begin + 20);
|
||||
QCOMPARE(i.peekNext(), QCHAR_UNICODE_VALUE(QLatin1Char('l')));
|
||||
QCOMPARE(i.next(), QCHAR_UNICODE_VALUE(QLatin1Char('l')));
|
||||
|
||||
QCOMPARE(i.position(), begin + 21);
|
||||
QCOMPARE(i.peekNext(), 0xFFFDu);
|
||||
QCOMPARE(i.next(), 0xFFFDu);
|
||||
|
||||
QCOMPARE(i.position(), begin + 22);
|
||||
QCOMPARE(i.peekNext(), 0xFFFDu);
|
||||
QCOMPARE(i.next(), 0xFFFDu);
|
||||
|
||||
QCOMPARE(i.position(), begin + 23);
|
||||
QCOMPARE(i.peekNext(), QCHAR_UNICODE_VALUE(QLatin1Char('m')));
|
||||
QCOMPARE(i.next(), QCHAR_UNICODE_VALUE(QLatin1Char('m')));
|
||||
|
||||
QCOMPARE(i.position(), begin + 24);
|
||||
QCOMPARE(i.peekNext(), 0xFFFDu);
|
||||
QCOMPARE(i.next(), 0xFFFDu);
|
||||
|
||||
QCOMPARE(i.position(), begin + 25);
|
||||
QCOMPARE(i.peekNext(), 0xFFFDu);
|
||||
QCOMPARE(i.next(), 0xFFFDu);
|
||||
|
||||
QCOMPARE(i.position(), begin + 26);
|
||||
QCOMPARE(i.peekNext(), QCHAR_UNICODE_VALUE(QLatin1Char('n')));
|
||||
QCOMPARE(i.next(), QCHAR_UNICODE_VALUE(QLatin1Char('n')));
|
||||
|
||||
QCOMPARE(i.position(), begin + 27);
|
||||
QCOMPARE(i.peekNext(), 0xFFFDu);
|
||||
QCOMPARE(i.next(), 0xFFFDu);
|
||||
|
||||
QCOMPARE(i.position(), begin + 28);
|
||||
QCOMPARE(i.peekNext(), 0x10000u);
|
||||
QCOMPARE(i.next(), 0x10000u);
|
||||
|
||||
QCOMPARE(i.position(), begin + 30);
|
||||
QCOMPARE(i.peekNext(), QCHAR_UNICODE_VALUE(QLatin1Char('o')));
|
||||
QCOMPARE(i.next(), QCHAR_UNICODE_VALUE(QLatin1Char('o')));
|
||||
|
||||
QCOMPARE(i.position(), begin + 31);
|
||||
QCOMPARE(i.peekNext(), 0xFFFDu);
|
||||
QCOMPARE(i.next(), 0xFFFDu);
|
||||
|
||||
QCOMPARE(i.position(), begin + 32);
|
||||
QCOMPARE(i.peekNext(), 0x10000u);
|
||||
QCOMPARE(i.next(), 0x10000u);
|
||||
|
||||
QCOMPARE(i.position(), begin + 34);
|
||||
QCOMPARE(i.peekNext(), QCHAR_UNICODE_VALUE(QLatin1Char('p')));
|
||||
QCOMPARE(i.next(), QCHAR_UNICODE_VALUE(QLatin1Char('p')));
|
||||
|
||||
QVERIFY(!i.hasNext());
|
||||
|
||||
QCOMPARE(i.position(), begin + 35);
|
||||
QCOMPARE(i.peekPrevious(), QCHAR_UNICODE_VALUE(QLatin1Char('p')));
|
||||
QCOMPARE(i.previous(), QCHAR_UNICODE_VALUE(QLatin1Char('p')));
|
||||
|
||||
QCOMPARE(i.position(), begin + 34);
|
||||
QCOMPARE(i.peekPrevious(), 0x10000u);
|
||||
QCOMPARE(i.previous(), 0x10000u);
|
||||
|
||||
QCOMPARE(i.position(), begin + 32);
|
||||
QCOMPARE(i.peekPrevious(), 0xFFFDu);
|
||||
QCOMPARE(i.previous(), 0xFFFDu);
|
||||
|
||||
QCOMPARE(i.position(), begin + 31);
|
||||
QCOMPARE(i.peekPrevious(), QCHAR_UNICODE_VALUE(QLatin1Char('o')));
|
||||
QCOMPARE(i.previous(), QCHAR_UNICODE_VALUE(QLatin1Char('o')));
|
||||
|
||||
QCOMPARE(i.position(), begin + 30);
|
||||
QCOMPARE(i.peekPrevious(), 0x10000u);
|
||||
QCOMPARE(i.previous(), 0x10000u);
|
||||
|
||||
QCOMPARE(i.position(), begin + 28);
|
||||
QCOMPARE(i.peekPrevious(), 0xFFFDu);
|
||||
QCOMPARE(i.previous(), 0xFFFDu);
|
||||
|
||||
QCOMPARE(i.position(), begin + 27);
|
||||
QCOMPARE(i.peekPrevious(), QCHAR_UNICODE_VALUE(QLatin1Char('n')));
|
||||
QCOMPARE(i.previous(), QCHAR_UNICODE_VALUE(QLatin1Char('n')));
|
||||
|
||||
QCOMPARE(i.position(), begin + 26);
|
||||
QCOMPARE(i.peekPrevious(), 0xFFFDu);
|
||||
QCOMPARE(i.previous(), 0xFFFDu);
|
||||
|
||||
QCOMPARE(i.position(), begin + 25);
|
||||
QCOMPARE(i.peekPrevious(), 0xFFFDu);
|
||||
QCOMPARE(i.previous(), 0xFFFDu);
|
||||
|
||||
QCOMPARE(i.position(), begin + 24);
|
||||
QCOMPARE(i.peekPrevious(), QCHAR_UNICODE_VALUE(QLatin1Char('m')));
|
||||
QCOMPARE(i.previous(), QCHAR_UNICODE_VALUE(QLatin1Char('m')));
|
||||
|
||||
QCOMPARE(i.position(), begin + 23);
|
||||
QCOMPARE(i.peekPrevious(), 0xFFFDu);
|
||||
QCOMPARE(i.previous(), 0xFFFDu);
|
||||
|
||||
QCOMPARE(i.position(), begin + 22);
|
||||
QCOMPARE(i.peekPrevious(), 0xFFFDu);
|
||||
QCOMPARE(i.previous(), 0xFFFDu);
|
||||
|
||||
QCOMPARE(i.position(), begin + 21);
|
||||
QCOMPARE(i.peekPrevious(), QCHAR_UNICODE_VALUE(QLatin1Char('l')));
|
||||
QCOMPARE(i.previous(), QCHAR_UNICODE_VALUE(QLatin1Char('l')));
|
||||
|
||||
QCOMPARE(i.position(), begin + 20);
|
||||
QCOMPARE(i.peekPrevious(), 0xFFFDu);
|
||||
QCOMPARE(i.previous(), 0xFFFDu);
|
||||
|
||||
QCOMPARE(i.position(), begin + 19);
|
||||
QCOMPARE(i.peekPrevious(), QCHAR_UNICODE_VALUE(QLatin1Char('k')));
|
||||
QCOMPARE(i.previous(), QCHAR_UNICODE_VALUE(QLatin1Char('k')));
|
||||
|
||||
QCOMPARE(i.position(), begin + 18);
|
||||
QCOMPARE(i.peekPrevious(), 0xFFFDu);
|
||||
QCOMPARE(i.previous(), 0xFFFDu);
|
||||
|
||||
QCOMPARE(i.position(), begin + 17);
|
||||
QCOMPARE(i.peekPrevious(), QCHAR_UNICODE_VALUE(QLatin1Char('j')));
|
||||
QCOMPARE(i.previous(), QCHAR_UNICODE_VALUE(QLatin1Char('j')));
|
||||
|
||||
i.setPosition(begin + 29);
|
||||
QCOMPARE(i.position(), begin + 29);
|
||||
QCOMPARE(i.peekNext(), 0xFFFDu);
|
||||
QCOMPARE(i.next(), 0xFFFDu);
|
||||
|
||||
QCOMPARE(i.position(), begin + 30);
|
||||
QCOMPARE(i.peekNext(), QCHAR_UNICODE_VALUE(QLatin1Char('o')));
|
||||
QCOMPARE(i.next(), QCHAR_UNICODE_VALUE(QLatin1Char('o')));
|
||||
|
||||
QCOMPARE(i.position(), begin + 31);
|
||||
QCOMPARE(i.peekPrevious(), QCHAR_UNICODE_VALUE(QLatin1Char('o')));
|
||||
QCOMPARE(i.previous(), QCHAR_UNICODE_VALUE(QLatin1Char('o')));
|
||||
|
||||
QCOMPARE(i.position(), begin + 30);
|
||||
QCOMPARE(i.peekPrevious(), 0x10000u);
|
||||
QCOMPARE(i.previous(), 0x10000u);
|
||||
|
||||
QCOMPARE(i.position(), begin + 28);
|
||||
|
||||
i.setPosition(begin + 33);
|
||||
QCOMPARE(i.position(), begin + 33);
|
||||
QCOMPARE(i.peekNext(), 0xFFFDu);
|
||||
QCOMPARE(i.next(), 0xFFFDu);
|
||||
|
||||
QCOMPARE(i.position(), begin + 34);
|
||||
QCOMPARE(i.peekNext(), QCHAR_UNICODE_VALUE(QLatin1Char('p')));
|
||||
QCOMPARE(i.next(), QCHAR_UNICODE_VALUE(QLatin1Char('p')));
|
||||
|
||||
QCOMPARE(i.position(), begin + 35);
|
||||
QCOMPARE(i.peekPrevious(), QCHAR_UNICODE_VALUE(QLatin1Char('p')));
|
||||
QCOMPARE(i.previous(), QCHAR_UNICODE_VALUE(QLatin1Char('p')));
|
||||
|
||||
QCOMPARE(i.position(), begin + 34);
|
||||
QCOMPARE(i.peekPrevious(), 0x10000u);
|
||||
QCOMPARE(i.previous(), 0x10000u);
|
||||
|
||||
QCOMPARE(i.position(), begin + 32);
|
||||
|
||||
|
||||
i.setPosition(begin + 16);
|
||||
QCOMPARE(i.position(), begin + 16);
|
||||
|
||||
i.recedeUnchecked();
|
||||
i.recedeUnchecked();
|
||||
QCOMPARE(i.position(), begin + 12);
|
||||
|
||||
i.recedeUnchecked();
|
||||
i.recedeUnchecked();
|
||||
i.recedeUnchecked();
|
||||
i.recedeUnchecked();
|
||||
QCOMPARE(i.position(), begin + 8);
|
||||
|
||||
i.recedeUnchecked();
|
||||
i.recedeUnchecked();
|
||||
i.recedeUnchecked();
|
||||
i.recedeUnchecked();
|
||||
i.recedeUnchecked();
|
||||
i.recedeUnchecked();
|
||||
QCOMPARE(i.position(), begin + 2);
|
||||
|
||||
#undef QCHAR_UNICODE_VALUE
|
||||
}
|
||||
|
||||
QTEST_APPLESS_MAIN(tst_QStringIterator)
|
||||
|
||||
#include "tst_qstringiterator.moc"
|
||||
|
|
@ -44,6 +44,7 @@ SUBDIRS=\
|
|||
qstring \
|
||||
qstring_no_cast_from_bytearray \
|
||||
qstringbuilder \
|
||||
qstringiterator \
|
||||
qstringlist \
|
||||
qstringmatcher \
|
||||
qstringref \
|
||||
|
|
|
|||
Loading…
Reference in New Issue