summaryrefslogtreecommitdiff
path: root/src/corelib/tools
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/tools')
-rw-r--r--src/corelib/tools/qalgorithms.h17
-rw-r--r--src/corelib/tools/qalgorithms.qdoc651
-rw-r--r--src/corelib/tools/qbitarray.cpp7
-rw-r--r--src/corelib/tools/qbytearray.cpp107
-rw-r--r--src/corelib/tools/qbytearray.h24
-rw-r--r--src/corelib/tools/qbytearraymatcher.cpp2
-rw-r--r--src/corelib/tools/qbytearraymatcher.h11
-rw-r--r--src/corelib/tools/qbytedata_p.h213
-rw-r--r--src/corelib/tools/qcache.qdoc244
-rw-r--r--src/corelib/tools/qchar.cpp44
-rw-r--r--src/corelib/tools/qcontiguouscache.cpp432
-rw-r--r--src/corelib/tools/qcontiguouscache.h437
-rw-r--r--src/corelib/tools/qcryptographichash.cpp4
-rw-r--r--src/corelib/tools/qdatetime.cpp57
-rw-r--r--src/corelib/tools/qdatetime.h3
-rw-r--r--src/corelib/tools/qdatetime_p.h18
-rw-r--r--src/corelib/tools/qdumper.cpp1157
-rw-r--r--src/corelib/tools/qeasingcurve.cpp850
-rw-r--r--src/corelib/tools/qeasingcurve.h114
-rw-r--r--src/corelib/tools/qharfbuzz.cpp5
-rw-r--r--src/corelib/tools/qharfbuzz_p.h2
-rw-r--r--src/corelib/tools/qhash.cpp82
-rw-r--r--src/corelib/tools/qhash.h64
-rw-r--r--src/corelib/tools/qiterator.qdoc1431
-rw-r--r--src/corelib/tools/qline.cpp8
-rw-r--r--src/corelib/tools/qlinkedlist.cpp2
-rw-r--r--src/corelib/tools/qlinkedlist.h44
-rw-r--r--src/corelib/tools/qlist.cpp (renamed from src/corelib/tools/qlistdata.cpp)117
-rw-r--r--src/corelib/tools/qlist.h129
-rw-r--r--src/corelib/tools/qlocale.cpp263
-rw-r--r--src/corelib/tools/qlocale.h2
-rw-r--r--src/corelib/tools/qlocale_data_p.h10
-rw-r--r--src/corelib/tools/qlocale_p.h40
-rw-r--r--src/corelib/tools/qlocale_symbian.cpp879
-rw-r--r--src/corelib/tools/qmap.cpp41
-rw-r--r--src/corelib/tools/qmap.h45
-rw-r--r--src/corelib/tools/qpair.qdoc229
-rw-r--r--src/corelib/tools/qpodlist_p.h192
-rw-r--r--src/corelib/tools/qpoint.cpp21
-rw-r--r--src/corelib/tools/qpoint.h6
-rw-r--r--src/corelib/tools/qqueue.cpp2
-rw-r--r--src/corelib/tools/qrect.cpp4
-rw-r--r--src/corelib/tools/qregexp.cpp410
-rw-r--r--src/corelib/tools/qregexp.h2
-rw-r--r--src/corelib/tools/qringbuffer_p.h102
-rw-r--r--src/corelib/tools/qscopedpointer.cpp218
-rw-r--r--src/corelib/tools/qscopedpointer.h307
-rw-r--r--src/corelib/tools/qset.h14
-rw-r--r--src/corelib/tools/qset.qdoc953
-rw-r--r--src/corelib/tools/qshareddata.cpp673
-rw-r--r--src/corelib/tools/qshareddata.h18
-rw-r--r--src/corelib/tools/qsharedpointer.cpp723
-rw-r--r--src/corelib/tools/qsharedpointer.h7
-rw-r--r--src/corelib/tools/qsharedpointer_impl.h483
-rw-r--r--src/corelib/tools/qsize.cpp4
-rw-r--r--src/corelib/tools/qsize.h12
-rw-r--r--src/corelib/tools/qstack.cpp2
-rw-r--r--src/corelib/tools/qstring.cpp499
-rw-r--r--src/corelib/tools/qstring.h14
-rw-r--r--src/corelib/tools/qstringbuilder.cpp145
-rw-r--r--src/corelib/tools/qstringbuilder.h260
-rw-r--r--src/corelib/tools/qstringlist.cpp5
-rw-r--r--src/corelib/tools/qstringlist.h1
-rw-r--r--src/corelib/tools/qstringmatcher.cpp2
-rw-r--r--src/corelib/tools/qstringmatcher.h11
-rw-r--r--src/corelib/tools/qtextboundaryfinder.cpp14
-rw-r--r--src/corelib/tools/qtimeline.cpp130
-rw-r--r--src/corelib/tools/qtimeline.h5
-rw-r--r--src/corelib/tools/qunicodetables_p.h2
-rw-r--r--src/corelib/tools/qvarlengtharray.h82
-rw-r--r--src/corelib/tools/qvarlengtharray.qdoc274
-rw-r--r--src/corelib/tools/qvector.cpp3
-rw-r--r--src/corelib/tools/qvector.h253
-rw-r--r--src/corelib/tools/tools.pri23
74 files changed, 10866 insertions, 2795 deletions
diff --git a/src/corelib/tools/qalgorithms.h b/src/corelib/tools/qalgorithms.h
index 649ed19787..4a8107d4a9 100644
--- a/src/corelib/tools/qalgorithms.h
+++ b/src/corelib/tools/qalgorithms.h
@@ -141,23 +141,6 @@ inline void qCount(const Container &container, const T &value, Size &n)
qCount(container.constBegin(), container.constEnd(), value, n);
}
-
-#if defined Q_CC_MSVC && _MSC_VER < 1300
-template <typename T>
-inline void qSwap(T &value1, T &value2)
-{
- qSwap_helper<T>(value1, value2, (T *)0);
-}
-#else
-template <typename T>
-inline void qSwap(T &value1, T &value2)
-{
- T t = value1;
- value1 = value2;
- value2 = t;
-}
-#endif
-
#ifdef qdoc
template <typename T>
LessThan qLess()
diff --git a/src/corelib/tools/qalgorithms.qdoc b/src/corelib/tools/qalgorithms.qdoc
new file mode 100644
index 0000000000..3b43b4e4cf
--- /dev/null
+++ b/src/corelib/tools/qalgorithms.qdoc
@@ -0,0 +1,651 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \headerfile <QtAlgorithms>
+ \title Generic Algorithms
+ \ingroup funclists
+
+ \brief The <QtAlgorithms> header includes the generic, template-based algorithms.
+
+ Qt provides a number of global template functions in \c
+ <QtAlgorithms> that work on containers and perform well-know
+ algorithms. You can use these algorithms with any \l {container
+ class} that provides STL-style iterators, including Qt's QList,
+ QLinkedList, QVector, QMap, and QHash classes.
+
+ These functions have taken their inspiration from similar
+ functions available in the STL \c <algorithm> header. Most of them
+ have a direct STL equivalent; for example, qCopyBackward() is the
+ same as STL's copy_backward() algorithm.
+
+ If STL is available on all your target platforms, you can use the
+ STL algorithms instead of their Qt counterparts. One reason why
+ you might want to use the STL algorithms is that STL provides
+ dozens and dozens of algorithms, whereas Qt only provides the most
+ important ones, making no attempt to duplicate functionality that
+ is already provided by the C++ standard.
+
+ Most algorithms take \l {STL-style iterators} as parameters. The
+ algorithms are generic in the sense that they aren't bound to a
+ specific iterator class; you can use them with any iterators that
+ meet a certain set of requirements.
+
+ Let's take the qFill() algorithm as an example. Unlike QVector,
+ QList has no fill() function that can be used to fill a list with
+ a particular value. If you need that functionality, you can use
+ qFill():
+
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.qdoc 0
+
+ qFill() takes a begin iterator, an end iterator, and a value.
+ In the example above, we pass \c list.begin() and \c list.end()
+ as the begin and end iterators, but this doesn't have to be
+ the case:
+
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.qdoc 1
+
+ Different algorithms can have different requirements for the
+ iterators they accept. For example, qFill() accepts two
+ \l {forward iterators}. The iterator types required are specified
+ for each algorithm. If an iterator of the wrong type is passed (for
+ example, if QList::ConstIterator is passed as an \l {output
+ iterator}), you will always get a compiler error, although not
+ necessarily a very informative one.
+
+ Some algorithms have special requirements on the value type
+ stored in the containers. For example, qEqual() requires that the
+ value type supports operator==(), which it uses to compare items.
+ Similarly, qDeleteAll() requires that the value type is a
+ non-const pointer type (for example, QWidget *). The value type
+ requirements are specified for each algorithm, and the compiler
+ will produce an error if a requirement isn't met.
+
+ \target binaryFind example
+
+ The generic algorithms can be used on other container classes
+ than those provided by Qt and STL. The syntax of STL-style
+ iterators is modeled after C++ pointers, so it's possible to use
+ plain arrays as containers and plain pointers as iterators. A
+ common idiom is to use qBinaryFind() together with two static
+ arrays: one that contains a list of keys, and another that
+ contains a list of associated values. For example, the following
+ code will look up an HTML entity (e.g., \c &amp;) in the \c
+ name_table array and return the corresponding Unicode value from
+ the \c value_table if the entity is recognized:
+
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.qdoc 2
+
+ This kind of code is for advanced users only; for most
+ applications, a QMap- or QHash-based approach would work just as
+ well:
+
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.qdoc 3
+
+ \section1 Types of Iterators
+
+ The algorithms have certain requirements on the iterator types
+ they accept, and these are specified individually for each
+ function. The compiler will produce an error if a requirement
+ isn't met.
+
+ \section2 Input Iterators
+
+ An \e{input iterator} is an iterator that can be used for reading
+ data sequentially from a container. It must provide the following
+ operators: \c{==} and \c{!=} for comparing two iterators, unary
+ \c{*} for retrieving the value stored in the item, and prefix
+ \c{++} for advancing to the next item.
+
+ The Qt containers' iterator types (const and non-const) are all
+ input iterators.
+
+ \section2 Output Iterators
+
+ An \e{output iterator} is an iterator that can be used for
+ writing data sequentially to a container or to some output
+ stream. It must provide the following operators: unary \c{*} for
+ writing a value (i.e., \c{*it = val}) and prefix \c{++} for
+ advancing to the next item.
+
+ The Qt containers' non-const iterator types are all output
+ iterators.
+
+ \section2 Forward Iterators
+
+ A \e{forward iterator} is an iterator that meets the requirements
+ of both input iterators and output iterators.
+
+ The Qt containers' non-const iterator types are all forward
+ iterators.
+
+ \section2 Bidirectional Iterators
+
+ A \e{bidirectional iterator} is an iterator that meets the
+ requirements of forward iterators but that in addition supports
+ prefix \c{--} for iterating backward.
+
+ The Qt containers' non-const iterator types are all bidirectional
+ iterators.
+
+ \section2 Random Access Iterators
+
+ The last category, \e{random access iterators}, is the most
+ powerful type of iterator. It supports all the requirements of a
+ bidirectional iterator, and supports the following operations:
+
+ \table
+ \row \i \c{i += n} \i advances iterator \c i by \c n positions
+ \row \i \c{i -= n} \i moves iterator \c i back by \c n positions
+ \row \i \c{i + n} or \c{n + i} \i returns the iterator for the item \c
+ n positions ahead of iterator \c i
+ \row \i \c{i - n} \i returns the iterator for the item \c n positions behind of iterator \c i
+ \row \i \c{i - j} \i returns the number of items between iterators \c i and \c j
+ \row \i \c{i[n]} \i same as \c{*(i + n)}
+ \row \i \c{i < j} \i returns true if iterator \c j comes after iterator \c i
+ \endtable
+
+ QList and QVector's non-const iterator types are random access iterators.
+
+ \sa {container classes}, <QtGlobal>
+*/
+
+/*! \fn OutputIterator qCopy(InputIterator begin1, InputIterator end1, OutputIterator begin2)
+ \relates <QtAlgorithms>
+
+ Copies the items from range [\a begin1, \a end1) to range [\a
+ begin2, ...), in the order in which they appear.
+
+ The item at position \a begin1 is assigned to that at position \a
+ begin2; the item at position \a begin1 + 1 is assigned to that at
+ position \a begin2 + 1; and so on.
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.qdoc 4
+
+ \sa qCopyBackward(), {input iterators}, {output iterators}
+*/
+
+/*! \fn BiIterator2 qCopyBackward(BiIterator1 begin1, BiIterator1 end1, BiIterator2 end2)
+ \relates <QtAlgorithms>
+
+ Copies the items from range [\a begin1, \a end1) to range [...,
+ \a end2).
+
+ The item at position \a end1 - 1 is assigned to that at position
+ \a end2 - 1; the item at position \a end1 - 2 is assigned to that
+ at position \a end2 - 2; and so on.
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.qdoc 5
+
+ \sa qCopy(), {bidirectional iterators}
+*/
+
+/*! \fn bool qEqual(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2)
+ \relates <QtAlgorithms>
+
+ Compares the items in the range [\a begin1, \a end1) with the
+ items in the range [\a begin2, ...). Returns true if all the
+ items compare equal; otherwise returns false.
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.qdoc 6
+
+ This function requires the item type (in the example above,
+ QString) to implement \c operator==().
+
+ \sa {input iterators}
+*/
+
+/*! \fn void qFill(ForwardIterator begin, ForwardIterator end, const T &value)
+ \relates <QtAlgorithms>
+
+ Fills the range [\a begin, \a end) with \a value.
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.qdoc 7
+
+ \sa qCopy(), {forward iterators}
+*/
+
+/*! \fn void qFill(Container &container, const T &value)
+ \relates <QtAlgorithms>
+
+ \overload
+
+ This is the same as qFill(\a{container}.begin(), \a{container}.end(), \a value);
+*/
+
+/*! \fn InputIterator qFind(InputIterator begin, InputIterator end, const T &value)
+ \relates <QtAlgorithms>
+
+ Returns an iterator to the first occurrence of \a value in a
+ container in the range [\a begin, \a end). Returns \a end if \a
+ value isn't found.
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.qdoc 8
+
+ This function requires the item type (in the example above,
+ QString) to implement \c operator==().
+
+ If the items in the range are in ascending order, you can get
+ faster results by using qLowerBound() or qBinaryFind() instead of
+ qFind().
+
+ \sa qBinaryFind(), {input iterators}
+*/
+
+/*! \fn void qFind(const Container &container, const T &value)
+ \relates <QtAlgorithms>
+
+ \overload
+
+ This is the same as qFind(\a{container}.begin(), \a{container}.end(), value);
+*/
+
+/*! \fn void qCount(InputIterator begin, InputIterator end, const T &value, Size &n)
+ \relates <QtAlgorithms>
+
+ Returns the number of occurrences of \a value in the range [\a begin, \a end),
+ which is returned in \a n. \a n is never initialized, the count is added to \a n.
+ It is the caller's responsibility to initialize \a n.
+
+ Example:
+
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.qdoc 9
+
+ This function requires the item type (in the example above,
+ \c int) to implement \c operator==().
+
+ \sa {input iterators}
+*/
+
+/*! \fn void qCount(const Container &container, const T &value, Size &n)
+\relates <QtAlgorithms>
+
+\overload
+
+Instead of operating on iterators, as in the other overload, this function
+operates on the specified \a container to obtain the number of instances
+of \a value in the variable passed as a reference in argument \a n.
+*/
+
+/*! \fn void qSwap(T &var1, T &var2)
+ \relates <QtAlgorithms>
+
+ Exchanges the values of variables \a var1 and \a var2.
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.qdoc 10
+*/
+
+/*! \fn void qSort(RandomAccessIterator begin, RandomAccessIterator end)
+ \relates <QtAlgorithms>
+
+ Sorts the items in range [\a begin, \a end) in ascending order
+ using the quicksort algorithm.
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.qdoc 11
+
+ The sort algorithm is efficient on large data sets. It operates
+ in \l {linear-logarithmic time}, O(\e{n} log \e{n}).
+
+ This function requires the item type (in the example above,
+ \c{int}) to implement \c operator<().
+
+ If neither of the two items is "less than" the other, the items are
+ taken to be equal. It is then undefined which one of the two
+ items will appear before the other after the sort.
+
+ \sa qStableSort(), {random access iterators}
+*/
+
+/*! \fn void qSort(RandomAccessIterator begin, RandomAccessIterator end, LessThan lessThan)
+ \relates <QtAlgorithms>
+
+ \overload
+
+ Uses the \a lessThan function instead of \c operator<() to
+ compare the items.
+
+ For example, here's how to sort the strings in a QStringList
+ in case-insensitive alphabetical order:
+
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.qdoc 12
+
+ To sort values in reverse order, pass
+ \l{qGreater()}{qGreater<T>()} as the \a lessThan parameter. For
+ example:
+
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.qdoc 13
+
+ If neither of the two items is "less than" the other, the items are
+ taken to be equal. It is then undefined which one of the two
+ items will appear before the other after the sort.
+
+ An alternative to using qSort() is to put the items to sort in a
+ QMap, using the sort key as the QMap key. This is often more
+ convenient than defining a \a lessThan function. For example, the
+ following code shows how to sort a list of strings case
+ insensitively using QMap:
+
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.qdoc 14
+
+ \sa QMap
+*/
+
+/*! \fn void qSort(Container &container)
+ \relates <QtAlgorithms>
+
+ \overload
+
+ This is the same as qSort(\a{container}.begin(), \a{container}.end());
+*/
+
+/*!
+ \fn void qStableSort(RandomAccessIterator begin, RandomAccessIterator end)
+ \relates <QtAlgorithms>
+
+ Sorts the items in range [\a begin, \a end) in ascending order
+ using a stable sorting algorithm.
+
+ If neither of the two items is "less than" the other, the items are
+ taken to be equal. The item that appeared before the other in the
+ original container will still appear first after the sort. This
+ property is often useful when sorting user-visible data.
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.qdoc 15
+
+ The sort algorithm is efficient on large data sets. It operates
+ in \l {linear-logarithmic time}, O(\e{n} log \e{n}).
+
+ This function requires the item type (in the example above,
+ \c{int}) to implement \c operator<().
+
+ \sa qSort(), {random access iterators}
+*/
+
+/*!
+ \fn void qStableSort(RandomAccessIterator begin, RandomAccessIterator end, LessThan lessThan)
+ \relates <QtAlgorithms>
+
+ \overload
+
+ Uses the \a lessThan function instead of \c operator<() to
+ compare the items.
+
+ For example, here's how to sort the strings in a QStringList
+ in case-insensitive alphabetical order:
+
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.qdoc 16
+
+ Note that earlier versions of Qt allowed using a lessThan function that took its
+ arguments by non-const reference. From 4.3 and on this is no longer possible,
+ the arguments has to be passed by const reference or value.
+
+ To sort values in reverse order, pass
+ \l{qGreater()}{qGreater<T>()} as the \a lessThan parameter. For
+ example:
+
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.qdoc 17
+
+ If neither of the two items is "less than" the other, the items are
+ taken to be equal. The item that appeared before the other in the
+ original container will still appear first after the sort. This
+ property is often useful when sorting user-visible data.
+*/
+
+/*!
+ \fn void qStableSort(Container &container)
+ \relates <QtAlgorithms>
+
+ \overload
+
+ This is the same as qStableSort(\a{container}.begin(), \a{container}.end());
+*/
+
+/*! \fn RandomAccessIterator qLowerBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value)
+ \relates <QtAlgorithms>
+
+ Performs a binary search of the range [\a begin, \a end) and
+ returns the position of the first ocurrence of \a value. If no
+ such item is found, returns the position where it should be
+ inserted.
+
+ The items in the range [\a begin, \e end) must be sorted in
+ ascending order; see qSort().
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.qdoc 18
+
+ This function requires the item type (in the example above,
+ \c{int}) to implement \c operator<().
+
+ qLowerBound() can be used in conjunction with qUpperBound() to
+ iterate over all occurrences of the same value:
+
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.qdoc 19
+
+ \sa qUpperBound(), qBinaryFind()
+*/
+
+/*!
+ \fn RandomAccessIterator qLowerBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan)
+ \relates <QtAlgorithms>
+
+ \overload
+
+ Uses the \a lessThan function instead of \c operator<() to
+ compare the items.
+
+ Note that the items in the range must be sorted according to the order
+ specified by the \a lessThan object.
+*/
+
+/*!
+ \fn void qLowerBound(const Container &container, const T &value)
+ \relates <QtAlgorithms>
+
+ \overload
+
+ For read-only iteration over containers, this function is broadly equivalent to
+ qLowerBound(\a{container}.begin(), \a{container}.end(), value). However, since it
+ returns a const iterator, you cannot use it to modify the container; for example,
+ to insert items.
+*/
+
+/*! \fn RandomAccessIterator qUpperBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value)
+ \relates <QtAlgorithms>
+
+ Performs a binary search of the range [\a begin, \a end) and
+ returns the position of the one-past-the-last occurrence of \a
+ value. If no such item is found, returns the position where the
+ item should be inserted.
+
+ The items in the range [\a begin, \e end) must be sorted in
+ ascending order; see qSort().
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.qdoc 20
+
+ This function requires the item type (in the example above,
+ \c{int}) to implement \c operator<().
+
+ qUpperBound() can be used in conjunction with qLowerBound() to
+ iterate over all occurrences of the same value:
+
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.qdoc 21
+
+ \sa qLowerBound(), qBinaryFind()
+*/
+
+/*!
+ \fn RandomAccessIterator qUpperBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan)
+ \relates <QtAlgorithms>
+
+ \overload
+
+ Uses the \a lessThan function instead of \c operator<() to
+ compare the items.
+
+ Note that the items in the range must be sorted according to the order
+ specified by the \a lessThan object.
+*/
+
+/*!
+ \fn void qUpperBound(const Container &container, const T &value)
+ \relates <QtAlgorithms>
+
+ \overload
+
+ This is the same as qUpperBound(\a{container}.begin(), \a{container}.end(), value);
+*/
+
+
+/*! \fn RandomAccessIterator qBinaryFind(RandomAccessIterator begin, RandomAccessIterator end, const T &value)
+ \relates <QtAlgorithms>
+
+ Performs a binary search of the range [\a begin, \a end) and
+ returns the position of an occurrence of \a value. If there are
+ no occurrences of \a value, returns \a end.
+
+ The items in the range [\a begin, \a end) must be sorted in
+ ascending order; see qSort().
+
+ If there are many occurrences of the same value, any one of them
+ could be returned. Use qLowerBound() or qUpperBound() if you need
+ finer control.
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.qdoc 22
+
+ This function requires the item type (in the example above,
+ QString) to implement \c operator<().
+
+ See the \l{<QtAlgorithms>#binaryFind example}{detailed
+ description} for an example usage.
+
+ \sa qLowerBound(), qUpperBound(), {random access iterators}
+*/
+
+/*! \fn RandomAccessIterator qBinaryFind(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan)
+ \relates <QtAlgorithms>
+
+ \overload
+
+ Uses the \a lessThan function instead of \c operator<() to
+ compare the items.
+
+ Note that the items in the range must be sorted according to the order
+ specified by the \a lessThan object.
+*/
+
+/*!
+ \fn void qBinaryFind(const Container &container, const T &value)
+ \relates <QtAlgorithms>
+
+ \overload
+
+ This is the same as qBinaryFind(\a{container}.begin(), \a{container}.end(), value);
+*/
+
+
+/*!
+ \fn void qDeleteAll(ForwardIterator begin, ForwardIterator end)
+ \relates <QtAlgorithms>
+
+ Deletes all the items in the range [\a begin, \a end) using the
+ C++ \c delete operator. The item type must be a pointer type (for
+ example, \c{QWidget *}).
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.qdoc 23
+
+ Notice that qDeleteAll() doesn't remove the items from the
+ container; it merely calls \c delete on them. In the example
+ above, we call clear() on the container to remove the items.
+
+ This function can also be used to delete items stored in
+ associative containers, such as QMap and QHash. Only the objects
+ stored in each container will be deleted by this function; objects
+ used as keys will not be deleted.
+
+ \sa {forward iterators}
+*/
+
+/*!
+ \fn void qDeleteAll(const Container &c)
+ \relates <QtAlgorithms>
+
+ \overload
+
+ This is the same as qDeleteAll(\a{c}.begin(), \a{c}.end()).
+*/
+
+/*! \fn LessThan qLess()
+ \relates <QtAlgorithms>
+
+ Returns a functional object, or functor, that can be passed to qSort()
+ or qStableSort().
+
+ Example:
+
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.qdoc 24
+
+ \sa {qGreater()}{qGreater<T>()}
+*/
+
+/*! \fn LessThan qGreater()
+ \relates <QtAlgorithms>
+
+ Returns a functional object, or functor, that can be passed to qSort()
+ or qStableSort().
+
+ Example:
+
+ \snippet doc/src/snippets/code/doc_src_qalgorithms.qdoc 25
+
+ \sa {qLess()}{qLess<T>()}
+*/
diff --git a/src/corelib/tools/qbitarray.cpp b/src/corelib/tools/qbitarray.cpp
index c429a9ff8f..19ac8dc0a1 100644
--- a/src/corelib/tools/qbitarray.cpp
+++ b/src/corelib/tools/qbitarray.cpp
@@ -209,6 +209,8 @@ void QBitArray::resize(int size)
uchar* c = reinterpret_cast<uchar*>(d.data());
if (size > (s << 3))
memset(c + s, 0, d.size() - s);
+ else if ( size % 8)
+ *(c+1+size/8) &= (1 << (size%8)) - 1;
*c = d.size()*8 - size;
}
}
@@ -653,6 +655,7 @@ QBitArray operator^(const QBitArray &a1, const QBitArray &a2)
QBitArray stream functions
*****************************************************************************/
+#ifndef QT_NO_DATASTREAM
/*!
\relates QBitArray
@@ -660,7 +663,7 @@ QBitArray operator^(const QBitArray &a1, const QBitArray &a2)
\sa \link datastreamformat.html Format of the QDataStream operators \endlink
*/
-#ifndef QT_NO_DATASTREAM
+
QDataStream &operator<<(QDataStream &out, const QBitArray &ba)
{
quint32 len = ba.size();
@@ -713,7 +716,7 @@ QDataStream &operator>>(QDataStream &in, QBitArray &ba)
*ba.d.data() = ba.d.size() * 8 - len;
return in;
}
-#endif
+#endif // QT_NO_DATASTREAM
/*!
\fn DataPtr &QBitArray::data_ptr()
diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp
index 4f77633396..840f6a5949 100644
--- a/src/corelib/tools/qbytearray.cpp
+++ b/src/corelib/tools/qbytearray.cpp
@@ -538,9 +538,13 @@ QByteArray qUncompress(const uchar* data, int nbytes)
QByteArray baunzip;
int res;
do {
- baunzip.resize(len);
- res = ::uncompress((uchar*)baunzip.data(), &len,
- (uchar*)data+4, nbytes-4);
+ QT_TRY {
+ baunzip.resize(len);
+ res = ::uncompress((uchar*)baunzip.data(), &len,
+ (uchar*)data+4, nbytes-4);
+ } QT_CATCH (const std::bad_alloc &) {
+ res = Z_MEM_ERROR;
+ }
switch (res) {
case Z_OK:
@@ -579,7 +583,7 @@ static inline char qToLower(char c)
return c;
}
-Q_CORE_EXPORT QByteArray::Data QByteArray::shared_null = {Q_BASIC_ATOMIC_INITIALIZER(1),
+QByteArray::Data QByteArray::shared_null = {Q_BASIC_ATOMIC_INITIALIZER(1),
0, 0, shared_null.array, {0} };
QByteArray::Data QByteArray::shared_empty = { Q_BASIC_ATOMIC_INITIALIZER(1),
0, 0, shared_empty.array, {0} };
@@ -590,8 +594,8 @@ QByteArray::Data QByteArray::shared_empty = { Q_BASIC_ATOMIC_INITIALIZER(1),
\ingroup tools
\ingroup shared
- \ingroup text
- \mainclass
+ \ingroup string-processing
+
\reentrant
QByteArray can be used to store both raw bytes (including '\\0's)
@@ -1233,14 +1237,11 @@ QByteArray::QByteArray(const char *str)
} else {
int len = qstrlen(str);
d = static_cast<Data *>(qMalloc(sizeof(Data)+len));
- if (!d) {
- d = &shared_null;
- } else {
- d->ref = 0;;
- d->alloc = d->size = len;
- d->data = d->array;
- memcpy(d->array, str, len+1); // include null terminator
- }
+ Q_CHECK_PTR(d);
+ d->ref = 0;;
+ d->alloc = d->size = len;
+ d->data = d->array;
+ memcpy(d->array, str, len+1); // include null terminator
}
d->ref.ref();
}
@@ -1264,15 +1265,12 @@ QByteArray::QByteArray(const char *data, int size)
d = &shared_empty;
} else {
d = static_cast<Data *>(qMalloc(sizeof(Data) + size));
- if (!d) {
- d = &shared_null;
- } else {
- d->ref = 0;
- d->alloc = d->size = size;
- d->data = d->array;
- memcpy(d->array, data, size);
- d->array[size] = '\0';
- }
+ Q_CHECK_PTR(d);
+ d->ref = 0;
+ d->alloc = d->size = size;
+ d->data = d->array;
+ memcpy(d->array, data, size);
+ d->array[size] = '\0';
}
d->ref.ref();
}
@@ -1290,20 +1288,33 @@ QByteArray::QByteArray(int size, char ch)
d = &shared_null;
} else {
d = static_cast<Data *>(qMalloc(sizeof(Data)+size));
- if (!d) {
- d = &shared_null;
- } else {
- d->ref = 0;
- d->alloc = d->size = size;
- d->data = d->array;
- d->array[size] = '\0';
- memset(d->array, ch, size);
- }
+ Q_CHECK_PTR(d);
+ d->ref = 0;
+ d->alloc = d->size = size;
+ d->data = d->array;
+ d->array[size] = '\0';
+ memset(d->array, ch, size);
}
d->ref.ref();
}
/*!
+ \internal
+
+ Constructs a byte array of size \a size with uninitialized contents.
+*/
+
+QByteArray::QByteArray(int size, Qt::Initialization)
+{
+ d = static_cast<Data *>(qMalloc(sizeof(Data)+size));
+ Q_CHECK_PTR(d);
+ d->ref = 1;
+ d->alloc = d->size = size;
+ d->data = d->array;
+ d->array[size] = '\0';
+}
+
+/*!
Sets the size of the byte array to \a size bytes.
If \a size is greater than the current size, the byte array is
@@ -1334,8 +1345,7 @@ void QByteArray::resize(int size)
// QByteArray a(sz);
//
Data *x = static_cast<Data *>(qMalloc(sizeof(Data)+size));
- if (!x)
- return;
+ Q_CHECK_PTR(x);
x->ref = 1;
x->alloc = x->size = size;
x->data = x->array;
@@ -1377,8 +1387,7 @@ void QByteArray::realloc(int alloc)
{
if (d->ref != 1 || d->data != d->array) {
Data *x = static_cast<Data *>(qMalloc(sizeof(Data) + alloc));
- if (!x)
- return;
+ Q_CHECK_PTR(x);
x->size = qMin(alloc, d->size);
::memcpy(x->array, d->data, x->size);
x->array[x->size] = '\0';
@@ -1390,8 +1399,7 @@ void QByteArray::realloc(int alloc)
d = x;
} else {
Data *x = static_cast<Data *>(qRealloc(d, sizeof(Data) + alloc));
- if (!x)
- return;
+ Q_CHECK_PTR(x);
x->alloc = alloc;
x->data = x->array;
d = x;
@@ -1812,11 +1820,13 @@ QByteArray &QByteArray::replace(const char *before, int bsize, const char *after
const char *b = before;
if (after >= d->data && after < d->data + d->size) {
char *copy = (char *)malloc(asize);
+ Q_CHECK_PTR(copy);
memcpy(copy, after, asize);
a = copy;
}
if (before >= d->data && before < d->data + d->size) {
char *copy = (char *)malloc(bsize);
+ Q_CHECK_PTR(copy);
memcpy(copy, before, bsize);
b = copy;
}
@@ -2591,6 +2601,8 @@ void QByteArray::clear()
d->ref.ref();
}
+#ifndef QT_NO_DATASTREAM
+
/*! \relates QByteArray
Writes byte array \a ba to the stream \a out and returns a reference
@@ -2598,7 +2610,6 @@ void QByteArray::clear()
\sa {Format of the QDataStream operators}
*/
-#ifndef QT_NO_DATASTREAM
QDataStream &operator<<(QDataStream &out, const QByteArray &ba)
{
@@ -2641,7 +2652,7 @@ QDataStream &operator>>(QDataStream &in, QByteArray &ba)
return in;
}
-#endif //QT_NO_DATASTREAM
+#endif // QT_NO_DATASTREAM
/*! \fn bool QByteArray::operator==(const QString &str) const
@@ -2976,8 +2987,7 @@ QByteArray QByteArray::simplified() const
{
if (d->size == 0)
return *this;
- QByteArray result;
- result.resize(d->size);
+ QByteArray result(d->size, Qt::Uninitialized);
const char *from = d->data;
const char *fromend = from + d->size;
int outc=0;
@@ -3428,8 +3438,7 @@ QByteArray QByteArray::toBase64() const
const char padchar = '=';
int padlen = 0;
- QByteArray tmp;
- tmp.resize(((d->size * 4) / 3) + 3);
+ QByteArray tmp((d->size * 4) / 3 + 3, Qt::Uninitialized);
int i = 0;
char *out = tmp.data();
@@ -3738,6 +3747,7 @@ QByteArray QByteArray::number(double n, char f, int prec)
QByteArray QByteArray::fromRawData(const char *data, int size)
{
Data *x = static_cast<Data *>(qMalloc(sizeof(Data)));
+ Q_CHECK_PTR(x);
if (data) {
x->data = const_cast<char *>(data);
} else {
@@ -3767,8 +3777,7 @@ QByteArray QByteArray::fromBase64(const QByteArray &base64)
{
unsigned int buf = 0;
int nbits = 0;
- QByteArray tmp;
- tmp.resize((base64.size() * 3) / 4);
+ QByteArray tmp((base64.size() * 3) / 4, Qt::Uninitialized);
int offset = 0;
for (int i = 0; i < base64.size(); ++i) {
@@ -3816,8 +3825,7 @@ QByteArray QByteArray::fromBase64(const QByteArray &base64)
*/
QByteArray QByteArray::fromHex(const QByteArray &hexEncoded)
{
- QByteArray res;
- res.resize((hexEncoded.size() + 1)/ 2);
+ QByteArray res((hexEncoded.size() + 1)/ 2, Qt::Uninitialized);
uchar *result = (uchar *)res.data() + res.size();
bool odd_digit = true;
@@ -3854,8 +3862,7 @@ QByteArray QByteArray::fromHex(const QByteArray &hexEncoded)
*/
QByteArray QByteArray::toHex() const
{
- QByteArray hex;
- hex.resize(d->size*2);
+ QByteArray hex(d->size * 2, Qt::Uninitialized);
char *hexData = hex.data();
const uchar *data = (const uchar *)d->data;
for (int i = 0; i < d->size; ++i) {
diff --git a/src/corelib/tools/qbytearray.h b/src/corelib/tools/qbytearray.h
index 86ba397f66..f7e790dcc7 100644
--- a/src/corelib/tools/qbytearray.h
+++ b/src/corelib/tools/qbytearray.h
@@ -42,8 +42,8 @@
#ifndef QBYTEARRAY_H
#define QBYTEARRAY_H
-#include <QtCore/qglobal.h>
#include <QtCore/qatomic.h>
+#include <QtCore/qnamespace.h>
#include <string.h>
#include <stdarg.h>
@@ -122,11 +122,23 @@ template <typename T> class QList;
class Q_CORE_EXPORT QByteArray
{
+private:
+ struct Data {
+ QBasicAtomicInt ref;
+ int alloc, size;
+ // ### Qt 5.0: We need to add the missing capacity bit
+ // (like other tool classes have), to maintain the
+ // reserved memory on resize.
+ char *data;
+ char array[1];
+ };
+
public:
inline QByteArray();
QByteArray(const char *);
QByteArray(const char *, int size);
QByteArray(int size, char c);
+ QByteArray(int size, Qt::Initialization);
inline QByteArray(const QByteArray &);
inline ~QByteArray();
@@ -309,6 +321,7 @@ public:
// stl compatibility
typedef const char & const_reference;
typedef char & reference;
+ typedef char value_type;
void push_back(char c);
void push_back(const char *c);
void push_back(const QByteArray &a);
@@ -347,15 +360,6 @@ public:
private:
operator QNoImplicitBoolCast() const;
- struct Data {
- QBasicAtomicInt ref;
- int alloc, size;
- // ### Qt 5.0: We need to add the missing capacity bit
- // (like other tool classes have), to maintain the
- // reserved memory on resize.
- char *data;
- char array[1];
- };
static Data shared_null;
static Data shared_empty;
Data *d;
diff --git a/src/corelib/tools/qbytearraymatcher.cpp b/src/corelib/tools/qbytearraymatcher.cpp
index 7fb60c2531..fb212126ef 100644
--- a/src/corelib/tools/qbytearraymatcher.cpp
+++ b/src/corelib/tools/qbytearraymatcher.cpp
@@ -94,7 +94,7 @@ static inline int bm_find(const uchar *cc, int l, int index, const uchar *puc, u
can be quickly matched in a byte array.
\ingroup tools
- \ingroup text
+ \ingroup string-processing
This class is useful when you have a sequence of bytes that you
want to repeatedly match against some byte arrays (perhaps in a
diff --git a/src/corelib/tools/qbytearraymatcher.h b/src/corelib/tools/qbytearraymatcher.h
index 291c6d6c03..c0d669d90f 100644
--- a/src/corelib/tools/qbytearraymatcher.h
+++ b/src/corelib/tools/qbytearraymatcher.h
@@ -81,13 +81,14 @@ private:
// explicitely allow anonymous unions for RVCT to prevent compiler warnings
#pragma anon_unions
#endif
+ struct Data {
+ uchar q_skiptable[256];
+ const uchar *p;
+ int l;
+ };
union {
uint dummy[256];
- struct {
- uchar q_skiptable[256];
- const uchar *p;
- int l;
- } p;
+ Data p;
};
};
diff --git a/src/corelib/tools/qbytedata_p.h b/src/corelib/tools/qbytedata_p.h
new file mode 100644
index 0000000000..c3275c76d9
--- /dev/null
+++ b/src/corelib/tools/qbytedata_p.h
@@ -0,0 +1,213 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBYTEDATA_H
+#define QBYTEDATA_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <qbytearray.h>
+
+QT_BEGIN_NAMESPACE
+
+// this class handles a list of QByteArrays. It is a variant of QRingBuffer
+// that avoid malloc/realloc/memcpy.
+class QByteDataBuffer
+{
+private:
+ QList<QByteArray> buffers;
+ qint64 bufferCompleteSize;
+public:
+ QByteDataBuffer() : bufferCompleteSize(0)
+ {
+ }
+
+ ~QByteDataBuffer()
+ {
+ clear();
+ }
+
+ inline void append(QByteDataBuffer& other)
+ {
+ if (other.isEmpty())
+ return;
+
+ buffers.append(other.buffers);
+ bufferCompleteSize += other.byteAmount();
+ }
+
+
+ inline void append(QByteArray& bd)
+ {
+ if (bd.isEmpty())
+ return;
+
+ buffers.append(bd);
+ bufferCompleteSize += bd.size();
+ }
+
+ inline void prepend(QByteArray& bd)
+ {
+ if (bd.isEmpty())
+ return;
+
+ buffers.prepend(bd);
+ bufferCompleteSize += bd.size();
+ }
+
+ // return the first QByteData. User of this function has to qFree() its .data!
+ // preferably use this function to read data.
+ inline QByteArray read()
+ {
+ bufferCompleteSize -= buffers.first().size();
+ return buffers.takeFirst();
+ }
+
+ // return everything. User of this function has to qFree() its .data!
+ // avoid to use this, it might malloc and memcpy.
+ inline QByteArray readAll()
+ {
+ return read(byteAmount());
+ }
+
+ // return amount. User of this function has to qFree() its .data!
+ // avoid to use this, it might malloc and memcpy.
+ inline QByteArray read(qint64 amount)
+ {
+ amount = qMin(byteAmount(), amount);
+ QByteArray byteData;
+ byteData.resize(amount);
+ read(byteData.data(), byteData.size());
+ return byteData;
+ }
+
+ // return amount bytes. User of this function has to qFree() its .data!
+ // avoid to use this, it will memcpy.
+ qint64 read(char* dst, qint64 amount)
+ {
+ amount = qMin(amount, byteAmount());
+ qint64 originalAmount = amount;
+ char *writeDst = dst;
+
+ while (amount > 0) {
+ QByteArray first = buffers.takeFirst();
+ if (amount >= first.size()) {
+ // take it completely
+ bufferCompleteSize -= first.size();
+ amount -= first.size();
+ memcpy(writeDst, first.constData(), first.size());
+ writeDst += first.size();
+ first.clear();
+ } else {
+ // take a part of it & it is the last one to take
+ bufferCompleteSize -= amount;
+ memcpy(writeDst, first.constData(), amount);
+
+ qint64 newFirstSize = first.size() - amount;
+ QByteArray newFirstData;
+ newFirstData.resize(newFirstSize);
+ memcpy(newFirstData.data(), first.constData() + amount, newFirstSize);
+ buffers.prepend(newFirstData);
+
+ amount = 0;
+ first.clear();
+ }
+ }
+
+ return originalAmount;
+ }
+
+ inline char getChar()
+ {
+ char c;
+ read(&c, 1);
+ return c;
+ }
+
+ inline void clear()
+ {
+ buffers.clear();
+ bufferCompleteSize = 0;
+ }
+
+ // The byte count of all QByteArrays
+ inline qint64 byteAmount() const
+ {
+ return bufferCompleteSize;
+ }
+
+ // the number of QByteArrays
+ inline qint64 bufferCount() const
+ {
+ return buffers.length();
+ }
+
+ inline bool isEmpty() const
+ {
+ return byteAmount() == 0;
+ }
+
+ inline qint64 sizeNextBlock() const
+ {
+ if(buffers.isEmpty())
+ return 0;
+ else
+ return buffers.first().size();
+ }
+
+ inline QByteArray& operator[](int i)
+ {
+ return buffers[i];
+ }
+};
+
+QT_END_NAMESPACE
+
+#endif // QBYTEDATA_H
diff --git a/src/corelib/tools/qcache.qdoc b/src/corelib/tools/qcache.qdoc
new file mode 100644
index 0000000000..d443c9381b
--- /dev/null
+++ b/src/corelib/tools/qcache.qdoc
@@ -0,0 +1,244 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QCache
+ \brief The QCache class is a template class that provides a cache.
+
+ \ingroup tools
+ \ingroup shared
+
+ \reentrant
+
+ QCache\<Key, T\> defines a cache that stores objects of type T
+ associated with keys of type Key. For example, here's the
+ definition of a cache that stores objects of type Employee
+ associated with an integer key:
+
+ \snippet doc/src/snippets/code/doc_src_qcache.qdoc 0
+
+ Here's how to insert an object in the cache:
+
+ \snippet doc/src/snippets/code/doc_src_qcache.qdoc 1
+
+ The advantage of using QCache over some other key-based data
+ structure (such as QMap or QHash) is that QCache automatically
+ takes ownership of the objects that are inserted into the cache and
+ deletes them to make room for new objects, if necessary. When
+ inserting an object into the cache, you can specify a \e{cost},
+ which should bear some approximate relationship to the amount of
+ memory taken by the object. When the sum of all objects' costs
+ (totalCost()) exceeds the cache's limit (maxCost()), QCache starts
+ deleting objects in the cache to keep under the limit, starting with
+ less recently accessed objects.
+
+ By default, QCache's maxCost() is 100. You can specify a
+ different value in the QCache constructor:
+
+ \snippet doc/src/snippets/code/doc_src_qcache.qdoc 2
+
+ Each time you call insert(), you can specify a cost as third
+ argument (after the key and a pointer to the object to insert).
+ After the call, the inserted object is owned by the QCache, which
+ may delete it at any time to make room for other objects.
+
+ To look up objects in the cache, use object() or
+ operator[](). This function looks up an object by its key, and
+ returns either a pointer to the cached object (which is owned by
+ the cache) or 0.
+
+ If you want to remove an object from the cache for a particular key,
+ call remove(). This will also delete the object. If you want to
+ remove an object from the cache without the QCache deleting it, use
+ take().
+
+ \sa QPixmapCache, QHash, QMap
+*/
+
+/*! \fn QCache::QCache(int maxCost = 100)
+
+ Constructs a cache whose contents will never have a total cost
+ greater than \a maxCost.
+*/
+
+/*! \fn QCache::~QCache()
+
+ Destroys the cache. Deletes all the objects in the cache.
+*/
+
+/*! \fn int QCache::maxCost() const
+
+ Returns the maximum allowed total cost of the cache.
+
+ \sa setMaxCost(), totalCost()
+*/
+
+/*! \fn void QCache::setMaxCost(int cost)
+
+ Sets the maximum allowed total cost of the cache to \a cost. If
+ the current total cost is greater than \a cost, some objects are
+ deleted immediately.
+
+ \sa maxCost(), totalCost()
+*/
+
+/*! \fn int QCache::totalCost() const
+
+ Returns the total cost of the objects in the cache.
+
+ This value is normally below maxCost(), but QCache makes an
+ exception for Qt's \l{implicitly shared} classes. If a cached
+ object shares its internal data with another instance, QCache may
+ keep the object lying around, possibly contributing to making
+ totalCost() larger than maxCost().
+
+ \sa setMaxCost()
+*/
+
+/*! \fn int QCache::size() const
+
+ Returns the number of objects in the cache.
+
+ \sa isEmpty()
+*/
+
+/*! \fn int QCache::count() const
+
+ Same as size().
+*/
+
+/*! \fn bool QCache::isEmpty() const
+
+ Returns true if the cache contains no objects; otherwise
+ returns false.
+
+ \sa size()
+*/
+
+/*! \fn QList<Key> QCache::keys() const
+
+ Returns a list of the keys in the cache.
+*/
+
+/*! \fn void QCache::clear();
+
+ Deletes all the objects in the cache.
+
+ \sa remove(), take()
+*/
+
+
+/*! \fn bool QCache::insert(const Key &key, T *object, int cost = 1)
+
+ Inserts \a object into the cache with key \a key and
+ associated cost \a cost. Any object with the same key already in
+ the cache will be removed.
+
+ After this call, \a object is owned by the QCache and may be
+ deleted at any time. In particular, if \a cost is greater than
+ maxCost(), the object will be deleted immediately.
+
+ The function returns true if the object was inserted into the
+ cache; otherwise it returns false.
+
+ \sa take(), remove()
+*/
+
+/*! \fn T *QCache::object(const Key &key) const
+
+ Returns the object associated with key \a key, or 0 if the key does
+ not exist in the cache.
+
+ \warning The returned object is owned by QCache and may be
+ deleted at any time.
+
+ \sa take(), remove()
+*/
+
+/*! \fn bool QCache::contains(const Key &key) const
+
+ Returns true if the cache contains an object associated with key \a
+ key; otherwise returns false.
+
+ \sa take(), remove()
+*/
+
+/*! \fn T *QCache::operator[](const Key &key) const
+
+ Returns the object associated with key \a key, or 0 if the key does
+ not exist in the cache.
+
+ This is the same as object().
+
+ \warning The returned object is owned by QCache and may be
+ deleted at any time.
+*/
+
+/*! \fn bool QCache::remove(const Key &key)
+
+ Deletes the object associated with key \a key. Returns true if the
+ object was found in the cache; otherwise returns false.
+
+ \sa take(), clear()
+*/
+
+/*! \fn T *QCache::take(const Key &key)
+
+ Takes the object associated with key \a key out of the cache
+ without deleting it. Returns a pointer to the object taken out, or
+ 0 if the key does not exist in the cache.
+
+ The ownership of the returned object is passed to the caller.
+
+ \sa remove()
+*/
+
+/*!
+ \fn QCache::QCache(int maxCost, int dummy)
+
+ Use QCache(int) instead.
+*/
+
+/*!
+ \fn T *QCache::find(const Key &key) const
+
+ Use object() instead.
+*/
diff --git a/src/corelib/tools/qchar.cpp b/src/corelib/tools/qchar.cpp
index 8f115d5e66..f20d61f2f0 100644
--- a/src/corelib/tools/qchar.cpp
+++ b/src/corelib/tools/qchar.cpp
@@ -70,7 +70,7 @@ QT_BEGIN_NAMESPACE
/*! \class QLatin1Char
\brief The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
- \ingroup text
+ \ingroup string-processing
This class is only useful to avoid the codec for C strings business
in the QChar(ch) constructor. You can avoid it by writing
@@ -104,7 +104,7 @@ QT_BEGIN_NAMESPACE
\class QChar
\brief The QChar class provides a 16-bit Unicode character.
- \ingroup text
+ \ingroup string-processing
\reentrant
In Qt, Unicode characters are 16-bit entities without any markup
@@ -1321,7 +1321,7 @@ QDataStream &operator>>(QDataStream &in, QChar &chr)
chr.unicode() = ushort(u);
return in;
}
-#endif
+#endif // QT_NO_DATASTREAM
/*!
\fn ushort & QChar::unicode()
@@ -1421,16 +1421,15 @@ QDataStream &operator>>(QDataStream &in, QChar &chr)
// ---------------------------------------------------------------------------
-static QString decomposeHelper
- (const QString &str, bool canonical, QChar::UnicodeVersion version)
+static void decomposeHelper(QString *str, bool canonical, QChar::UnicodeVersion version, int from)
{
unsigned short buffer[3];
- QString s = str;
+ QString &s = *str;
- const unsigned short *utf16 = s.utf16();
+ const unsigned short *utf16 = reinterpret_cast<unsigned short *>(s.data());
const unsigned short *uc = utf16 + s.length();
- while (uc != utf16) {
+ while (uc != utf16 + from) {
uint ucs4 = *(--uc);
if (QChar(ucs4).isLowSurrogate() && uc != utf16) {
ushort high = *(uc - 1);
@@ -1450,11 +1449,9 @@ static QString decomposeHelper
s.replace(uc - utf16, ucs4 > 0x10000 ? 2 : 1, (const QChar *)d, length);
// since the insert invalidates the pointers and we do decomposition recursive
int pos = uc - utf16;
- utf16 = s.utf16();
+ utf16 = reinterpret_cast<unsigned short *>(s.data());
uc = utf16 + pos + length;
}
-
- return s;
}
@@ -1489,21 +1486,21 @@ static ushort ligatureHelper(ushort u1, ushort u2)
return 0;
}
-static QString composeHelper(const QString &str)
+static void composeHelper(QString *str, int from)
{
- QString s = str;
+ QString &s = *str;
- if (s.length() < 2)
- return s;
+ if (s.length() - from < 2)
+ return;
// the loop can partly ignore high Unicode as all ligatures are in the BMP
int starter = 0;
int lastCombining = 0;
- int pos = 0;
+ int pos = from;
while (pos < s.length()) {
- uint uc = s.utf16()[pos];
+ uint uc = s.at(pos).unicode();
if (QChar(uc).isHighSurrogate() && pos < s.length()-1) {
- ushort low = s.utf16()[pos+1];
+ ushort low = s.at(pos+1).unicode();
if (QChar(low).isLowSurrogate()) {
uc = QChar::surrogateToUcs4(uc, low);
++pos;
@@ -1512,7 +1509,7 @@ static QString composeHelper(const QString &str)
int combining = QChar::combiningClass(uc);
if (starter == pos - 1 || combining > lastCombining) {
// allowed to form ligature with S
- QChar ligature = ligatureHelper(s.utf16()[starter], uc);
+ QChar ligature = ligatureHelper(s.at(starter).unicode(), uc);
if (ligature.unicode()) {
s[starter] = ligature;
s.remove(pos, 1);
@@ -1524,16 +1521,14 @@ static QString composeHelper(const QString &str)
lastCombining = combining;
++pos;
}
- return s;
}
-static QString canonicalOrderHelper
- (const QString &str, QChar::UnicodeVersion version)
+static void canonicalOrderHelper(QString *str, QChar::UnicodeVersion version, int from)
{
- QString s = str;
+ QString &s = *str;
const int l = s.length()-1;
- int pos = 0;
+ int pos = from;
while (pos < l) {
int p2 = pos+1;
uint u1 = s.at(pos).unicode();
@@ -1593,7 +1588,6 @@ static QString canonicalOrderHelper
++pos;
}
}
- return s;
}
int QT_FASTCALL QUnicodeTables::script(unsigned int uc)
diff --git a/src/corelib/tools/qcontiguouscache.cpp b/src/corelib/tools/qcontiguouscache.cpp
new file mode 100644
index 0000000000..7a46d83966
--- /dev/null
+++ b/src/corelib/tools/qcontiguouscache.cpp
@@ -0,0 +1,432 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qcontiguouscache.h"
+#ifdef QT_QCONTIGUOUSCACHE_DEBUG
+#include <QDebug>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#ifdef QT_QCONTIGUOUSCACHE_DEBUG
+void QContiguousCacheData::dump() const
+{
+ qDebug() << "capacity:" << alloc;
+ qDebug() << "count:" << count;
+ qDebug() << "start:" << start;
+ qDebug() << "offset:" << offset;
+}
+#endif
+
+/*! \class QContiguousCache
+ \brief The QContiguousCache class is a template class that provides a contiguous cache.
+ \ingroup tools
+ \ingroup shared
+ \reentrant
+ \since 4.6
+
+ The QContiguousCache class provides an efficient way of caching items for
+ display in a user interface view. Unlike QCache, it adds a restriction
+ that elements within the cache are contiguous. This has the advantage
+ of matching how user interface views most commonly request data, as
+ a set of rows localized around the current scrolled position. This
+ restriction allows the cache to consume less memory and processor
+ cycles than QCache. The QContiguousCache class also can provide
+ an upper bound on memory usage via setCapacity().
+
+ The simplest way of using a contiguous cache is to use the append()
+ and prepend().
+
+\code
+MyRecord record(int row) const
+{
+ Q_ASSERT(row >= 0 && row < count());
+
+ while(row > cache.lastIndex())
+ cache.append(slowFetchRecord(cache.lastIndex()+1));
+ while(row < cache.firstIndex())
+ cache.prepend(slowFetchRecord(cache.firstIndex()-1));
+
+ return cache.at(row);
+}
+\endcode
+
+ If the cache is full then the item at the opposite end of the cache from
+ where the new item is appended or prepended will be removed.
+
+ This usage can be further optimized by using the insert() function
+ in the case where the requested row is a long way from the currently cached
+ items. If there is a gap between where the new item is inserted and the currently
+ cached items then the existing cached items are first removed to retain
+ the contiguous nature of the cache. Hence it is important to take some care then
+ when using insert() in order to avoid unwanted clearing of the cache.
+
+ The range of valid indexes for the QContiguousCache class are from
+ 0 to INT_MAX. Calling prepend() such that the first index would become less
+ than 0 or append() such that the last index would become greater
+ than INT_MAX can result in the indexes of the cache being invalid.
+ When the cache indexes are invalid it is important to call
+ normalizeIndexes() before calling any of containsIndex(), firstIndex(),
+ lastIndex(), at() or \l{QContiguousCache::operator[]()}{operator[]()}.
+ Calling these functions when the cache has invalid indexes will result in
+ undefined behavior. The indexes can be checked by using areIndexesValid()
+
+ In most cases the indexes will not exceed 0 to INT_MAX, and
+ normalizeIndexes() will not need to be used.
+
+ See the \l{Contiguous Cache Example}{Contiguous Cache} example.
+*/
+
+/*! \fn QContiguousCache::QContiguousCache(int capacity)
+
+ Constructs a cache with the given \a capacity.
+
+ \sa setCapacity()
+*/
+
+/*! \fn QContiguousCache::QContiguousCache(const QContiguousCache<T> &other)
+
+ Constructs a copy of \a other.
+
+ This operation takes \l{constant time}, because QContiguousCache is
+ \l{implicitly shared}. This makes returning a QContiguousCache from a
+ function very fast. If a shared instance is modified, it will be
+ copied (copy-on-write), and that takes \l{linear time}.
+
+ \sa operator=()
+*/
+
+/*! \fn QContiguousCache::~QContiguousCache()
+
+ Destroys the cache.
+*/
+
+/*! \fn void QContiguousCache::detach()
+
+ \internal
+*/
+
+/*! \fn bool QContiguousCache::isDetached() const
+
+ \internal
+*/
+
+/*! \fn void QContiguousCache::setSharable(bool sharable)
+
+ \internal
+*/
+
+/*! \fn QContiguousCache<T> &QContiguousCache::operator=(const QContiguousCache<T> &other)
+
+ Assigns \a other to this cache and returns a reference to this cache.
+*/
+
+/*! \fn bool QContiguousCache::operator==(const QContiguousCache<T> &other) const
+
+ Returns true if \a other is equal to this cache; otherwise returns false.
+
+ Two caches are considered equal if they contain the same values at the same
+ indexes. This function requires the value type to implement the \c operator==().
+
+ \sa operator!=()
+*/
+
+/*! \fn bool QContiguousCache::operator!=(const QContiguousCache<T> &other) const
+
+ Returns true if \a other is not equal to this cache; otherwise
+ returns false.
+
+ Two caches are considered equal if they contain the same values at the same
+ indexes. This function requires the value type to implement the \c operator==().
+
+ \sa operator==()
+*/
+
+/*! \fn int QContiguousCache::capacity() const
+
+ Returns the number of items the cache can store before it is full.
+ When a cache contains a number of items equal to its capacity, adding new
+ items will cause items farthest from the added item to be removed.
+
+ \sa setCapacity(), size()
+*/
+
+/*! \fn int QContiguousCache::count() const
+
+ Same as size().
+*/
+
+/*! \fn int QContiguousCache::size() const
+
+ Returns the number of items contained within the cache.
+
+ \sa capacity()
+*/
+
+/*! \fn bool QContiguousCache::isEmpty() const
+
+ Returns true if no items are stored within the cache.
+
+ \sa size(), capacity()
+*/
+
+/*! \fn bool QContiguousCache::isFull() const
+
+ Returns true if the number of items stored within the cache is equal
+ to the capacity of the cache.
+
+ \sa size(), capacity()
+*/
+
+/*! \fn int QContiguousCache::available() const
+
+ Returns the number of items that can be added to the cache before it becomes full.
+
+ \sa size(), capacity(), isFull()
+*/
+
+/*! \fn void QContiguousCache::clear()
+
+ Removes all items from the cache. The capacity is unchanged.
+*/
+
+/*! \fn void QContiguousCache::setCapacity(int size)
+
+ Sets the capacity of the cache to the given \a size. A cache can hold a
+ number of items equal to its capacity. When inserting, appending or prepending
+ items to the cache, if the cache is already full then the item farthest from
+ the added item will be removed.
+
+ If the given \a size is smaller than the current count of items in the cache
+ then only the last \a size items from the cache will remain.
+
+ \sa capacity(), isFull()
+*/
+
+/*! \fn const T &QContiguousCache::at(int i) const
+
+ Returns the item at index position \a i in the cache. \a i must
+ be a valid index position in the cache (i.e, firstIndex() <= \a i <= lastIndex()).
+
+ The indexes in the cache refer to the number of positions the item is from the
+ first item appended into the cache. That is to say a cache with a capacity of
+ 100, that has had 150 items appended will have a valid index range of
+ 50 to 149. This allows inserting and retrieving items into the cache based
+ on a theoretical infinite list
+
+ \sa firstIndex(), lastIndex(), insert(), operator[]()
+*/
+
+/*! \fn T &QContiguousCache::operator[](int i)
+
+ Returns the item at index position \a i as a modifiable reference. If
+ the cache does not contain an item at the given index position \a i
+ then it will first insert an empty item at that position.
+
+ In most cases it is better to use either at() or insert().
+
+ \note This non-const overload of operator[] requires QContiguousCache
+ to make a deep copy. Use at() for read-only access to a non-const
+ QContiguousCache.
+
+ \sa insert(), at()
+*/
+
+/*! \fn const T &QContiguousCache::operator[](int i) const
+
+ \overload
+
+ Same as at(\a i).
+*/
+
+/*! \fn void QContiguousCache::append(const T &value)
+
+ Inserts \a value at the end of the cache. If the cache is already full
+ the item at the start of the cache will be removed.
+
+ \sa prepend(), insert(), isFull()
+*/
+
+/*! \fn void QContiguousCache::prepend(const T &value)
+
+ Inserts \a value at the start of the cache. If the cache is already full
+ the item at the end of the cache will be removed.
+
+ \sa append(), insert(), isFull()
+*/
+
+/*! \fn void QContiguousCache::insert(int i, const T &value)
+
+ Inserts the \a value at the index position \a i. If the cache already contains
+ an item at \a i then that value is replaced. If \a i is either one more than
+ lastIndex() or one less than firstIndex() it is the equivalent to an append()
+ or a prepend().
+
+ If the given index \a i is not within the current range of the cache nor adjacent
+ to the bounds of the cache's index range, the cache is first cleared before
+ inserting the item. At this point the cache will have a size of 1. It is
+ worthwhile taking effort to insert items in an order that starts adjacent
+ to the current index range for the cache.
+
+ The range of valid indexes for the QContiguousCache class are from
+ 0 to INT_MAX. Inserting outside of this range has undefined behavior.
+
+
+ \sa prepend(), append(), isFull(), firstIndex(), lastIndex()
+*/
+
+/*! \fn bool QContiguousCache::containsIndex(int i) const
+
+ Returns true if the cache's index range includes the given index \a i.
+
+ \sa firstIndex(), lastIndex()
+*/
+
+/*! \fn int QContiguousCache::firstIndex() const
+
+ Returns the first valid index in the cache. The index will be invalid if the
+ cache is empty.
+
+ \sa capacity(), size(), lastIndex()
+*/
+
+/*! \fn int QContiguousCache::lastIndex() const
+
+ Returns the last valid index in the cache. The index will be invalid if the cache is empty.
+
+ \sa capacity(), size(), firstIndex()
+*/
+
+
+/*! \fn T &QContiguousCache::first()
+
+ Returns a reference to the first item in the cache. This function
+ assumes that the cache isn't empty.
+
+ \sa last(), isEmpty()
+*/
+
+/*! \fn T &QContiguousCache::last()
+
+ Returns a reference to the last item in the cache. This function
+ assumes that the cache isn't empty.
+
+ \sa first(), isEmpty()
+*/
+
+/*! \fn const T& QContiguousCache::first() const
+
+ \overload
+*/
+
+/*! \fn const T& QContiguousCache::last() const
+
+ \overload
+*/
+
+/*! \fn void QContiguousCache::removeFirst()
+
+ Removes the first item from the cache. This function assumes that
+ the cache isn't empty.
+
+ \sa removeLast()
+*/
+
+/*! \fn void QContiguousCache::removeLast()
+
+ Removes the last item from the cache. This function assumes that
+ the cache isn't empty.
+
+ \sa removeFirst()
+*/
+
+/*! \fn T QContiguousCache::takeFirst()
+
+ Removes the first item in the cache and returns it. This function
+ assumes that the cache isn't empty.
+
+ If you don't use the return value, removeFirst() is more efficient.
+
+ \sa takeLast(), removeFirst()
+*/
+
+/*! \fn T QContiguousCache::takeLast()
+
+ Removes the last item in the cache and returns it. This function
+ assumes that the cache isn't empty.
+
+ If you don't use the return value, removeLast() is more efficient.
+
+ \sa takeFirst(), removeLast()
+*/
+
+/*! \fn void QContiguousCache::normalizeIndexes()
+
+ Moves the first index and last index of the cache
+ such that they point to valid indexes. The function does not modify
+ the contents of the cache or the ordering of elements within the cache.
+
+ It is provided so that index overflows can be corrected when using the
+ cache as a circular buffer.
+
+ \code
+ QContiguousCache<int> cache(10);
+ cache.insert(INT_MAX, 1); // cache contains one value and has valid indexes, INT_MAX to INT_MAX
+ cache.append(2); // cache contains two values but does not have valid indexes.
+ cache.normalizeIndexes(); // cache has two values, 1 and 2. New first index will be in the range of 0 to capacity().
+ \endcode
+
+ \sa areIndexesValid(), append(), prepend()
+*/
+
+/*! \fn bool QContiguousCache::areIndexesValid() const
+
+ Returns whether the indexes for items stored in the cache are valid.
+ Indexes can become invalid if items are appended after the index position
+ INT_MAX or prepended before the index position 0. This is only expected
+ to occur in very long lived circular buffer style usage of the
+ contiguous cache. Indexes can be made valid again by calling
+ normalizeIndexs().
+
+ \sa normalizeIndexes(), append(), prepend()
+*/
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qcontiguouscache.h b/src/corelib/tools/qcontiguouscache.h
new file mode 100644
index 0000000000..8d44fc4d4a
--- /dev/null
+++ b/src/corelib/tools/qcontiguouscache.h
@@ -0,0 +1,437 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCONTIGUOUSCACHE_H
+#define QCONTIGUOUSCACHE_H
+
+#include <QtCore/qatomic.h>
+#include <limits.h>
+#include <new>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+#undef QT_QCONTIGUOUSCACHE_DEBUG
+QT_MODULE(Core)
+
+
+struct Q_CORE_EXPORT QContiguousCacheData
+{
+ QBasicAtomicInt ref;
+ int alloc;
+ int count;
+ int start;
+ int offset;
+ uint sharable : 1;
+
+#ifdef QT_QCONTIGUOUSCACHE_DEBUG
+ void dump() const;
+#endif
+};
+
+template <typename T>
+struct QContiguousCacheTypedData
+{
+ QBasicAtomicInt ref;
+ int alloc;
+ int count;
+ int start;
+ int offset;
+ uint sharable : 1;
+ // uint unused : 31;
+
+ // total is 24 bytes (HP-UX aCC: 40 bytes)
+ // the next entry is already aligned to 8 bytes
+ // there will be an 8 byte gap here if T requires 16-byte alignment
+ // (such as long double on 64-bit platforms, __int128, __float128)
+
+ T array[1];
+};
+
+template<typename T>
+class QContiguousCache {
+ typedef QContiguousCacheTypedData<T> Data;
+ union { QContiguousCacheData *p; QContiguousCacheTypedData<T> *d; };
+public:
+ explicit QContiguousCache(int capacity = 0);
+ QContiguousCache(const QContiguousCache<T> &v) : d(v.d) { d->ref.ref(); if (!d->sharable) detach_helper(); }
+
+ inline ~QContiguousCache() { if (!d) return; if (!d->ref.deref()) free(d); }
+
+ inline void detach() { if (d->ref != 1) detach_helper(); }
+ inline bool isDetached() const { return d->ref == 1; }
+ inline void setSharable(bool sharable) { if (!sharable) detach(); d->sharable = sharable; }
+
+ QContiguousCache<T> &operator=(const QContiguousCache<T> &other);
+ bool operator==(const QContiguousCache<T> &other) const;
+ inline bool operator!=(const QContiguousCache<T> &other) const { return !(*this == other); }
+
+ inline int capacity() const {return d->alloc; }
+ inline int count() const { return d->count; }
+ inline int size() const { return d->count; }
+
+ inline bool isEmpty() const { return d->count == 0; }
+ inline bool isFull() const { return d->count == d->alloc; }
+ inline int available() const { return d->alloc - d->count; }
+
+ void clear();
+ void setCapacity(int size);
+
+ const T &at(int pos) const;
+ T &operator[](int i);
+ const T &operator[](int i) const;
+
+ void append(const T &value);
+ void prepend(const T &value);
+ void insert(int pos, const T &value);
+
+ inline bool containsIndex(int pos) const { return pos >= d->offset && pos - d->offset < d->count; }
+ inline int firstIndex() const { return d->offset; }
+ inline int lastIndex() const { return d->offset + d->count - 1; }
+
+ inline const T &first() const { Q_ASSERT(!isEmpty()); return d->array[d->start]; }
+ inline const T &last() const { Q_ASSERT(!isEmpty()); return d->array[(d->start + d->count -1) % d->alloc]; }
+ inline T &first() { Q_ASSERT(!isEmpty()); detach(); return d->array[d->start]; }
+ inline T &last() { Q_ASSERT(!isEmpty()); detach(); return d->array[(d->start + d->count -1) % d->alloc]; }
+
+ void removeFirst();
+ T takeFirst();
+ void removeLast();
+ T takeLast();
+
+ inline bool areIndexesValid() const
+ { return d->offset >= 0 && d->offset < INT_MAX - d->count && (d->offset % d->alloc) == d->start; }
+
+ inline void normalizeIndexes() { d->offset = d->start; }
+
+#ifdef QT_QCONTIGUOUSCACHE_DEBUG
+ void dump() const { p->dump(); }
+#endif
+private:
+ void detach_helper();
+
+ QContiguousCacheData *malloc(int aalloc);
+ void free(Data *x);
+ int sizeOfTypedData() {
+ // this is more or less the same as sizeof(Data), except that it doesn't
+ // count the padding at the end
+ return reinterpret_cast<const char *>(&(reinterpret_cast<const Data *>(this))->array[1]) - reinterpret_cast<const char *>(this);
+ }
+};
+
+template <typename T>
+void QContiguousCache<T>::detach_helper()
+{
+ union { QContiguousCacheData *p; QContiguousCacheTypedData<T> *d; } x;
+
+ x.p = malloc(d->alloc);
+ x.d->ref = 1;
+ x.d->count = d->count;
+ x.d->start = d->start;
+ x.d->offset = d->offset;
+ x.d->alloc = d->alloc;
+ x.d->sharable = true;
+
+ T *dest = x.d->array + x.d->start;
+ T *src = d->array + d->start;
+ int oldcount = x.d->count;
+ while (oldcount--) {
+ if (QTypeInfo<T>::isComplex) {
+ new (dest) T(*src);
+ } else {
+ *dest = *src;
+ }
+ dest++;
+ if (dest == x.d->array + x.d->alloc)
+ dest = x.d->array;
+ src++;
+ if (src == d->array + d->alloc)
+ src = d->array;
+ }
+
+ if (!d->ref.deref())
+ free(d);
+ d = x.d;
+}
+
+template <typename T>
+void QContiguousCache<T>::setCapacity(int asize)
+{
+ if (asize == d->alloc)
+ return;
+ detach();
+ union { QContiguousCacheData *p; QContiguousCacheTypedData<T> *d; } x;
+ x.p = malloc(asize);
+ x.d->alloc = asize;
+ x.d->count = qMin(d->count, asize);
+ x.d->offset = d->offset + d->count - x.d->count;
+ x.d->start = x.d->offset % x.d->alloc;
+ T *dest = x.d->array + (x.d->start + x.d->count-1) % x.d->alloc;
+ T *src = d->array + (d->start + d->count-1) % d->alloc;
+ int oldcount = x.d->count;
+ while (oldcount--) {
+ if (QTypeInfo<T>::isComplex) {
+ new (dest) T(*src);
+ } else {
+ *dest = *src;
+ }
+ if (dest == x.d->array)
+ dest = x.d->array + x.d->alloc;
+ dest--;
+ if (src == d->array)
+ src = d->array + d->alloc;
+ src--;
+ }
+ /* free old */
+ free(d);
+ d = x.d;
+}
+
+template <typename T>
+void QContiguousCache<T>::clear()
+{
+ if (d->ref == 1) {
+ if (QTypeInfo<T>::isComplex) {
+ int oldcount = d->count;
+ T * i = d->array + d->start;
+ T * e = d->array + d->alloc;
+ while (oldcount--) {
+ i->~T();
+ i++;
+ if (i == e)
+ i = d->array;
+ }
+ }
+ d->count = d->start = d->offset = 0;
+ } else {
+ union { QContiguousCacheData *p; QContiguousCacheTypedData<T> *d; } x;
+ x.p = malloc(d->alloc);
+ x.d->ref = 1;
+ x.d->alloc = d->alloc;
+ x.d->count = x.d->start = x.d->offset = 0;
+ x.d->sharable = true;
+ if (!d->ref.deref()) free(d);
+ d = x.d;
+ }
+}
+
+template <typename T>
+inline QContiguousCacheData *QContiguousCache<T>::malloc(int aalloc)
+{
+ return static_cast<QContiguousCacheData *>(qMalloc(sizeOfTypedData() + (aalloc - 1) * sizeof(T)));
+}
+
+template <typename T>
+QContiguousCache<T>::QContiguousCache(int cap)
+{
+ p = malloc(cap);
+ d->ref = 1;
+ d->alloc = cap;
+ d->count = d->start = d->offset = 0;
+ d->sharable = true;
+}
+
+template <typename T>
+QContiguousCache<T> &QContiguousCache<T>::operator=(const QContiguousCache<T> &other)
+{
+ other.d->ref.ref();
+ if (!d->ref.deref())
+ free(d);
+ d = other.d;
+ if (!d->sharable)
+ detach_helper();
+ return *this;
+}
+
+template <typename T>
+bool QContiguousCache<T>::operator==(const QContiguousCache<T> &other) const
+{
+ if (other.d == d)
+ return true;
+ if (other.d->start != d->start
+ || other.d->count != d->count
+ || other.d->offset != d->offset
+ || other.d->alloc != d->alloc)
+ return false;
+ for (int i = firstIndex(); i <= lastIndex(); ++i)
+ if (!(at(i) == other.at(i)))
+ return false;
+ return true;
+}
+
+template <typename T>
+void QContiguousCache<T>::free(Data *x)
+{
+ if (QTypeInfo<T>::isComplex) {
+ int oldcount = d->count;
+ T * i = d->array + d->start;
+ T * e = d->array + d->alloc;
+ while (oldcount--) {
+ i->~T();
+ i++;
+ if (i == e)
+ i = d->array;
+ }
+ }
+ qFree(x);
+}
+template <typename T>
+void QContiguousCache<T>::append(const T &value)
+{
+ detach();
+ if (QTypeInfo<T>::isComplex) {
+ if (d->count == d->alloc)
+ (d->array + (d->start+d->count) % d->alloc)->~T();
+ new (d->array + (d->start+d->count) % d->alloc) T(value);
+ } else {
+ d->array[(d->start+d->count) % d->alloc] = value;
+ }
+
+ if (d->count == d->alloc) {
+ d->start++;
+ d->start %= d->alloc;
+ d->offset++;
+ } else {
+ d->count++;
+ }
+}
+
+template<typename T>
+void QContiguousCache<T>::prepend(const T &value)
+{
+ detach();
+ if (d->start)
+ d->start--;
+ else
+ d->start = d->alloc-1;
+ d->offset--;
+
+ if (d->count != d->alloc)
+ d->count++;
+ else
+ if (d->count == d->alloc)
+ (d->array + d->start)->~T();
+
+ if (QTypeInfo<T>::isComplex)
+ new (d->array + d->start) T(value);
+ else
+ d->array[d->start] = value;
+}
+
+template<typename T>
+void QContiguousCache<T>::insert(int pos, const T &value)
+{
+ Q_ASSERT_X(pos >= 0 && pos < INT_MAX, "QContiguousCache<T>::insert", "index out of range");
+ detach();
+ if (containsIndex(pos)) {
+ if(QTypeInfo<T>::isComplex)
+ new (d->array + pos % d->alloc) T(value);
+ else
+ d->array[pos % d->alloc] = value;
+ } else if (pos == d->offset-1)
+ prepend(value);
+ else if (pos == d->offset+d->count)
+ append(value);
+ else {
+ // we don't leave gaps.
+ clear();
+ d->offset = pos;
+ d->start = pos % d->alloc;
+ d->count = 1;
+ if (QTypeInfo<T>::isComplex)
+ new (d->array + d->start) T(value);
+ else
+ d->array[d->start] = value;
+ }
+}
+
+template <typename T>
+inline const T &QContiguousCache<T>::at(int pos) const
+{ Q_ASSERT_X(pos >= d->offset && pos - d->offset < d->count, "QContiguousCache<T>::at", "index out of range"); return d->array[pos % d->alloc]; }
+template <typename T>
+inline const T &QContiguousCache<T>::operator[](int pos) const
+{ Q_ASSERT_X(pos >= d->offset && pos - d->offset < d->count, "QContiguousCache<T>::at", "index out of range"); return d->array[pos % d->alloc]; }
+
+template <typename T>
+inline T &QContiguousCache<T>::operator[](int pos)
+{
+ detach();
+ if (!containsIndex(pos))
+ insert(pos, T());
+ return d->array[pos % d->alloc];
+}
+
+template <typename T>
+inline void QContiguousCache<T>::removeFirst()
+{
+ Q_ASSERT(d->count > 0);
+ detach();
+ d->count--;
+ if (QTypeInfo<T>::isComplex)
+ (d->array + d->start)->~T();
+ d->start = (d->start + 1) % d->alloc;
+ d->offset++;
+}
+
+template <typename T>
+inline void QContiguousCache<T>::removeLast()
+{
+ Q_ASSERT(d->count > 0);
+ detach();
+ d->count--;
+ if (QTypeInfo<T>::isComplex)
+ (d->array + (d->start + d->count) % d->alloc)->~T();
+}
+
+template <typename T>
+inline T QContiguousCache<T>::takeFirst()
+{ T t = first(); removeFirst(); return t; }
+
+template <typename T>
+inline T QContiguousCache<T>::takeLast()
+{ T t = last(); removeLast(); return t; }
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/corelib/tools/qcryptographichash.cpp b/src/corelib/tools/qcryptographichash.cpp
index 3cc5fbab58..b37d61c872 100644
--- a/src/corelib/tools/qcryptographichash.cpp
+++ b/src/corelib/tools/qcryptographichash.cpp
@@ -41,6 +41,10 @@
#include <qcryptographichash.h>
+#ifdef Q_OS_SYMBIAN
+#define _MD5_H_ // Needed to disable system header
+#endif
+
#include "../../3rdparty/md5/md5.h"
#include "../../3rdparty/md5/md5.cpp"
#include "../../3rdparty/md4/md4.h"
diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp
index 47b7a0a248..d2b7135aa8 100644
--- a/src/corelib/tools/qdatetime.cpp
+++ b/src/corelib/tools/qdatetime.cpp
@@ -49,7 +49,7 @@
#include "qregexp.h"
#include "qdebug.h"
#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
-#include <windows.h>
+#include <qt_windows.h>
#endif
#ifndef Q_WS_WIN
#include <locale.h>
@@ -193,8 +193,6 @@ static QString fmtDateTime(const QString& f, const QTime* dt = 0, const QDate* d
\reentrant
\brief The QDate class provides date functions.
- \ingroup time
- \mainclass
A QDate object contains a calendar date, i.e. year, month, and day
numbers, in the Gregorian calendar. (see \l{QDate G and J} {Use of
@@ -1411,8 +1409,6 @@ void QDate::julianToGregorian(uint jd, int &y, int &m, int &d)
\brief The QTime class provides clock time functions.
- \ingroup time
- \mainclass
A QTime object contains a clock time, i.e. the number of hours,
minutes, seconds, and milliseconds since midnight. It can read the
@@ -1842,14 +1838,14 @@ QTime QTime::currentTime()
#else
t = localtime(&ltime);
#endif
-
+ Q_CHECK_PTR(t);
+
ct.mds = MSECS_PER_HOUR * t->tm_hour + MSECS_PER_MIN * t->tm_min + 1000 * t->tm_sec
+ tv.tv_usec / 1000;
#else
time_t ltime; // no millisecond resolution
::time(&ltime);
- tm *t = 0;
- localtime(&ltime);
+ const tm *const t = localtime(&ltime);
ct.mds = MSECS_PER_HOUR * t->tm_hour + MSECS_PER_MIN * t->tm_min + 1000 * t->tm_sec;
#endif
return ct;
@@ -2075,8 +2071,6 @@ int QTime::elapsed() const
\reentrant
\brief The QDateTime class provides date and time functions.
- \ingroup time
- \mainclass
A QDateTime object contains a calendar date and a clock time (a
"datetime"). It is a combination of the QDate and QTime classes.
@@ -2200,8 +2194,8 @@ int QTime::elapsed() const
\sa isValid()
*/
QDateTime::QDateTime()
+ : d(new QDateTimePrivate)
{
- d = new QDateTimePrivate;
}
@@ -2211,8 +2205,8 @@ QDateTime::QDateTime()
*/
QDateTime::QDateTime(const QDate &date)
+ : d(new QDateTimePrivate)
{
- d = new QDateTimePrivate;
d->date = date;
d->time = QTime(0, 0, 0);
}
@@ -2225,8 +2219,8 @@ QDateTime::QDateTime(const QDate &date)
*/
QDateTime::QDateTime(const QDate &date, const QTime &time, Qt::TimeSpec spec)
+ : d(new QDateTimePrivate)
{
- d = new QDateTimePrivate;
d->date = date;
d->time = date.isValid() && !time.isValid() ? QTime(0, 0, 0) : time;
d->spec = (spec == Qt::UTC) ? QDateTimePrivate::UTC : QDateTimePrivate::LocalUnknown;
@@ -2237,9 +2231,8 @@ QDateTime::QDateTime(const QDate &date, const QTime &time, Qt::TimeSpec spec)
*/
QDateTime::QDateTime(const QDateTime &other)
+ : d(other.d)
{
- d = other.d;
- d->ref.ref();
}
/*!
@@ -2247,8 +2240,6 @@ QDateTime::QDateTime(const QDateTime &other)
*/
QDateTime::~QDateTime()
{
- if (!d->ref.deref())
- delete d;
}
/*!
@@ -2258,7 +2249,7 @@ QDateTime::~QDateTime()
QDateTime &QDateTime::operator=(const QDateTime &other)
{
- qAtomicAssign(d, other.d);
+ d = other.d;
return *this;
}
@@ -2504,16 +2495,9 @@ QString QDateTime::toString(Qt::DateFormat f) const
buf += QLatin1Char(' ');
buf += QString::number(d->date.day());
#else
- QString winstr;
- QT_WA({
- TCHAR out[255];
- GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_ILDATE, out, 255);
- winstr = QString::fromUtf16((ushort*)out);
- } , {
- char out[255];
- GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_ILDATE, (char*)&out, 255);
- winstr = QString::fromLocal8Bit(out);
- });
+ wchar_t out[255];
+ GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_ILDATE, out, 255);
+ QString winstr = QString::fromWCharArray(out);
switch (winstr.toInt()) {
case 1:
buf = d->date.shortDayName(d->date.dayOfWeek());
@@ -3298,7 +3282,7 @@ QDateTime QDateTime::fromString(const QString &string, const QString &format)
*/
void QDateTime::detach()
{
- qAtomicDetach(d);
+ d.detach();
}
/*****************************************************************************
@@ -3833,19 +3817,19 @@ void QDateTimePrivate::getUTC(QDate &outDate, QTime &outTime) const
#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_NO_DATESTRING)
QDebug operator<<(QDebug dbg, const QDate &date)
{
- dbg.nospace() << "QDate(" << date.toString() << ")";
+ dbg.nospace() << "QDate(" << date.toString() << ')';
return dbg.space();
}
QDebug operator<<(QDebug dbg, const QTime &time)
{
- dbg.nospace() << "QTime(" << time.toString() << ")";
+ dbg.nospace() << "QTime(" << time.toString() << ')';
return dbg.space();
}
QDebug operator<<(QDebug dbg, const QDateTime &date)
{
- dbg.nospace() << "QDateTime(" << date.toString() << ")";
+ dbg.nospace() << "QDateTime(" << date.toString() << ')';
return dbg.space();
}
#endif
@@ -4398,6 +4382,13 @@ int QDateTimeParser::sectionMaxSize(Section s, int count) const
case DateSectionMask:
qWarning("QDateTimeParser::sectionMaxSize: Invalid section %s",
sectionName(s).toLatin1().constData());
+
+ case NoSectionIndex:
+ case FirstSectionIndex:
+ case LastSectionIndex:
+ case CalendarPopupIndex:
+ // these cases can't happen
+ break;
}
return -1;
}
@@ -4688,7 +4679,7 @@ QDateTimeParser::StateNode QDateTimeParser::parse(QString &input, int &cursorPos
if (fixup && tmpstate == Intermediate && used < sn.count) {
const FieldInfo fi = fieldInfo(index);
if ((fi & (Numeric|FixedWidth)) == (Numeric|FixedWidth)) {
- const QString newText = QString(QLatin1String("%1")).arg(num, sn.count, 10, QLatin1Char('0'));
+ const QString newText = QString::fromLatin1("%1").arg(num, sn.count, 10, QLatin1Char('0'));
input.replace(pos, used, newText);
used = sn.count;
}
diff --git a/src/corelib/tools/qdatetime.h b/src/corelib/tools/qdatetime.h
index a1279db869..1af3132483 100644
--- a/src/corelib/tools/qdatetime.h
+++ b/src/corelib/tools/qdatetime.h
@@ -44,6 +44,7 @@
#include <QtCore/qstring.h>
#include <QtCore/qnamespace.h>
+#include <QtCore/qsharedpointer.h>
QT_BEGIN_HEADER
@@ -284,7 +285,7 @@ public:
private:
friend class QDateTimePrivate;
void detach();
- QDateTimePrivate *d;
+ QExplicitlySharedDataPointer<QDateTimePrivate> d;
#ifndef QT_NO_DATASTREAM
friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QDateTime &);
diff --git a/src/corelib/tools/qdatetime_p.h b/src/corelib/tools/qdatetime_p.h
index a8ab8bfdf7..7f9c3bdf16 100644
--- a/src/corelib/tools/qdatetime_p.h
+++ b/src/corelib/tools/qdatetime_p.h
@@ -81,9 +81,9 @@ class QDateTimePrivate
public:
enum Spec { LocalUnknown = -1, LocalStandard = 0, LocalDST = 1, UTC = 2, OffsetFromUTC = 3};
- QDateTimePrivate() : ref(1), spec(LocalUnknown), utcOffset(0) {}
+ QDateTimePrivate() : spec(LocalUnknown), utcOffset(0) {}
QDateTimePrivate(const QDateTimePrivate &other)
- : ref(1), date(other.date), time(other.time), spec(other.spec), utcOffset(other.utcOffset)
+ : date(other.date), time(other.time), spec(other.spec), utcOffset(other.utcOffset)
{}
QAtomicInt ref;
@@ -138,13 +138,6 @@ public:
PossibleBoth = 4
};
- enum {
- NoSectionIndex = -1,
- FirstSectionIndex = -2,
- LastSectionIndex = -3,
- CalendarPopupIndex = -4
- };
-
enum Section {
NoSection = 0x00000,
AmPmSection = 0x00001,
@@ -163,7 +156,12 @@ public:
DateSectionMask = (DaySection|MonthSection|YearSection|YearSection2Digits|DayOfWeekSection),
FirstSection = 0x02000|Internal,
LastSection = 0x04000|Internal,
- CalendarPopupSection = 0x08000|Internal
+ CalendarPopupSection = 0x08000|Internal,
+
+ NoSectionIndex = -1,
+ FirstSectionIndex = -2,
+ LastSectionIndex = -3,
+ CalendarPopupIndex = -4
}; // duplicated from qdatetimeedit.h
Q_DECLARE_FLAGS(Sections, Section)
diff --git a/src/corelib/tools/qdumper.cpp b/src/corelib/tools/qdumper.cpp
deleted file mode 100644
index 7c88f39a83..0000000000
--- a/src/corelib/tools/qdumper.cpp
+++ /dev/null
@@ -1,1157 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
-** package.
-**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <qdatetime.h>
-#include <qdebug.h>
-#include <qdir.h>
-#include <qfileinfo.h>
-#include <qhash.h>
-#include <qmap.h>
-#include <qmetaobject.h>
-#include <qobject.h>
-#include <qstring.h>
-#include <qvariant.h>
-#include <qvector.h>
-
-#if !defined(Q_OS_WINCE) && !defined(QT_NO_DUMPER)
-
-#include <stdlib.h>
-#include <stdio.h>
-
-#ifdef Q_OS_WIN
-# include <windows.h>
-#endif
-
-QT_BEGIN_NAMESPACE
-
-namespace {
-
-// This is used to abort evaluation of custom data dumpers in a "coordinated"
-// way. Abortion will happen anyway when we try to access a non-initialized
-// non-trivial object, so there is no way to prevent this from occuring at all
-// conceptionally. Gdb will catch SIGSEGV and return to the calling frame.
-// This is just fine provided we only _read_ memory in the custom handlers
-// below.
-
-volatile int qProvokeSegFaultHelper;
-
-static void qCheckAccess(const void *d)
-{
- // provoke segfault when address is not readable
- qProvokeSegFaultHelper = *(char*)d;
-}
-
-static void qCheckPointer(const void *d)
-{
- if (!d)
- return;
- qProvokeSegFaultHelper = *(char*)d;
-}
-
-static void qProvokeSegFault()
-{
- // provoke segfault unconditionally
- qCheckAccess(0);
-}
-
-static char qDumpInBuffer[100];
-static char qDumpBuffer[1000];
-#ifdef Q_OS_WIN
-static char qDumpBuffer2[sizeof(qDumpBuffer) + 100];
-#endif
-
-static char toHex(int n)
-{
- return n < 10 ? '0' + n : 'a' - 10 + n;
-}
-
-
-struct QDumper
-{
- explicit QDumper();
- ~QDumper();
- void flush();
- QDumper &operator<<(long c);
- QDumper &operator<<(int i);
- QDumper &operator<<(unsigned long c);
- QDumper &operator<<(unsigned int i);
- QDumper &operator<<(const void *p);
- void put(char c);
- void addCommaIfNeeded();
- void putEncoded(unsigned c);
- QDumper &operator<<(const char *str);
- QDumper &operator<<(const QString &str);
- void disarm();
-
- void beginHash(); // start of data hash output
- void endHash(); // start of data hash output
-
- // the dumper arguments
- int protocolVersion; // dumper protocol version
- int token; // some token to show on success
- const char *outertype; // object type
- const char *iname; // object name used for display
- const char *exp; // object expression
- const char *innertype; // 'inner type' for class templates
- const void *data; // pointer to raw data
- bool dumpChildren; // do we want to see children?
-
- // handling of nested templates
- void setupTemplateParameters();
- enum { maxTemplateParameters = 10 };
- const char *templateParameters[maxTemplateParameters + 1];
- int templateParametersCount;
-
- // internal state
- bool success; // are we finished?
- size_t pos;
-};
-
-
-QDumper::QDumper()
-{
- success = false;
- pos = 0;
-}
-
-QDumper::~QDumper()
-{
- flush();
- put(0); // our end marker
-#ifdef Q_OS_WIN
- sprintf(qDumpBuffer2, "@@CDD/%d/done\n", token);
- OutputDebugStringA(qDumpBuffer2);
-#else
- fprintf(stderr, "%d/done\n", token);
-#endif
- qDumpInBuffer[0] = 0;
-}
-
-void QDumper::flush()
-{
- qDumpBuffer[pos++] = 0;
-#ifdef Q_OS_WIN
- sprintf(qDumpBuffer2, "@@CDD#%d#%d,%s\n", token, int(pos - 1), qDumpBuffer);
- OutputDebugStringA(qDumpBuffer2);
-#else
- fprintf(stderr, "%d#%d,%s\n", token, int(pos - 1), qDumpBuffer);
-#endif
- pos = 0;
-}
-
-void QDumper::setupTemplateParameters()
-{
- char *s = const_cast<char *>(innertype);
-
- templateParametersCount = 1;
- templateParameters[0] = s;
- for (int i = 1; i != maxTemplateParameters + 1; ++i)
- templateParameters[i] = 0;
-
- while (*s) {
- while (*s && *s != '@')
- ++s;
- if (*s) {
- *s = '\0';
- ++s;
- templateParameters[templateParametersCount++] = s;
- }
- }
-}
-
-QDumper &QDumper::operator<<(unsigned long c)
-{
- static char buf[100];
- sprintf(buf, "%lu", c);
- return (*this) << buf;
-}
-
-QDumper &QDumper::operator<<(unsigned int i)
-{
- static char buf[100];
- sprintf(buf, "%u", i);
- return (*this) << buf;
-}
-
-QDumper &QDumper::operator<<(long c)
-{
- static char buf[100];
- sprintf(buf, "%ld", c);
- return (*this) << buf;
-}
-
-QDumper &QDumper::operator<<(int i)
-{
- static char buf[100];
- sprintf(buf, "%d", i);
- return (*this) << buf;
-}
-
-QDumper &QDumper::operator<<(const void *p)
-{
- static char buf[100];
- sprintf(buf, "%p", p);
- // we get a '0x' prefix only on some implementations.
- // if it isn't there, write it out manually.
- if (buf[1] != 'x') {
- put('0');
- put('x');
- }
- return (*this) << buf;
-}
-
-void QDumper::put(char c)
-{
- if (pos >= sizeof(qDumpBuffer) - 100)
- flush();
- qDumpBuffer[pos++] = c;
-}
-
-void QDumper::addCommaIfNeeded()
-{
- if (pos == 0)
- return;
- if (qDumpBuffer[pos - 1] == '}' || qDumpBuffer[pos - 1] == '"')
- put(',');
-}
-
-void QDumper::putEncoded(unsigned c)
-{
- if (c >= 32 && c <= 126 && c != '"' && c != '\\') {
- put(c);
- } else {
- put('\\');
- put('u');
- put(toHex((c >> 12) & 0xf));
- put(toHex((c >> 8) & 0xf));
- put(toHex((c >> 4) & 0xf));
- put(toHex( c & 0xf));
- }
-}
-
-QDumper &QDumper::operator<<(const char *str)
-{
- while (*str)
- put(*(str++));
- return *this;
-}
-
-QDumper &QDumper::operator<<(const QString &str)
-{
- int n = str.size();
- if (n < 0) {
- qProvokeSegFault();
- } else {
- //(*this) << "[" << n << "]";
- if (n > 1000000)
- n = 1000000;
- //put(' ');
- put('\\');
- put('"');
- for (int i = 0; i != n; ++i)
- putEncoded(str[i].unicode());
- put('\\');
- put('"');
- if (n < str.size())
- (*this) << "<incomplete string>";
- }
- return *this;
-}
-
-void QDumper::disarm()
-{
- flush();
- success = true;
-}
-
-void QDumper::beginHash()
-{
- addCommaIfNeeded();
- put('{');
-}
-
-void QDumper::endHash()
-{
- put('}');
-}
-
-
-//
-// Some helpers to keep the dumper code short
-//
-
-// dump property=value pair
-#undef P
-#define P(dumper,name,value) \
- do { \
- dumper.addCommaIfNeeded(); \
- dumper << (name) << "=\"" << value << "\""; \
- } while (0)
-
-// simple string property
-#undef S
-#define S(dumper, name, value) \
- dumper.beginHash(); \
- P(dumper, "name", name); \
- P(dumper, "value", value); \
- P(dumper, "type", "QString"); \
- P(dumper, "numchild", "0"); \
- dumper.endHash();
-
-// simple integer property
-#undef I
-#define I(dumper, name, value) \
- dumper.beginHash(); \
- P(dumper, "name", name); \
- P(dumper, "value", value); \
- P(dumper, "type", "int"); \
- P(dumper, "numchild", "0"); \
- dumper.endHash();
-
-// simple boolean property
-#undef BL
-#define BL(dumper, name, value) \
- dumper.beginHash(); \
- P(dumper, "name", name); \
- P(dumper, "value", (value ? "true" : "false")); \
- P(dumper, "type", "bool"); \
- P(dumper, "numchild", "0"); \
- dumper.endHash();
-
-#undef TT
-#define TT(type, value) \
- "<tr><td>" << type << "</td><td> : </td><td>" << value << "</td></tr>"
-
-static void qDumpUnknown(QDumper &d)
-{
- P(d, "iname", d.iname);
- P(d, "addr", d.data);
- P(d, "value", "<internal error>");
- P(d, "type", d.outertype);
- P(d, "numchild", "0");
- d.disarm();
-}
-
-static void qDumpQPropertyList(QDumper &d)
-{
- const QObject *ob = (const QObject *)d.data;
- const QMetaObject *mo = ob->metaObject();
- P(d, "iname", d.iname);
- P(d, "addr", "<synthetic>");
- P(d, "type", "QObject");
- P(d, "numchild", mo->propertyCount());
- if (d.dumpChildren) {
- d << ",children=[";
- for (int i = mo->propertyCount(); --i >= 0; ) {
- const QMetaProperty & prop = mo->property(i);
- d.beginHash();
- P(d, "name", prop.name());
- if (QLatin1String(prop.typeName()) == QLatin1String("QString")) {
- P(d, "value", prop.read(ob).toString());
- P(d, "numchild", "0");
- } else if (QLatin1String(prop.typeName()) == QLatin1String("bool")) {
- P(d, "value", (prop.read(ob).toBool() ? "true" : "false"));
- P(d, "numchild", "0");
- } else if (QLatin1String(prop.typeName()) == QLatin1String("int")) {
- P(d, "value", prop.read(ob).toInt());
- P(d, "numchild", "0");
- } else {
- P(d, "exp", "((" << mo->className() << "*)" << ob
- << ")->" << prop.name() << "()");
- }
- P(d, "type", prop.typeName());
- P(d, "numchild", "1");
- d.endHash();
- }
- d << "]";
- }
- d.disarm();
-}
-
-static void qDumpQObject(QDumper &d)
-{
- const QObject *ob = reinterpret_cast<const QObject *>(d.data);
- P(d, "iname", d.iname);
- P(d, "addr", d.data);
- P(d, "value", (void*)d.data);
- P(d, "type", "QObject");
- P(d, "numchild", 4);
- if (d.dumpChildren) {
- const QMetaObject *mo = ob->metaObject();
- const QObjectList &children = ob->children();
- d << ",children=[";
- S(d, "objectName", ob->objectName());
- d.beginHash();
- P(d, "name", "properties");
- // FIXME: Note that when simply using '(QObject*)'
- // in the cast below, Gdb/MI _sometimes misparses
- // expressions further down in the tree.
- P(d, "exp", "*(class QObject*)" << d.data);
- P(d, "type", "QPropertyList");
- P(d, "value", "<" << mo->propertyCount() << " items>");
- P(d, "numchild", mo->propertyCount());
- d.endHash();
- d.beginHash();
- P(d, "name", "children");
- P(d, "exp", "((class QObject*)" << d.data << ")->children()");
- P(d, "type", "QList<QObject *>");
- P(d, "value", "<" << children.size() << " items>");
- P(d, "numchild", children.size());
- d.endHash();
- d.beginHash();
- P(d, "name", "parent");
- P(d, "exp", "((class QObject*)" << d.data << ")->parent()");
- P(d, "type", "QObject *");
- P(d, "numchild", (ob->parent() ? "1" : "0"));
- d.endHash();
- d << "]";
- }
- d.disarm();
-}
-
-static void qDumpQDir(QDumper &d)
-{
- const QDir &dir = *reinterpret_cast<const QDir *>(d.data);
- P(d, "iname", d.iname);
- P(d, "addr", d.data);
- P(d, "value", dir.path());
- P(d, "type", "QDir");
- P(d, "numchild", "3");
- if (d.dumpChildren) {
- d << ",children=[";
- S(d, "absolutePath", dir.absolutePath());
- S(d, "canonicalPath", dir.canonicalPath());
- d << "]";
- }
- d.disarm();
-}
-
-static void qDumpQFileInfo(QDumper &d)
-{
- const QFileInfo &info = *reinterpret_cast<const QFileInfo *>(d.data);
- P(d, "iname", d.iname);
- P(d, "addr", d.data);
- P(d, "value", info.filePath());
- P(d, "type", "QDir");
- P(d, "numchild", "3");
- if (d.dumpChildren) {
- d << ",children=[";
- S(d, "absolutePath", info.absolutePath());
- S(d, "absoluteFilePath", info.absoluteFilePath());
- S(d, "canonicalPath", info.canonicalPath());
- S(d, "canonicalFilePath", info.canonicalFilePath());
- S(d, "completeBaseName", info.completeBaseName());
- S(d, "completeSuffix", info.completeSuffix());
- S(d, "baseName", info.baseName());
-#ifdef Q_OS_MACX
- BL(d, "isBundle", info.isBundle());
- S(d, "bundleName", info.bundleName());
-#endif
- S(d, "completeSuffix", info.completeSuffix());
- S(d, "fileName", info.fileName());
- S(d, "filePath", info.filePath());
- S(d, "group", info.group());
- S(d, "owner", info.owner());
- S(d, "path", info.path());
-
- I(d, "groupid", (long)info.groupId());
- I(d, "ownerid", (long)info.ownerId());
- //QFile::Permissions permissions () const
- I(d, "permissions", info.permissions());
-
- //QDir absoluteDir () const
- //QDir dir () const
-
- BL(d, "caching", info.caching());
- BL(d, "exists", info.exists());
- BL(d, "isAbsolute", info.isAbsolute());
- BL(d, "isDir", info.isDir());
- BL(d, "isExecutable", info.isExecutable());
- BL(d, "isFile", info.isFile());
- BL(d, "isHidden", info.isHidden());
- BL(d, "isReadable", info.isReadable());
- BL(d, "isRelative", info.isRelative());
- BL(d, "isRoot", info.isRoot());
- BL(d, "isSymLink", info.isSymLink());
- BL(d, "isWritable", info.isWritable());
-
-#ifndef QT_NO_DATESTRING
- d.beginHash();
- P(d, "name", "created");
- P(d, "value", info.created().toString());
- P(d, "exp", "((QFileInfo*)" << d.data << ")->created()");
- P(d, "type", "QDateTime");
- P(d, "numchild", "1");
- d.endHash();
-
- d.beginHash();
- P(d, "name", "lastModified");
- P(d, "value", info.lastModified().toString());
- P(d, "exp", "((QFileInfo*)" << d.data << ")->lastModified()");
- P(d, "type", "QDateTime");
- P(d, "numchild", "1");
- d.endHash();
-
- d.beginHash();
- P(d, "name", "lastRead");
- P(d, "value", info.lastRead().toString());
- P(d, "exp", "((QFileInfo*)" << d.data << ")->lastRead()");
- P(d, "type", "QDateTime");
- P(d, "numchild", "1");
- d.endHash();
-#endif
-
- d << "]";
- }
- d.disarm();
-}
-
-static void qDumpQDateTime(QDumper &d)
-{
-#ifdef QT_NO_DATESTRING
- qDumpUnknown(d);
-#else
- const QDateTime &date = *reinterpret_cast<const QDateTime *>(d.data);
- P(d, "iname", d.iname);
- P(d, "addr", d.data);
- P(d, "value", date.toString());
- P(d, "type", "QDateTime");
- P(d, "numchild", "3");
- if (d.dumpChildren) {
- d << ",children=[";
- BL(d, "isNull", date.isNull());
- I(d, "toTime_t", (long)date.toTime_t());
- S(d, "toString", date.toString());
- S(d, "toString_(ISO)", date.toString(Qt::ISODate));
- S(d, "toString_(SystemLocale)", date.toString(Qt::SystemLocaleDate));
- S(d, "toString_(Locale)", date.toString(Qt::LocaleDate));
- S(d, "toString", date.toString());
-
- d.beginHash();
- P(d, "name", "toUTC");
- P(d, "exp", "((QDateTime*)" << d.data << ")->toTimeSpec(Qt::UTC)");
- P(d, "type", "QDateTime");
- P(d, "numchild", "1");
- d.endHash();
-
- d.beginHash();
- P(d, "name", "toLocalTime");
- P(d, "exp", "((QDateTime*)" << d.data << ")->toTimeSpec(Qt::LocalTime)");
- P(d, "type", "QDateTime");
- P(d, "numchild", "1");
- d.endHash();
-
- d << "]";
- }
- d.disarm();
-#endif // ifdef QT_NO_DATESTRING
-}
-
-static void qDumpQString(QDumper &d)
-{
- const QString &str = *reinterpret_cast<const QString *>(d.data);
-
- // Try to provoke segfaults early to prevent the frontend
- // from asking for unavailable child details
- if (!str.isEmpty()) {
- volatile ushort dummy = 0;
- dummy += str.at(0).unicode();
- dummy += str.at(str.size() - 1).unicode();
- }
-
- P(d, "iname", d.iname);
- P(d, "addr", d.data);
- P(d, "value", str);
- P(d, "type", "QString");
- P(d, "numchild", "0");
- d.disarm();
-}
-
-static void qDumpQStringList(QDumper &d)
-{
- const QStringList &list = *reinterpret_cast<const QStringList *>(d.data);
- int n = list.size();
- if (n < 0)
- qProvokeSegFault();
- if (n > 0) {
- qCheckAccess(&list.front());
- qCheckAccess(&list.back());
- }
-
- P(d, "iname", d.iname);
- P(d, "addr", d.data);
- P(d, "value", "<" << n << " items>");
- P(d, "valuedisabled", "true");
- P(d, "numchild", n);
- if (d.dumpChildren) {
- if (n > 100)
- n = 100;
- d << ",children=[";
- for (int i = 0; i != n; ++i) {
- S(d, "[" << i << "]", list[i]);
- }
- if (n < list.size()) {
- d.beginHash();
- P(d, "value", "<incomplete>");
- P(d, "type", " ");
- P(d, "numchild", "0");
- d.endHash();
- }
- d << "]";
- }
- d.disarm();
-}
-
-static void qDumpQVariantHelper(const void *data, QString *value,
- QString *exp, int *numchild)
-{
- const QVariant &v = *reinterpret_cast<const QVariant *>(data);
- switch (v.type()) {
- case QVariant::Invalid:
- *value = QLatin1String("<invalid>");
- *numchild = 0;
- break;
- case QVariant::String:
- *value = QLatin1Char('"') + v.toString() + QLatin1Char('"');
- *numchild = 0;
- break;
- case QVariant::StringList:
- *exp = QString(QLatin1String("((QVariant*)%1)->d.data.c"))
- .arg((qulonglong)data);
- *numchild = v.toStringList().size();
- break;
- case QVariant::Int:
- *value = QString::number(v.toInt());
- *numchild= 0;
- break;
- case QVariant::Double:
- *value = QString::number(v.toDouble());
- *numchild = 0;
- break;
- default:
- // FIXME
- //*exp = QString("qVariantValue<" << v.typeName() << ">"
- // << "(*(QVariant*)" << data << ")");
- break;
- }
-}
-
-static void qDumpQVariant(QDumper &d)
-{
- const QVariant &v = *reinterpret_cast<const QVariant *>(d.data);
- QString value;
- QString exp;
- int numchild = 0;
- qDumpQVariantHelper(d.data, &value, &exp, &numchild);
- P(d, "iname", d.iname);
- P(d, "addr", d.data);
- P(d, "value", "(" << v.typeName() << ") " << qPrintable(value));
- P(d, "type", "QVariant");
- P(d, "numchild", 1);
- if (d.dumpChildren) {
- d << ",children=[";
- d.beginHash();
- P(d, "name", "value");
- if (!exp.isEmpty())
- P(d, "exp", qPrintable(exp));
- if (!value.isEmpty())
- P(d, "value", qPrintable(value));
- P(d, "type", v.typeName());
- P(d, "numchild", numchild);
- d.endHash();
- d << "]";
- }
- d.disarm();
-}
-
-static void qDumpQList(QDumper &d)
-{
- // This uses the knowledge that QList<T> has only a single member
- // of type union { QListData p; QListData::Data *d; };
- const QListData &ldata = *reinterpret_cast<const QListData*>(d.data);
- const QListData::Data *pdata = *reinterpret_cast<const QListData::Data* const*>(d.data);
- int nn = ldata.size();
- if (nn < 0)
- qProvokeSegFault();
- if (nn > 0) {
- qCheckAccess(ldata.d->array);
- //qCheckAccess(ldata.d->array[0]);
- //qCheckAccess(ldata.d->array[nn - 1]);
- }
-
- int n = nn;
- P(d, "iname", d.iname);
- P(d, "value", "<" << n << " items>");
- P(d, "valuedisabled", "true");
- P(d, "numchild", n);
- if (d.dumpChildren) {
- if (n > 100)
- n = 100;
- d << ",children=[";
- for (int i = 0; i != n; ++i) {
- d.beginHash();
- P(d, "name", "[" << i << "]");
- // The exact condition here is:
- // QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic
- // but this data is not available in the compiled binary.
- // So as first approximation only do the 'isLarge' check:
- void *p = &(ldata.d->array[i + pdata->begin]);
- unsigned long voidpsize = sizeof(void*);
- P(d, "exp", "(sizeof(" << d.innertype << ")>" << voidpsize <<
- "?(**(" << d.innertype << "**)(" << p << "))"
- ":(*(" << d.innertype << "*)(" << p << ")))");
- P(d, "type", d.innertype);
- d.endHash();
- }
- if (n < nn) {
- d << ",{";
- P(d, "value", "<incomplete>");
- d.endHash();
- }
- d << "]";
- }
- d.disarm();
-}
-
-static void qDumpQVector(QDumper &d)
-{
- // Use 'int' as representative value. No way (and no need)
- // to deduce proper type here.
- const QVector<int> &vec = *reinterpret_cast<const QVector<int> *>(d.data);
- const int nn = vec.size();
-
- // Try to provoke segfaults early to prevent the frontend
- // from asking for unavailable child details
- if (nn < 0)
- qProvokeSegFault();
- if (nn > 0) {
- qCheckAccess(&vec.front());
- qCheckAccess(&vec.back());
- }
-
- //int innersize = 0;
- //scanf(qDumpInBuffer, "%d", &innersize);
-
- int n = nn;
- P(d, "iname", d.iname);
- P(d, "addr", d.data);
- P(d, "value", "<" << n << " items>");
- P(d, "valuedisabled", "true");
- P(d, "numchild", n);
- if (d.dumpChildren) {
- if (n > 100)
- n = 100;
- d << ",children=[";
- for (int i = 0; i != n; ++i) {
- if (i)
- d << ",";
- d.beginHash();
- P(d, "name", "[" << i << "]");
- P(d, "exp", "(" << d.exp << ".d->array[" << i << "])");
- P(d, "type", d.innertype);
- d.endHash();
- }
- if (n < nn) {
- d << ",{";
- P(d, "value", "<incomplete>");
- d.endHash();
- }
- d << "]";
- }
- d.disarm();
-}
-
-static void qDumpQHashNode(QDumper &d)
-{
- struct NodeOS { void *next; uint k; uint v; } nodeOS; // int-key optimization, small value
- struct NodeOL { void *next; uint k; void *v; } nodeOL; // int-key optimiatzion, large value
- struct NodeNS { void *next; uint h; uint k; uint v; } nodeNS; // no optimization, small value
- struct NodeNL { void *next; uint h; uint k; void *v; } nodeNL; // no optimization, large value
- struct NodeL { void *next; uint h; void *k; void *v; } nodeL; // complex key
-
- // offsetof(...,...) not yet in Standard C++
- const ulong nodeOSk ( (char *)&nodeOS.k - (char *)&nodeOS );
- const ulong nodeOSv ( (char *)&nodeOS.v - (char *)&nodeOS );
- const ulong nodeOLk ( (char *)&nodeOL.k - (char *)&nodeOL );
- const ulong nodeOLv ( (char *)&nodeOL.v - (char *)&nodeOL );
- const ulong nodeNSk ( (char *)&nodeNS.k - (char *)&nodeNS );
- const ulong nodeNSv ( (char *)&nodeNS.v - (char *)&nodeNS );
- const ulong nodeNLk ( (char *)&nodeNL.k - (char *)&nodeNL );
- const ulong nodeNLv ( (char *)&nodeNL.v - (char *)&nodeNL );
- const ulong nodeLk ( (char *)&nodeL.k - (char *)&nodeL );
- const ulong nodeLv ( (char *)&nodeL.v - (char *)&nodeL );
-
- const QHashData *h = reinterpret_cast<const QHashData *>(d.data);
- const char *keyType = d.templateParameters[0];
- const char *valueType = d.templateParameters[1];
-
- P(d, "iname", d.iname);
- P(d, "addr", d.data);
- P(d, "value", "");
- P(d, "numchild", 2);
- if (d.dumpChildren) {
- // there is a hash specialization in cast the key are integers or shorts
- bool isOptimizedIntKey = qstrcmp(keyType, "int") == 0
-#if defined(Q_BYTE_ORDER) && Q_BYTE_ORDER == Q_LITTLE_ENDIAN
- || qstrcmp(keyType, "short") == 0
- || qstrcmp(keyType, "ushort") == 0
-#endif
- || qstrcmp(keyType, "uint") == 0;
-
- d << ",children=[";
- d.beginHash();
- P(d, "name", "key");
- P(d, "type", keyType);
- unsigned long intsize = sizeof(int);
- if (isOptimizedIntKey) {
- P(d, "exp", "*(" << keyType << "*)"
- "(((sizeof(" << valueType << ")>" << intsize << ")?"
- << nodeOLk << ":" << nodeOSk <<
- ")+(char*)" << h << ")");
- } else {
- P(d, "exp", "*(" << keyType << "*)"
- "(((sizeof(" << keyType << ")>" << intsize << ")?"
- << nodeLk << ":"
- "((sizeof(" << valueType << ")>" << intsize << ")?"
- << nodeNLk << ":" << nodeNSk << "))+(char*)" << h << ")");
- }
- d.endHash();
- d.beginHash();
- P(d, "name", "value");
- P(d, "type", valueType);
- if (isOptimizedIntKey) {
- P(d, "exp", "*(" << valueType << "*)"
- "(((sizeof(" << valueType << ")>" << intsize << ")?"
- << nodeOLv << ":" << nodeOSv << ")+(char*)" << h << ")");
- } else {
- P(d, "exp", "*(" << valueType << "*)"
- "(((sizeof(" << keyType << ")>" << intsize << ")?" << nodeLv << ":"
- "((sizeof(" << valueType << ")>" << intsize << ")?"
- << nodeNLv << ":" << nodeNSv << "))+(char*)" << h << ")");
- }
- d.endHash();
- d << "]";
- }
- d.disarm();
-}
-
-static void qDumpQHash(QDumper &d)
-{
- QHashData *h = *reinterpret_cast<QHashData *const*>(d.data);
- const char *keyType = d.templateParameters[0];
- const char *valueType = d.templateParameters[1];
-
- qCheckPointer(h->fakeNext);
- qCheckPointer(h->buckets);
-
- int n = h->size;
-
- if (n < 0)
- qProvokeSegFault();
- if (n > 0) {
- qCheckPointer(h->fakeNext);
- qCheckPointer(*h->buckets);
- }
-
- P(d, "iname", d.iname);
- P(d, "addr", d.data);
- P(d, "value", "<" << n << " items>");
- P(d, "numchild", n);
- if (d.dumpChildren) {
- if (n > 100)
- n = 100;
- d << ",children=[";
-
- QHashData::Node *node = h->firstNode();
- QHashData::Node *end = reinterpret_cast<QHashData::Node *>(h);
- int i = 0;
-
- while (node != end) {
- d.beginHash();
- P(d, "name", "[" << i << "]");
- P(d, "type", "QHashNode<" << keyType << "," << valueType << " >");
- P(d, "exp", "*(QHashNode<" << keyType << "," << valueType << " >*)" << node);
- d.endHash();
-
- ++i;
- node = QHashData::nextNode(node);
- }
- d << "]";
- }
- d.disarm();
-}
-
-static void qDumpQMapNode(QDumper &d)
-{
- const QMapData *h = reinterpret_cast<const QMapData *>(d.data);
- const char *keyType = d.templateParameters[0];
- const char *valueType = d.templateParameters[1];
-
- qCheckAccess(h->backward);
- qCheckAccess(h->forward[0]);
-
- P(d, "iname", d.iname);
- P(d, "addr", d.data);
- P(d, "value", "");
- P(d, "numchild", 2);
- if (d.dumpChildren) {
- unsigned long voidpsize = sizeof(void*);
- d << ",children=[";
- d.beginHash();
- P(d, "name", "key");
- P(d, "type", keyType);
- P(d, "exp", "*(" << keyType << "*)"
- << "("
- << 2 * voidpsize
- << "-sizeof('QMap<" << keyType << "," << valueType << ">::Node')"
- << "+(char*)" << h
- << ")");
- d.endHash();
- d.beginHash();
- P(d, "name", "value");
- P(d, "type", valueType);
- P(d, "exp", "*(" << valueType << "*)"
- << "("
- << "(size_t)&(('QMap<" << keyType << "," << valueType << ">::Node'*)0)->value"
- << "+" << 2 * voidpsize
- << "-sizeof('QMap<" << keyType << "," << valueType << ">::Node')"
- << "+(char*)" << h
- << ")");
- d.endHash();
- d << "]";
- }
-
- d.disarm();
-}
-
-static void qDumpQMap(QDumper &d)
-{
- QMapData *h = *reinterpret_cast<QMapData *const*>(d.data);
- const char *keyType = d.templateParameters[0];
- const char *valueType = d.templateParameters[1];
-
- int n = h->size;
-
- if (n < 0)
- qProvokeSegFault();
- if (n > 0) {
- qCheckAccess(h->backward);
- qCheckAccess(h->forward[0]);
- qCheckPointer(h->backward->backward);
- qCheckPointer(h->forward[0]->backward);
- }
-
- P(d, "iname", d.iname);
- P(d, "addr", d.data);
- P(d, "value", "<" << n << " items>");
- P(d, "numchild", n);
- if (d.dumpChildren) {
- if (n > 100)
- n = 100;
- d << ",children=[";
-
- QMapData::Node *node = reinterpret_cast<QMapData::Node *>(h->forward[0]);
- QMapData::Node *end = reinterpret_cast<QMapData::Node *>(h);
- int i = 0;
-
- while (node != end) {
- d.beginHash();
- P(d, "name", "[" << i << "]");
- P(d, "type", "QMap<" << keyType << "," << valueType << ">::Node");
- P(d, "exp", "*('QMap<" << keyType << "," << valueType << ">::Node'*)" << node);
- d.endHash();
-
- ++i;
- node = node->forward[0];
- }
- d << "]";
- }
-
- d.disarm();
-}
-
-static void qDumpQSet(QDumper &d)
-{
- // This uses the knowledge that QHash<T> has only a single member
- // of union { QHashData *d; QHashNode<Key, T> *e; };
- QHashData *hd = *(QHashData**)d.data;
- QHashData::Node *node = hd->firstNode();
-
- int n = hd->size;
- if (n < 0)
- qProvokeSegFault();
- if (n > 0) {
- qCheckAccess(node);
- qCheckPointer(node->next);
- }
-
- P(d, "iname", d.iname);
- P(d, "addr", d.data);
- P(d, "value", "<" << n << " items>");
- P(d, "valuedisabled", "true");
- P(d, "numchild", 2 * n);
- if (d.dumpChildren) {
- if (n > 100)
- n = 100;
- d << ",children=[";
- int i = 0;
- for (int bucket = 0; bucket != hd->numBuckets; ++bucket) {
- for (node = hd->buckets[bucket]; node->next; node = node->next) {
- d.beginHash();
- P(d, "name", "[" << i << "]");
- P(d, "type", d.innertype);
- P(d, "exp", "(('QHashNode<" << d.innertype
- << ",QHashDummyValue>'*)"
- << static_cast<const void*>(node) << ")->key"
- );
- d.endHash();
- ++i;
- }
- }
- d << "]";
- }
- d.disarm();
-}
-
-static void handleProtocolVersion2(QDumper & d)
-{
- if (!d.outertype[0]) {
- qDumpUnknown(d);
- return;
- }
-
- d.setupTemplateParameters();
- // d.outertype[0] is usally 'Q', so don't use it
- switch (d.outertype[1]) {
- case 'D':
- if (qstrcmp(d.outertype, "QDateTime") == 0)
- qDumpQDateTime(d);
- else if (qstrcmp(d.outertype, "QDir") == 0)
- qDumpQDir(d);
- break;
- case 'F':
- if (qstrcmp(d.outertype, "QFileInfo") == 0)
- qDumpQFileInfo(d);
- break;
- case 'H':
- if (qstrcmp(d.outertype, "QHash") == 0)
- qDumpQHash(d);
- else if (qstrcmp(d.outertype, "QHashNode") == 0)
- qDumpQHashNode(d);
- break;
- case 'L':
- if (qstrcmp(d.outertype, "QList") == 0)
- qDumpQList(d);
- break;
- case 'M':
- if (qstrcmp(d.outertype, "QMap") == 0)
- qDumpQMap(d);
- else if (qstrcmp(d.outertype, "QMap::Node") == 0)
- qDumpQMapNode(d);
- break;
- case 'O':
- if (qstrcmp(d.outertype, "QObject") == 0)
- qDumpQObject(d);
- break;
- case 'P':
- if (qstrcmp(d.outertype, "QPropertyList") == 0)
- qDumpQPropertyList(d);
- break;
- case 'S':
- if (qstrcmp(d.outertype, "QSet") == 0)
- qDumpQSet(d);
- else if (qstrcmp(d.outertype, "QString") == 0)
- qDumpQString(d);
- else if (qstrcmp(d.outertype, "QStringList") == 0)
- qDumpQStringList(d);
- break;
- case 'V':
- if (qstrcmp(d.outertype, "QVariant") == 0)
- qDumpQVariant(d);
- else if (qstrcmp(d.outertype, "QVector") == 0)
- qDumpQVector(d);
- break;
- }
-
- if (!d.success)
- qDumpUnknown(d);
-}
-
-} // anonymous namespace
-
-
-extern "C" Q_CORE_EXPORT void qDumpObjectData(
- int protocolVersion,
- int token,
- const char *outertype,
- const char *iname,
- const char *exp,
- const char *innertype,
- const void *data,
- bool dumpChildren)
-{
- if (protocolVersion == 1) {
- // used to test whether error output gets through
- //fprintf(stderr, "using stderr, qDebug follows: %d\n", token);
- //qDebug() << "using qDebug, stderr already used: " << token;
- }
-
- else if (protocolVersion == 2) {
- QDumper d;
- d.protocolVersion = protocolVersion;
- d.token = token;
- d.outertype = outertype ? outertype : "";
- d.iname = iname ? iname : "";
- d.exp = exp ? exp : "";
- d.innertype = innertype ? innertype : "";
- d.data = data ? data : "";
- d.dumpChildren = dumpChildren;
- handleProtocolVersion2(d);
- }
-
- else {
- qDebug() << "Unsupported protocol version" << protocolVersion;
- }
-}
-
-QT_END_NAMESPACE
-
-#endif // !Q_OS_WINCE && !QT_NO_QDUMPER
diff --git a/src/corelib/tools/qeasingcurve.cpp b/src/corelib/tools/qeasingcurve.cpp
new file mode 100644
index 0000000000..e84e3f03c4
--- /dev/null
+++ b/src/corelib/tools/qeasingcurve.cpp
@@ -0,0 +1,850 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+
+| *property* | *Used for type* |
+| period | QEasingCurve::{In,Out,InOut,OutIn}Elastic |
+| amplitude | QEasingCurve::{In,Out,InOut,OutIn}Bounce, QEasingCurve::{In,Out,InOut,OutIn}Elastic |
+| overshoot | QEasingCurve::{In,Out,InOut,OutIn}Back |
+
+*/
+
+
+
+
+/*!
+ \class QEasingCurve
+ \since 4.6
+ \ingroup animation
+ \brief The QEasingCurve class provides easing curves for controlling animation.
+
+ Easing curves describe a function that controls how the speed of the interpolation
+ between 0 and 1 should be. Easing curves allow transitions from
+ one value to another to appear more natural than a simple constant speed would allow.
+ The QEasingCurve class is usually used in conjunction with the QVariantAnimation and
+ QPropertyAnimation classes but can be used on its own. It is usually used to accelerate
+ the interpolation from zero velocity (ease in) or decelerate to zero velocity (ease out).
+ Ease in and ease out can also be combined in the same easing curve.
+
+ To calculate the speed of the interpolation, the easing curve provides the function
+ valueForProgress(), where the \a progress argument specifies the progress of the
+ interpolation: 0 is the start value of the interpolation, 1 is the end value of the
+ interpolation. The returned value is the effective progress of the interpolation.
+ If the returned value is the same as the input value for all input values the easing
+ curve is a linear curve. This is the default behaviour.
+
+ For example,
+ \code
+ QEasingCurve easing(QEasingCurve::InOutQuad);
+
+ for(qreal t = 0.0; t < 1.0; t+=0.1)
+ qWarning() << "Effective progress" << t << " is
+ << easing.valueForProgress(t);
+ \endcode
+ will print the effective progress of the interpolation between 0 and 1.
+
+ When using a QPropertyAnimation, the associated easing curve will be used to control the
+ progress of the interpolation between startValue and endValue:
+ \code
+ QPropertyAnimation animation;
+ animation.setStartValue(0);
+ animation.setEndValue(1000);
+ animation.setDuration(1000);
+ animation.setEasingCurve(QEasingCurve::InOutQuad);
+ \endcode
+ */
+
+/*!
+ \enum QEasingCurve::Type
+
+ The type of easing curve.
+
+ \value Linear \inlineimage qeasingcurve-linear.png
+ \br
+ Easing curve for a linear (t) function:
+ velocity is constant.
+ \value InQuad \inlineimage qeasingcurve-inquad.png
+ \br
+ Easing curve for a quadratic (t^2) function:
+ accelerating from zero velocity.
+ \value OutQuad \inlineimage qeasingcurve-outquad.png
+ \br
+ Easing curve for a quadratic (t^2) function:
+ decelerating to zero velocity.
+ \value InOutQuad \inlineimage qeasingcurve-inoutquad.png
+ \br
+ Easing curve for a quadratic (t^2) function:
+ acceleration until halfway, then deceleration.
+ \value OutInQuad \inlineimage qeasingcurve-outinquad.png
+ \br
+ Easing curve for a quadratic (t^2) function:
+ deceleration until halfway, then acceleration.
+ \value InCubic \inlineimage qeasingcurve-incubic.png
+ \br
+ Easing curve for a cubic (t^3) function:
+ accelerating from zero velocity.
+ \value OutCubic \inlineimage qeasingcurve-outcubic.png
+ \br
+ Easing curve for a cubic (t^3) function:
+ decelerating from zero velocity.
+ \value InOutCubic \inlineimage qeasingcurve-inoutcubic.png
+ \br
+ Easing curve for a cubic (t^3) function:
+ acceleration until halfway, then deceleration.
+ \value OutInCubic \inlineimage qeasingcurve-outincubic.png
+ \br
+ Easing curve for a cubic (t^3) function:
+ deceleration until halfway, then acceleration.
+ \value InQuart \inlineimage qeasingcurve-inquart.png
+ \br
+ Easing curve for a quartic (t^4) function:
+ accelerating from zero velocity.
+ \value OutQuart \inlineimage qeasingcurve-outquart.png
+ \br
+ Easing curve for a cubic (t^4) function:
+ decelerating from zero velocity.
+ \value InOutQuart \inlineimage qeasingcurve-inoutquart.png
+ \br
+ Easing curve for a cubic (t^4) function:
+ acceleration until halfway, then deceleration.
+ \value OutInQuart \inlineimage qeasingcurve-outinquart.png
+ \br
+ Easing curve for a cubic (t^4) function:
+ deceleration until halfway, then acceleration.
+ \value InQuint \inlineimage qeasingcurve-inquint.png
+ \br
+ Easing curve for a quintic (t^5) easing
+ in: accelerating from zero velocity.
+ \value OutQuint \inlineimage qeasingcurve-outquint.png
+ \br
+ Easing curve for a cubic (t^5) function:
+ decelerating from zero velocity.
+ \value InOutQuint \inlineimage qeasingcurve-inoutquint.png
+ \br
+ Easing curve for a cubic (t^5) function:
+ acceleration until halfway, then deceleration.
+ \value OutInQuint \inlineimage qeasingcurve-outinquint.png
+ \br
+ Easing curve for a cubic (t^5) function:
+ deceleration until halfway, then acceleration.
+ \value InSine \inlineimage qeasingcurve-insine.png
+ \br
+ Easing curve for a sinusoidal (sin(t)) function:
+ accelerating from zero velocity.
+ \value OutSine \inlineimage qeasingcurve-outsine.png
+ \br
+ Easing curve for a sinusoidal (sin(t)) function:
+ decelerating from zero velocity.
+ \value InOutSine \inlineimage qeasingcurve-inoutsine.png
+ \br
+ Easing curve for a sinusoidal (sin(t)) function:
+ acceleration until halfway, then deceleration.
+ \value OutInSine \inlineimage qeasingcurve-outinsine.png
+ \br
+ Easing curve for a sinusoidal (sin(t)) function:
+ deceleration until halfway, then acceleration.
+ \value InExpo \inlineimage qeasingcurve-inexpo.png
+ \br
+ Easing curve for an exponential (2^t) function:
+ accelerating from zero velocity.
+ \value OutExpo \inlineimage qeasingcurve-outexpo.png
+ \br
+ Easing curve for an exponential (2^t) function:
+ decelerating from zero velocity.
+ \value InOutExpo \inlineimage qeasingcurve-inoutexpo.png
+ \br
+ Easing curve for an exponential (2^t) function:
+ acceleration until halfway, then deceleration.
+ \value OutInExpo \inlineimage qeasingcurve-outinexpo.png
+ \br
+ Easing curve for an exponential (2^t) function:
+ deceleration until halfway, then acceleration.
+ \value InCirc \inlineimage qeasingcurve-incirc.png
+ \br
+ Easing curve for a circular (sqrt(1-t^2)) function:
+ accelerating from zero velocity.
+ \value OutCirc \inlineimage qeasingcurve-outcirc.png
+ \br
+ Easing curve for a circular (sqrt(1-t^2)) function:
+ decelerating from zero velocity.
+ \value InOutCirc \inlineimage qeasingcurve-inoutcirc.png
+ \br
+ Easing curve for a circular (sqrt(1-t^2)) function:
+ acceleration until halfway, then deceleration.
+ \value OutInCirc \inlineimage qeasingcurve-outincirc.png
+ \br
+ Easing curve for a circular (sqrt(1-t^2)) function:
+ deceleration until halfway, then acceleration.
+ \value InElastic \inlineimage qeasingcurve-inelastic.png
+ \br
+ Easing curve for an elastic
+ (exponentially decaying sine wave) function:
+ accelerating from zero velocity. The peak amplitude
+ can be set with the \e amplitude parameter, and the
+ period of decay by the \e period parameter.
+ \value OutElastic \inlineimage qeasingcurve-outelastic.png
+ \br
+ Easing curve for an elastic
+ (exponentially decaying sine wave) function:
+ decelerating from zero velocity. The peak amplitude
+ can be set with the \e amplitude parameter, and the
+ period of decay by the \e period parameter.
+ \value InOutElastic \inlineimage qeasingcurve-inoutelastic.png
+ \br
+ Easing curve for an elastic
+ (exponentially decaying sine wave) function:
+ acceleration until halfway, then deceleration.
+ \value OutInElastic \inlineimage qeasingcurve-outinelastic.png
+ \br
+ Easing curve for an elastic
+ (exponentially decaying sine wave) function:
+ deceleration until halfway, then acceleration.
+ \value InBack \inlineimage qeasingcurve-inback.png
+ \br
+ Easing curve for a back (overshooting
+ cubic function: (s+1)*t^3 - s*t^2) easing in:
+ accelerating from zero velocity.
+ \value OutBack \inlineimage qeasingcurve-outback.png
+ \br
+ Easing curve for a back (overshooting
+ cubic function: (s+1)*t^3 - s*t^2) easing out:
+ decelerating to zero velocity.
+ \value InOutBack \inlineimage qeasingcurve-inoutback.png
+ \br
+ Easing curve for a back (overshooting
+ cubic function: (s+1)*t^3 - s*t^2) easing in/out:
+ acceleration until halfway, then deceleration.
+ \value OutInBack \inlineimage qeasingcurve-outinback.png
+ \br
+ Easing curve for a back (overshooting
+ cubic easing: (s+1)*t^3 - s*t^2) easing out/in:
+ deceleration until halfway, then acceleration.
+ \value InBounce \inlineimage qeasingcurve-inbounce.png
+ \br
+ Easing curve for a bounce (exponentially
+ decaying parabolic bounce) function: accelerating
+ from zero velocity.
+ \value OutBounce \inlineimage qeasingcurve-outbounce.png
+ \br
+ Easing curve for a bounce (exponentially
+ decaying parabolic bounce) function: decelerating
+ from zero velocity.
+ \value InOutBounce \inlineimage qeasingcurve-inoutbounce.png
+ \br
+ Easing curve for a bounce (exponentially
+ decaying parabolic bounce) function easing in/out:
+ acceleration until halfway, then deceleration.
+ \value OutInBounce \inlineimage qeasingcurve-outinbounce.png
+ \br
+ Easing curve for a bounce (exponentially
+ decaying parabolic bounce) function easing out/in:
+ deceleration until halfway, then acceleration.
+ \omitvalue InCurve
+ \omitvalue OutCurve
+ \omitvalue SineCurve
+ \omitvalue CosineCurve
+ \value Custom This is returned if the user specified a custom curve type with
+ setCustomType(). Note that you cannot call setType() with this value,
+ but type() can return it.
+ \omitvalue NCurveTypes
+*/
+
+/*!
+ \typedef QEasingCurve::EasingFunction
+
+ This is a typedef for a pointer to a function with the following
+ signature:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qeasingcurve.cpp 0
+*/
+
+#include "qeasingcurve.h"
+
+#ifndef QT_NO_DEBUG_STREAM
+#include <QtCore/qdebug.h>
+#include <QtCore/qstring.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+static bool isConfigFunction(QEasingCurve::Type type)
+{
+ return type >= QEasingCurve::InElastic
+ && type <= QEasingCurve::OutInBounce;
+}
+
+class QEasingCurveFunction
+{
+public:
+ enum Type { In, Out, InOut, OutIn };
+
+ QEasingCurveFunction(QEasingCurveFunction::Type type = In, qreal period = 0.3, qreal amplitude = 1.0,
+ qreal overshoot = 1.70158f)
+ : _t(type), _p(period), _a(amplitude), _o(overshoot)
+ { }
+ virtual ~QEasingCurveFunction() {}
+ virtual qreal value(qreal t);
+ virtual QEasingCurveFunction *copy() const;
+ bool operator==(const QEasingCurveFunction& other);
+
+ Type _t;
+ qreal _p;
+ qreal _a;
+ qreal _o;
+};
+
+qreal QEasingCurveFunction::value(qreal t)
+{
+ return t;
+}
+
+QEasingCurveFunction *QEasingCurveFunction::copy() const
+{
+ return new QEasingCurveFunction(_t, _p, _a, _o);
+}
+
+bool QEasingCurveFunction::operator==(const QEasingCurveFunction& other)
+{
+ return _t == other._t &&
+ _p == other._p &&
+ _a == other._a &&
+ _o == other._o;
+}
+
+QT_BEGIN_INCLUDE_NAMESPACE
+#include "../../3rdparty/easing/easing.cpp"
+QT_END_INCLUDE_NAMESPACE
+
+class QEasingCurvePrivate
+{
+public:
+ QEasingCurvePrivate()
+ : type(QEasingCurve::Linear),
+ config(0),
+ func(&easeNone)
+ { }
+ ~QEasingCurvePrivate() { delete config; }
+ void setType_helper(QEasingCurve::Type);
+
+ QEasingCurve::Type type;
+ QEasingCurveFunction *config;
+ QEasingCurve::EasingFunction func;
+};
+
+struct ElasticEase : public QEasingCurveFunction
+{
+ ElasticEase(Type type)
+ : QEasingCurveFunction(type, qreal(0.3), qreal(1.0))
+ { }
+
+ QEasingCurveFunction *copy() const
+ {
+ ElasticEase *rv = new ElasticEase(_t);
+ rv->_p = _p;
+ rv->_a = _a;
+ return rv;
+ }
+
+ qreal value(qreal t)
+ {
+ qreal p = (_p < 0) ? 0.3f : _p;
+ qreal a = (_a < 0) ? 1.0f : _a;
+ switch(_t) {
+ case In:
+ return easeInElastic(t, a, p);
+ case Out:
+ return easeOutElastic(t, a, p);
+ case InOut:
+ return easeInOutElastic(t, a, p);
+ case OutIn:
+ return easeOutInElastic(t, a, p);
+ default:
+ return t;
+ }
+ }
+};
+
+struct BounceEase : public QEasingCurveFunction
+{
+ BounceEase(Type type)
+ : QEasingCurveFunction(type, 0.3f, 1.0f)
+ { }
+
+ QEasingCurveFunction *copy() const
+ {
+ BounceEase *rv = new BounceEase(_t);
+ rv->_a = _a;
+ return rv;
+ }
+
+ qreal value(qreal t)
+ {
+ qreal a = (_a < 0) ? 1.0f : _a;
+ switch(_t) {
+ case In:
+ return easeInBounce(t, a);
+ case Out:
+ return easeOutBounce(t, a);
+ case InOut:
+ return easeInOutBounce(t, a);
+ case OutIn:
+ return easeOutInBounce(t, a);
+ default:
+ return t;
+ }
+ }
+};
+
+struct BackEase : public QEasingCurveFunction
+{
+ BackEase(Type type)
+ : QEasingCurveFunction(type, 0.3f, 1.0f, 1.70158f)
+ { }
+
+ QEasingCurveFunction *copy() const
+ {
+ BackEase *rv = new BackEase(_t);
+ rv->_o = _o;
+ return rv;
+ }
+
+ qreal value(qreal t)
+ {
+ qreal o = (_o < 0) ? 1.70158f : _o;
+ switch(_t) {
+ case In:
+ return easeInBack(t, o);
+ case Out:
+ return easeOutBack(t, o);
+ case InOut:
+ return easeInOutBack(t, o);
+ case OutIn:
+ return easeOutInBack(t, o);
+ default:
+ return t;
+ }
+ }
+};
+
+static QEasingCurve::EasingFunction curveToFunc(QEasingCurve::Type curve)
+{
+ switch(curve) {
+ case QEasingCurve::Linear:
+ return &easeNone;
+ case QEasingCurve::InQuad:
+ return &easeInQuad;
+ case QEasingCurve::OutQuad:
+ return &easeOutQuad;
+ case QEasingCurve::InOutQuad:
+ return &easeInOutQuad;
+ case QEasingCurve::OutInQuad:
+ return &easeOutInQuad;
+ case QEasingCurve::InCubic:
+ return &easeInCubic;
+ case QEasingCurve::OutCubic:
+ return &easeOutCubic;
+ case QEasingCurve::InOutCubic:
+ return &easeInOutCubic;
+ case QEasingCurve::OutInCubic:
+ return &easeOutInCubic;
+ case QEasingCurve::InQuart:
+ return &easeInQuart;
+ case QEasingCurve::OutQuart:
+ return &easeOutQuart;
+ case QEasingCurve::InOutQuart:
+ return &easeInOutQuart;
+ case QEasingCurve::OutInQuart:
+ return &easeOutInQuart;
+ case QEasingCurve::InQuint:
+ return &easeInQuint;
+ case QEasingCurve::OutQuint:
+ return &easeOutQuint;
+ case QEasingCurve::InOutQuint:
+ return &easeInOutQuint;
+ case QEasingCurve::OutInQuint:
+ return &easeOutInQuint;
+ case QEasingCurve::InSine:
+ return &easeInSine;
+ case QEasingCurve::OutSine:
+ return &easeOutSine;
+ case QEasingCurve::InOutSine:
+ return &easeInOutSine;
+ case QEasingCurve::OutInSine:
+ return &easeOutInSine;
+ case QEasingCurve::InExpo:
+ return &easeInExpo;
+ case QEasingCurve::OutExpo:
+ return &easeOutExpo;
+ case QEasingCurve::InOutExpo:
+ return &easeInOutExpo;
+ case QEasingCurve::OutInExpo:
+ return &easeOutInExpo;
+ case QEasingCurve::InCirc:
+ return &easeInCirc;
+ case QEasingCurve::OutCirc:
+ return &easeOutCirc;
+ case QEasingCurve::InOutCirc:
+ return &easeInOutCirc;
+ case QEasingCurve::OutInCirc:
+ return &easeOutInCirc;
+ // Internal for, compatibility with QTimeLine only ??
+ case QEasingCurve::InCurve:
+ return &easeInCurve;
+ case QEasingCurve::OutCurve:
+ return &easeOutCurve;
+ case QEasingCurve::SineCurve:
+ return &easeSineCurve;
+ case QEasingCurve::CosineCurve:
+ return &easeCosineCurve;
+ default:
+ return 0;
+ };
+}
+
+static QEasingCurveFunction *curveToFunctionObject(QEasingCurve::Type type)
+{
+ QEasingCurveFunction *curveFunc = 0;
+ switch(type) {
+ case QEasingCurve::InElastic:
+ curveFunc = new ElasticEase(ElasticEase::In);
+ break;
+ case QEasingCurve::OutElastic:
+ curveFunc = new ElasticEase(ElasticEase::Out);
+ break;
+ case QEasingCurve::InOutElastic:
+ curveFunc = new ElasticEase(ElasticEase::InOut);
+ break;
+ case QEasingCurve::OutInElastic:
+ curveFunc = new ElasticEase(ElasticEase::OutIn);
+ break;
+ case QEasingCurve::OutBounce:
+ curveFunc = new BounceEase(BounceEase::Out);
+ break;
+ case QEasingCurve::InBounce:
+ curveFunc = new BounceEase(BounceEase::In);
+ break;
+ case QEasingCurve::OutInBounce:
+ curveFunc = new BounceEase(BounceEase::OutIn);
+ break;
+ case QEasingCurve::InOutBounce:
+ curveFunc = new BounceEase(BounceEase::InOut);
+ break;
+ case QEasingCurve::InBack:
+ curveFunc = new BackEase(BackEase::In);
+ break;
+ case QEasingCurve::OutBack:
+ curveFunc = new BackEase(BackEase::Out);
+ break;
+ case QEasingCurve::InOutBack:
+ curveFunc = new BackEase(BackEase::InOut);
+ break;
+ case QEasingCurve::OutInBack:
+ curveFunc = new BackEase(BackEase::OutIn);
+ break;
+ default:
+ curveFunc = new QEasingCurveFunction(QEasingCurveFunction::In, 0.3f, 1.0f, 1.70158f); // ###
+ }
+
+ return curveFunc;
+}
+
+/*!
+ Constructs an easing curve of the given \a type.
+ */
+QEasingCurve::QEasingCurve(Type type)
+ : d_ptr(new QEasingCurvePrivate)
+{
+ setType(type);
+}
+
+/*!
+ Construct a copy of \a other.
+ */
+QEasingCurve::QEasingCurve(const QEasingCurve &other)
+: d_ptr(new QEasingCurvePrivate)
+{
+ // ### non-atomic, requires malloc on shallow copy
+ *d_ptr = *other.d_ptr;
+ if(other.d_ptr->config)
+ d_ptr->config = other.d_ptr->config->copy();
+}
+
+/*!
+ Destructor.
+ */
+
+QEasingCurve::~QEasingCurve()
+{
+ delete d_ptr;
+}
+
+/*!
+ Copy \a other.
+ */
+QEasingCurve &QEasingCurve::operator=(const QEasingCurve &other)
+{
+ // ### non-atomic, requires malloc on shallow copy
+ if (d_ptr->config) {
+ delete d_ptr->config;
+ d_ptr->config = 0;
+ }
+
+ *d_ptr = *other.d_ptr;
+ if(other.d_ptr->config)
+ d_ptr->config = other.d_ptr->config->copy();
+
+ return *this;
+}
+
+/*!
+ Compare this easing curve with \a other and returns true if they are
+ equal. It will also compare the properties of a curve.
+ */
+bool QEasingCurve::operator==(const QEasingCurve &other) const
+{
+ bool res = d_ptr->func == other.d_ptr->func
+ && d_ptr->type == other.d_ptr->type;
+ if (res && d_ptr->config && other.d_ptr->config) {
+ // catch the config content
+ res = d_ptr->config->operator==(*(other.d_ptr->config));
+ }
+ return res;
+}
+
+/*!
+ \fn bool QEasingCurve::operator!=(const QEasingCurve &other) const
+ Compare this easing curve with \a other and returns true if they are not equal.
+ It will also compare the properties of a curve.
+
+ \sa operator==()
+*/
+
+/*!
+ Returns the amplitude. This is not applicable for all curve types.
+ It is only applicable for bounce and elastic curves (curves of type()
+ QEasingCurve::InBounce, QEasingCurve::OutBounce, QEasingCurve::InOutBounce,
+ QEasingCurve::OutInBounce, QEasingCurve::InElastic, QEasingCurve::OutElastic,
+ QEasingCurve::InOutElastic or QEasingCurve::OutInElastic).
+ */
+qreal QEasingCurve::amplitude() const
+{
+ return d_ptr->config ? d_ptr->config->_a : 1.0;
+}
+
+/*!
+ Sets the amplitude to \a amplitude.
+
+ This will set the amplitude of the bounce or the amplitude of the
+ elastic "spring" effect. The higher the number, the higher the amplitude.
+ \sa amplitude()
+*/
+void QEasingCurve::setAmplitude(qreal amplitude)
+{
+ if (!d_ptr->config)
+ d_ptr->config = curveToFunctionObject(d_ptr->type);
+ d_ptr->config->_a = amplitude;
+}
+
+/*!
+ Returns the period. This is not applicable for all curve types.
+ It is only applicable if type() is QEasingCurve::InElastic, QEasingCurve::OutElastic,
+ QEasingCurve::InOutElastic or QEasingCurve::OutInElastic.
+ */
+qreal QEasingCurve::period() const
+{
+ return d_ptr->config ? d_ptr->config->_p : 0.3;
+}
+
+/*!
+ Sets the period to \a period.
+ Setting a small period value will give a high frequency of the curve. A
+ large period will give it a small frequency.
+
+ \sa period()
+*/
+void QEasingCurve::setPeriod(qreal period)
+{
+ if (!d_ptr->config)
+ d_ptr->config = curveToFunctionObject(d_ptr->type);
+ d_ptr->config->_p = period;
+}
+
+/*!
+ Returns the overshoot. This is not applicable for all curve types.
+ It is only applicable if type() is QEasingCurve::InBack, QEasingCurve::OutBack,
+ QEasingCurve::InOutBack or QEasingCurve::OutInBack.
+ */
+qreal QEasingCurve::overshoot() const
+{
+ return d_ptr->config ? d_ptr->config->_o : 1.70158f;
+}
+
+/*!
+ Sets the overshoot to \a overshoot.
+
+ 0 produces no overshoot, and the default value of 1.70158 produces an overshoot of 10 percent.
+
+ \sa overshoot()
+*/
+void QEasingCurve::setOvershoot(qreal overshoot)
+{
+ if (!d_ptr->config)
+ d_ptr->config = curveToFunctionObject(d_ptr->type);
+ d_ptr->config->_o = overshoot;
+}
+
+/*!
+ Returns the type of the easing curve.
+*/
+QEasingCurve::Type QEasingCurve::type() const
+{
+ return d_ptr->type;
+}
+
+void QEasingCurvePrivate::setType_helper(QEasingCurve::Type newType)
+{
+ qreal amp = -1.0;
+ qreal period = -1.0;
+ qreal overshoot = -1.0;
+
+ if (config) {
+ amp = config->_a;
+ period = config->_p;
+ overshoot = config->_o;
+ delete config;
+ config = 0;
+ }
+
+ if (isConfigFunction(newType) || (amp != -1.0) || (period != -1.0) || (overshoot != -1.0)) {
+ config = curveToFunctionObject(newType);
+ if (amp != -1.0)
+ config->_a = amp;
+ if (period != -1.0)
+ config->_p = period;
+ if (overshoot != -1.0)
+ config->_o = overshoot;
+ func = 0;
+ } else if (newType != QEasingCurve::Custom) {
+ func = curveToFunc(newType);
+ }
+ Q_ASSERT((func == 0) == (config != 0));
+ type = newType;
+}
+
+/*!
+ Sets the type of the easing curve to \a type.
+*/
+void QEasingCurve::setType(Type type)
+{
+ if (d_ptr->type == type)
+ return;
+ if (type < Linear || type >= NCurveTypes - 1) {
+ qWarning("QEasingCurve: Invalid curve type %d", type);
+ return;
+ }
+
+ d_ptr->setType_helper(type);
+}
+
+/*!
+ Sets a custom easing curve that is defined by the user in the function \a func.
+ The signature of the function is qreal myEasingFunction(qreal progress),
+ where \e progress and the return value is considered to be normalized between 0 and 1.
+ (In some cases the return value can be outside that range)
+ After calling this function type() will return QEasingCurve::Custom.
+ \a func cannot be zero.
+
+ \sa customType()
+ \sa valueForProgress()
+*/
+void QEasingCurve::setCustomType(EasingFunction func)
+{
+ if (!func) {
+ qWarning("Function pointer must not be null");
+ return;
+ }
+ d_ptr->func = func;
+ d_ptr->setType_helper(Custom);
+}
+
+/*!
+ Returns the function pointer to the custom easing curve.
+ If type() does not return QEasingCurve::Custom, this function
+ will return 0.
+*/
+QEasingCurve::EasingFunction QEasingCurve::customType() const
+{
+ return d_ptr->type == Custom ? d_ptr->func : 0;
+}
+
+/*!
+ Return the effective progress for the easing curve at \a progress.
+ While \a progress must be between 0 and 1, the returned effective progress
+ can be outside those bounds. For instance, QEasingCurve::InBack will
+ return negative values in the beginning of the function.
+ */
+qreal QEasingCurve::valueForProgress(qreal progress) const
+{
+ progress = qBound<qreal>(0, progress, 1);
+ if (d_ptr->func)
+ return d_ptr->func(progress);
+ else if (d_ptr->config)
+ return d_ptr->config->value(progress);
+ else
+ return progress;
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug debug, const QEasingCurve &item)
+{
+ debug << "type:" << item.d_ptr->type
+ << "func:" << item.d_ptr->func;
+ if (item.d_ptr->config) {
+ debug << QString::fromAscii("period:%1").arg(item.d_ptr->config->_p, 0, 'f', 20)
+ << QString::fromAscii("amp:%1").arg(item.d_ptr->config->_a, 0, 'f', 20)
+ << QString::fromAscii("overshoot:%1").arg(item.d_ptr->config->_o, 0, 'f', 20);
+ }
+ return debug;
+}
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qeasingcurve.h b/src/corelib/tools/qeasingcurve.h
new file mode 100644
index 0000000000..4f48bd4181
--- /dev/null
+++ b/src/corelib/tools/qeasingcurve.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEASINGCURVE_H
+#define QEASINGCURVE_H
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qobjectdefs.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QEasingCurvePrivate;
+class Q_CORE_EXPORT QEasingCurve
+{
+ Q_GADGET
+ Q_ENUMS(Type)
+public:
+ enum Type {
+ Linear,
+ InQuad, OutQuad, InOutQuad, OutInQuad,
+ InCubic, OutCubic, InOutCubic, OutInCubic,
+ InQuart, OutQuart, InOutQuart, OutInQuart,
+ InQuint, OutQuint, InOutQuint, OutInQuint,
+ InSine, OutSine, InOutSine, OutInSine,
+ InExpo, OutExpo, InOutExpo, OutInExpo,
+ InCirc, OutCirc, InOutCirc, OutInCirc,
+ InElastic, OutElastic, InOutElastic, OutInElastic,
+ InBack, OutBack, InOutBack, OutInBack,
+ InBounce, OutBounce, InOutBounce, OutInBounce,
+ InCurve, OutCurve, SineCurve, CosineCurve,
+ Custom, NCurveTypes
+ };
+
+ QEasingCurve(Type type = Linear);
+ QEasingCurve(const QEasingCurve &other);
+ ~QEasingCurve();
+
+ QEasingCurve &operator=(const QEasingCurve &other);
+ bool operator==(const QEasingCurve &other) const;
+ inline bool operator!=(const QEasingCurve &other) const
+ { return !(this->operator==(other)); }
+
+ qreal amplitude() const;
+ void setAmplitude(qreal amplitude);
+
+ qreal period() const;
+ void setPeriod(qreal period);
+
+ qreal overshoot() const;
+ void setOvershoot(qreal overshoot);
+
+ Type type() const;
+ void setType(Type type);
+ typedef qreal (*EasingFunction)(qreal progress);
+ void setCustomType(EasingFunction func);
+ EasingFunction customType() const;
+
+ qreal valueForProgress(qreal progress) const;
+private:
+ QEasingCurvePrivate *d_ptr;
+ friend Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QEasingCurve &item);
+};
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QEasingCurve &item);
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/corelib/tools/qharfbuzz.cpp b/src/corelib/tools/qharfbuzz.cpp
index 6d06b37ce0..9a39f2f3f0 100644
--- a/src/corelib/tools/qharfbuzz.cpp
+++ b/src/corelib/tools/qharfbuzz.cpp
@@ -39,12 +39,12 @@
**
****************************************************************************/
-#include "qharfbuzz_p.h"
-
#include "qunicodetables_p.h"
#include "qlibrary.h"
#include "qtextcodec.h"
+#include "qharfbuzz_p.h"
+
QT_USE_NAMESPACE
extern "C" {
@@ -126,6 +126,7 @@ char *HB_TextCodec_ConvertFromUnicode(void *codec, const HB_UChar16 *unicode, hb
QByteArray data = reinterpret_cast<QTextCodec *>(codec)->fromUnicode((const QChar *)unicode, length);
// ### suboptimal
char *output = (char *)malloc(data.length() + 1);
+ Q_CHECK_PTR(output);
memcpy(output, data.constData(), data.length() + 1);
if (outputLength)
*outputLength = data.length();
diff --git a/src/corelib/tools/qharfbuzz_p.h b/src/corelib/tools/qharfbuzz_p.h
index 8b877b8a10..06b15e8814 100644
--- a/src/corelib/tools/qharfbuzz_p.h
+++ b/src/corelib/tools/qharfbuzz_p.h
@@ -53,8 +53,8 @@
#ifndef QHARFBUZZ_P_H
#define QHARFBUZZ_P_H
-#include <harfbuzz-shaper.h>
#include <QtCore/qglobal.h>
+#include <harfbuzz-shaper.h>
QT_BEGIN_NAMESPACE
diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp
index 0021547760..f6100fb3e9 100644
--- a/src/corelib/tools/qhash.cpp
+++ b/src/corelib/tools/qhash.cpp
@@ -171,7 +171,9 @@ QHashData QHashData::shared_null = {
void *QHashData::allocateNode()
{
- return qMalloc(nodeSize);
+ void *ptr = qMalloc(nodeSize);
+ Q_CHECK_PTR(ptr);
+ return ptr;
}
void QHashData::freeNode(void *node)
@@ -181,6 +183,13 @@ void QHashData::freeNode(void *node)
QHashData *QHashData::detach_helper(void (*node_duplicate)(Node *, void *), int nodeSize)
{
+ return detach_helper( node_duplicate, 0, nodeSize );
+}
+
+QHashData *QHashData::detach_helper(void (*node_duplicate)(Node *, void *),
+ void (*node_delete)(Node *),
+ int nodeSize)
+{
union {
QHashData *d;
Node *e;
@@ -197,18 +206,43 @@ QHashData *QHashData::detach_helper(void (*node_duplicate)(Node *, void *), int
d->sharable = true;
if (numBuckets) {
- d->buckets = new Node *[numBuckets];
+ QT_TRY {
+ d->buckets = new Node *[numBuckets];
+ } QT_CATCH(...) {
+ // restore a consistent state for d
+ d->numBuckets = 0;
+ // roll back
+ d->free_helper(node_delete);
+ QT_RETHROW;
+ }
+
Node *this_e = reinterpret_cast<Node *>(this);
for (int i = 0; i < numBuckets; ++i) {
Node **nextNode = &d->buckets[i];
Node *oldNode = buckets[i];
while (oldNode != this_e) {
- Node *dup = static_cast<Node *>(allocateNode());
- node_duplicate(oldNode, dup);
- dup->h = oldNode->h;
- *nextNode = dup;
- nextNode = &dup->next;
- oldNode = oldNode->next;
+ QT_TRY {
+ Node *dup = static_cast<Node *>(allocateNode());
+
+ QT_TRY {
+ node_duplicate(oldNode, dup);
+ } QT_CATCH(...) {
+ freeNode( dup );
+ QT_RETHROW;
+ }
+
+ dup->h = oldNode->h;
+ *nextNode = dup;
+ nextNode = &dup->next;
+ oldNode = oldNode->next;
+ } QT_CATCH(...) {
+ // restore a consistent state for d
+ *nextNode = e;
+ d->numBuckets = i+1;
+ // roll back
+ d->free_helper(node_delete);
+ QT_RETHROW;
+ }
}
*nextNode = e;
}
@@ -216,6 +250,26 @@ QHashData *QHashData::detach_helper(void (*node_duplicate)(Node *, void *), int
return d;
}
+void QHashData::free_helper(void (*node_delete)(Node *))
+{
+ if (node_delete) {
+ Node *this_e = reinterpret_cast<Node *>(this);
+ Node **bucket = reinterpret_cast<Node **>(this->buckets);
+
+ int n = numBuckets;
+ while (n--) {
+ Node *cur = *bucket++;
+ while (cur != this_e) {
+ Node *next = cur->next;
+ node_delete(cur);
+ cur = next;
+ }
+ }
+ }
+ delete [] buckets;
+ delete this;
+}
+
QHashData::Node *QHashData::nextNode(Node *node)
{
union {
@@ -298,9 +352,10 @@ void QHashData::rehash(int hint)
Node **oldBuckets = buckets;
int oldNumBuckets = numBuckets;
+ int nb = primeForNumBits(hint);
+ buckets = new Node *[nb];
numBits = hint;
- numBuckets = primeForNumBits(hint);
- buckets = new Node *[numBuckets];
+ numBuckets = nb;
for (int i = 0; i < numBuckets; ++i)
buckets[i] = e;
@@ -327,8 +382,7 @@ void QHashData::rehash(int hint)
void QHashData::destroyAndFree()
{
- delete [] buckets;
- delete this;
+ free_helper(0);
}
#ifdef QT_QHASH_DEBUG
@@ -485,7 +539,7 @@ void QHashData::checkSanity()
\ingroup tools
\ingroup shared
- \mainclass
+
\reentrant
QHash\<Key, T\> is one of Qt's generic \l{container classes}. It
@@ -1618,7 +1672,7 @@ void QHashData::checkSanity()
\ingroup tools
\ingroup shared
- \mainclass
+
\reentrant
QMultiHash\<Key, T\> is one of Qt's generic \l{container classes}.
diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h
index ab723048c4..73ebb77d64 100644
--- a/src/corelib/tools/qhash.h
+++ b/src/corelib/tools/qhash.h
@@ -129,12 +129,15 @@ struct Q_CORE_EXPORT QHashData
void *allocateNode();
void freeNode(void *node);
- QHashData *detach_helper(void (*node_duplicate)(Node *, void *), int nodeSize);
+ QHashData *detach_helper(void (*node_duplicate)(Node *, void *), int nodeSize); // ### Qt5 remove me
+ QHashData *detach_helper(void (*node_duplicate)(Node *, void *), void (*node_delete)(Node *),
+ int nodeSize);
void mightGrow();
bool willGrow();
void hasShrunk();
void rehash(int hint);
- void destroyAndFree();
+ void free_helper(void (*node_delete)(Node *));
+ void destroyAndFree(); // ### Qt5 remove me
Node *firstNode();
#ifdef QT_QHASH_DEBUG
void dump();
@@ -147,10 +150,10 @@ struct Q_CORE_EXPORT QHashData
};
inline void QHashData::mightGrow() // ### Qt 5: eliminate
-{
+{
if (size >= numBuckets)
rehash(numBits + 1);
-}
+}
inline bool QHashData::willGrow()
{
@@ -164,8 +167,13 @@ inline bool QHashData::willGrow()
inline void QHashData::hasShrunk()
{
- if (size <= (numBuckets >> 3) && numBits > userNumBits)
- rehash(qMax(int(numBits) - 2, int(userNumBits)));
+ if (size <= (numBuckets >> 3) && numBits > userNumBits) {
+ QT_TRY {
+ rehash(qMax(int(numBits) - 2, int(userNumBits)));
+ } QT_CATCH(const std::bad_alloc &) {
+ // ignore bad allocs - shrinking shouldn't throw. rehash is exception safe.
+ }
+ }
}
inline QHashData::Node *QHashData::firstNode()
@@ -476,21 +484,30 @@ private:
Node **findNode(const Key &key, uint *hp = 0) const;
Node *createNode(uint h, const Key &key, const T &value, Node **nextNode);
void deleteNode(Node *node);
+ static void deleteNode(QHashData::Node *node);
static void duplicateNode(QHashData::Node *originalNode, void *newNode);
};
+
template <class Key, class T>
Q_INLINE_TEMPLATE void QHash<Key, T>::deleteNode(Node *node)
{
+ deleteNode(reinterpret_cast<QHashData::Node*>(node));
+}
+
+
+template <class Key, class T>
+Q_INLINE_TEMPLATE void QHash<Key, T>::deleteNode(QHashData::Node *node)
+{
#ifdef Q_CC_BOR
- node->~QHashNode<Key, T>();
+ concrete(node)->~QHashNode<Key, T>();
#elif defined(QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION)
- node->~QHashNode();
+ concrete(node)->~QHashNode();
#else
- node->~Node();
+ concrete(node)->~Node();
#endif
- d->freeNode(node);
+ qFree(node);
}
template <class Key, class T>
@@ -538,18 +555,7 @@ Q_INLINE_TEMPLATE QHash<Key, T> &QHash<Key, T>::unite(const QHash<Key, T> &other
template <class Key, class T>
Q_OUTOFLINE_TEMPLATE void QHash<Key, T>::freeData(QHashData *x)
{
- Node *e_for_x = reinterpret_cast<Node *>(x);
- Node **bucket = reinterpret_cast<Node **>(x->buckets);
- int n = x->numBuckets;
- while (n--) {
- Node *cur = *bucket++;
- while (cur != e_for_x) {
- Node *next = cur->next;
- deleteNode(cur);
- cur = next;
- }
- }
- x->destroyAndFree();
+ x->free_helper(deleteNode);
}
template <class Key, class T>
@@ -561,7 +567,7 @@ Q_INLINE_TEMPLATE void QHash<Key, T>::clear()
template <class Key, class T>
Q_OUTOFLINE_TEMPLATE void QHash<Key, T>::detach_helper()
{
- QHashData *x = d->detach_helper(duplicateNode,
+ QHashData *x = d->detach_helper(duplicateNode, deleteNode,
QTypeInfo<T>::isDummy ? sizeof(DummyNode) : sizeof(Node));
if (!d->ref.deref())
freeData(d);
@@ -760,6 +766,8 @@ Q_INLINE_TEMPLATE typename QHash<Key, T>::iterator QHash<Key, T>::insertMulti(co
template <class Key, class T>
Q_OUTOFLINE_TEMPLATE int QHash<Key, T>::remove(const Key &akey)
{
+ if (isEmpty()) // prevents detaching shared null
+ return 0;
detach();
int oldSize = d->size;
@@ -781,6 +789,8 @@ Q_OUTOFLINE_TEMPLATE int QHash<Key, T>::remove(const Key &akey)
template <class Key, class T>
Q_OUTOFLINE_TEMPLATE T QHash<Key, T>::take(const Key &akey)
{
+ if (isEmpty()) // prevents detaching shared null
+ return T();
detach();
Node **node = findNode(akey);
@@ -911,7 +921,8 @@ public:
inline QMultiHash operator+(const QMultiHash &other) const
{ QMultiHash result = *this; result += other; return result; }
-#ifndef Q_NO_USING_KEYWORD
+#if !defined(Q_NO_USING_KEYWORD) && !defined(Q_CC_RVCT)
+ // RVCT compiler doesn't handle using-keyword right when used functions are overloaded in child class
using QHash<Key, T>::contains;
using QHash<Key, T>::remove;
using QHash<Key, T>::count;
@@ -981,7 +992,12 @@ Q_INLINE_TEMPLATE int QMultiHash<Key, T>::remove(const Key &key, const T &value)
typename QHash<Key, T>::iterator end(QHash<Key, T>::end());
while (i != end && i.key() == key) {
if (i.value() == value) {
+#if defined(Q_CC_RVCT)
+ // RVCT has problems with scoping, apparently.
+ i = QHash<Key, T>::erase(i);
+#else
i = erase(i);
+#endif
++n;
} else {
++i;
diff --git a/src/corelib/tools/qiterator.qdoc b/src/corelib/tools/qiterator.qdoc
new file mode 100644
index 0000000000..adb6b98d4b
--- /dev/null
+++ b/src/corelib/tools/qiterator.qdoc
@@ -0,0 +1,1431 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QListIterator
+ \inmodule QtCore
+
+ \brief The QListIterator class provides a Java-style const iterator for QList and QQueue.
+
+ QList has both \l{Java-style iterators} and \l{STL-style
+ iterators}. The Java-style iterators are more high-level and
+ easier to use than the STL-style iterators; on the other hand,
+ they are slightly less efficient.
+
+ An alternative to using iterators is to use index positions. Most
+ QList member functions take an index as their first parameter,
+ making it possible to access, modify, and remove items without
+ using iterators.
+
+ QListIterator\<T\> allows you to iterate over a QList\<T\> (or a
+ QQueue\<T\>). If you want to modify the list as you iterate over
+ it, use QMutableListIterator\<T\> instead.
+
+ The QListIterator constructor takes a QList as argument. After
+ construction, the iterator is located at the very beginning of
+ the list (before the first item). Here's how to iterate over all
+ the elements sequentially:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.qdoc 0
+
+ The next() function returns the next item in the list and
+ advances the iterator. Unlike STL-style iterators, Java-style
+ iterators point \e between items rather than directly \e at
+ items. The first call to next() advances the iterator to the
+ position between the first and second item, and returns the first
+ item; the second call to next() advances the iterator to the
+ position between the second and third item, and returns the second
+ item; and so on.
+
+ \img javaiterators1.png
+
+ Here's how to iterate over the elements in reverse order:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.qdoc 1
+
+ If you want to find all occurrences of a particular value, use
+ findNext() or findPrevious() in a loop.
+
+ Multiple iterators can be used on the same list. If the list is
+ modified while a QListIterator is active, the QListIterator will
+ continue iterating over the original list, ignoring the modified
+ copy.
+
+ \sa QMutableListIterator, QList::const_iterator
+*/
+
+/*!
+ \class QLinkedListIterator
+ \inmodule QtCore
+
+ \brief The QLinkedListIterator class provides a Java-style const iterator for QLinkedList.
+
+ QLinkedList has both \l{Java-style iterators} and
+ \l{STL-style iterators}. The Java-style iterators are more
+ high-level and easier to use than the STL-style iterators; on the
+ other hand, they are slightly less efficient.
+
+ QLinkedListIterator\<T\> allows you to iterate over a
+ QLinkedList\<T\>. If you want to modify the list as you iterate
+ over it, use QMutableLinkedListIterator\<T\> instead.
+
+ The QLinkedListIterator constructor takes a QLinkedList as
+ argument. After construction, the iterator is located at the very
+ beginning of the list (before the first item). Here's how to
+ iterate over all the elements sequentially:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.qdoc 2
+
+ The next() function returns the next item in the list and
+ advances the iterator. Unlike STL-style iterators, Java-style
+ iterators point \e between items rather than directly \e at
+ items. The first call to next() advances the iterator to the
+ position between the first and second item, and returns the first
+ item; the second call to next() advances the iterator to the
+ position between the second and third item, and returns the second
+ item; and so on.
+
+ \img javaiterators1.png
+
+ Here's how to iterate over the elements in reverse order:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.qdoc 3
+
+ If you want to find all occurrences of a particular value, use
+ findNext() or findPrevious() in a loop.
+
+ Multiple iterators can be used on the same list. If the list is
+ modified while a QLinkedListIterator is active, the
+ QLinkedListIterator will continue iterating over the original
+ list, ignoring the modified copy.
+
+ \sa QMutableLinkedListIterator, QLinkedList::const_iterator
+*/
+
+/*!
+ \class QVectorIterator
+ \inmodule QtCore
+ \brief The QVectorIterator class provides a Java-style const iterator for QVector and QStack.
+
+ QVector has both \l{Java-style iterators} and \l{STL-style
+ iterators}. The Java-style iterators are more high-level and
+ easier to use than the STL-style iterators; on the other hand,
+ they are slightly less efficient.
+
+ An alternative to using iterators is to use index positions. Most
+ QVector member functions take an index as their first parameter,
+ making it possible to access, insert, and remove items without
+ using iterators.
+
+ QVectorIterator\<T\> allows you to iterate over a QVector\<T\>
+ (or a QStack\<T\>). If you want to modify the vector as you
+ iterate over it, use QMutableVectorIterator\<T\> instead.
+
+ The QVectorIterator constructor takes a QVector as argument.
+ After construction, the iterator is located at the very beginning
+ of the vector (before the first item). Here's how to iterate over
+ all the elements sequentially:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.qdoc 4
+
+ The next() function returns the next item in the vector and
+ advances the iterator. Unlike STL-style iterators, Java-style
+ iterators point \e between items rather than directly \e at
+ items. The first call to next() advances the iterator to the
+ position between the first and second item, and returns the first
+ item; the second call to next() advances the iterator to the
+ position between the second and third item, returning the second
+ item; and so on.
+
+ \img javaiterators1.png
+
+ Here's how to iterate over the elements in reverse order:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.qdoc 5
+
+ If you want to find all occurrences of a particular value, use
+ findNext() or findPrevious() in a loop.
+
+ Multiple iterators can be used on the same vector. If the vector
+ is modified while a QVectorIterator is active, the QVectorIterator
+ will continue iterating over the original vector, ignoring the
+ modified copy.
+
+ \sa QMutableVectorIterator, QVector::const_iterator
+*/
+
+/*!
+ \class QSetIterator
+ \inmodule QtCore
+ \brief The QSetIterator class provides a Java-style const iterator for QSet.
+
+ QSet supports both \l{Java-style iterators} and \l{STL-style
+ iterators}. The Java-style iterators are more high-level and
+ easier to use than the STL-style iterators; on the other hand,
+ they are slightly less efficient.
+
+ QSetIterator\<T\> allows you to iterate over a QSet\<T\>. If you
+ want to modify the set as you iterate over it, use
+ QMutableSetIterator\<T\> instead.
+
+ The constructor takes a QSet as argument. After construction, the
+ iterator is located at the very beginning of the set (before
+ the first item). Here's how to iterate over all the elements
+ sequentially:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.qdoc 6
+
+ The next() function returns the next item in the set and
+ advances the iterator. Unlike STL-style iterators, Java-style
+ iterators point \e between items rather than directly \e at
+ items. The first call to next() advances the iterator to the
+ position between the first and second item, and returns the first
+ item; the second call to next() advances the iterator to the
+ position between the second and third item, returning the second
+ item; and so on.
+
+ \img javaiterators1.png
+
+ Here's how to iterate over the elements in reverse order:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.qdoc 7
+
+ If you want to find all occurrences of a particular value, use
+ findNext() or findPrevious() in a loop.
+
+ Multiple iterators can be used on the same set. If the set
+ is modified while a QSetIterator is active, the QSetIterator
+ will continue iterating over the original set, ignoring the
+ modified copy.
+
+ \sa QMutableSetIterator, QSet::const_iterator
+*/
+
+/*!
+ \class QMutableListIterator
+ \inmodule QtCore
+
+ \brief The QMutableListIterator class provides a Java-style non-const iterator for QList and QQueue.
+
+ QList has both \l{Java-style iterators} and \l{STL-style
+ iterators}. The Java-style iterators are more high-level and
+ easier to use than the STL-style iterators; on the other hand,
+ they are slightly less efficient.
+
+ An alternative to using iterators is to use index positions. Most
+ QList member functions take an index as their first parameter,
+ making it possible to access, insert, and remove items without
+ using iterators.
+
+ QMutableListIterator\<T\> allows you to iterate over a QList\<T\>
+ (or a QQueue\<T\>) and modify the list. If you don't want to
+ modify the list (or have a const QList), use the slightly faster
+ QListIterator\<T\> instead.
+
+ The QMutableListIterator constructor takes a QList as argument.
+ After construction, the iterator is located at the very beginning
+ of the list (before the first item). Here's how to iterate over
+ all the elements sequentially:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.qdoc 8
+
+ The next() function returns the next item in the list and
+ advances the iterator. Unlike STL-style iterators, Java-style
+ iterators point \e between items rather than directly \e at
+ items. The first call to next() advances the iterator to the
+ position between the first and second item, and returns the first
+ item; the second call to next() advances the iterator to the
+ position between the second and third item, returning the second
+ item; and so on.
+
+ \img javaiterators1.png
+
+ Here's how to iterate over the elements in reverse order:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.qdoc 9
+
+ If you want to find all occurrences of a particular value, use
+ findNext() or findPrevious() in a loop.
+
+ If you want to remove items as you iterate over the list, use
+ remove(). If you want to modify the value of an item, use
+ setValue(). If you want to insert a new item in the list, use
+ insert().
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qiterator.qdoc 10
+
+ The example traverses a list, replacing negative numbers with
+ their absolute values, and eliminating zeroes.
+
+ Only one mutable iterator can be active on a given list at any
+ time. Furthermore, no changes should be done directly to the list
+ while the iterator is active (as opposed to through the
+ iterator), since this could invalidate the iterator and lead to
+ undefined behavior.
+
+ \sa QListIterator, QList::iterator
+*/
+
+/*!
+ \class QMutableLinkedListIterator
+ \inmodule QtCore
+
+ \brief The QMutableLinkedListIterator class provides a Java-style non-const iterator for QLinkedList.
+
+ QLinkedList has both \l{Java-style iterators} and
+ \l{STL-style iterators}. The Java-style iterators are more
+ high-level and easier to use than the STL-style iterators; on the
+ other hand, they are slightly less efficient.
+
+ QMutableLinkedListIterator\<T\> allows you to iterate over a
+ QLinkedList\<T\> and modify the list. If you don't want to modify
+ the list (or have a const QLinkedList), use the slightly faster
+ QLinkedListIterator\<T\> instead.
+
+ The QMutableLinkedListIterator constructor takes a QLinkedList as
+ argument. After construction, the iterator is located at the very
+ beginning of the list (before the first item). Here's how to
+ iterate over all the elements sequentially:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.qdoc 11
+
+ The next() function returns the next item in the list and
+ advances the iterator. Unlike STL-style iterators, Java-style
+ iterators point \e between items rather than directly \e at
+ items. The first call to next() advances the iterator to the
+ position between the first and second item, and returns the first
+ item; the second call to next() advances the iterator to the
+ position between the second and third item, returning the second
+ item; and so on.
+
+ \img javaiterators1.png
+
+ Here's how to iterate over the elements in reverse order:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.qdoc 12
+
+ If you want to find all occurrences of a particular value, use
+ findNext() or findPrevious() in a loop.
+
+ If you want to remove items as you iterate over the list, use
+ remove(). If you want to modify the value of an item, use
+ setValue(). If you want to insert a new item in the list, use
+ insert().
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qiterator.qdoc 13
+
+ The example traverses a list, replacing negative numbers with
+ their absolute values, and eliminating zeroes.
+
+ Only one mutable iterator can be active on a given list at any
+ time. Furthermore, no changes should be done directly to the list
+ while the iterator is active (as opposed to through the
+ iterator), since this could invalidate the iterator and lead to
+ undefined behavior.
+
+ \sa QLinkedListIterator, QLinkedList::iterator
+*/
+
+/*!
+ \class QMutableVectorIterator
+ \inmodule QtCore
+
+ \brief The QMutableVectorIterator class provides a Java-style non-const iterator for QVector and QStack.
+
+ QVector has both \l{Java-style iterators} and \l{STL-style
+ iterators}. The Java-style iterators are more high-level and
+ easier to use than the STL-style iterators; on the other hand,
+ they are slightly less efficient.
+
+ An alternative to using iterators is to use index positions. Most
+ QVector member functions take an index as their first parameter,
+ making it possible to access, insert, and remove items without
+ using iterators.
+
+ QMutableVectorIterator\<T\> allows you to iterate over a
+ QVector\<T\> and modify the vector. If you don't want to modify
+ the vector (or have a const QVector), use the slightly faster
+ QVectorIterator\<T\> instead.
+
+ The QMutableVectorIterator constructor takes a QVector as
+ argument. After construction, the iterator is located at the very
+ beginning of the list (before the first item). Here's how to
+ iterate over all the elements sequentially:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.qdoc 14
+
+ The next() function returns the next item in the vector and
+ advances the iterator. Unlike STL-style iterators, Java-style
+ iterators point \e between items rather than directly \e at
+ items. The first call to next() advances the iterator to the
+ position between the first and second item, and returns the first
+ item; the second call to next() advances the iterator to the
+ position between the second and third item, returning the second
+ item; and so on.
+
+ \img javaiterators1.png
+
+ Here's how to iterate over the elements in reverse order:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.qdoc 15
+
+ If you want to find all occurrences of a particular value, use
+ findNext() or findPrevious() in a loop.
+
+ If you want to remove items as you iterate over the vector, use
+ remove(). If you want to modify the value of an item, use
+ setValue(). If you want to insert a new item in the vector, use
+ insert().
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qiterator.qdoc 16
+
+ The example traverses a vector, replacing negative numbers with
+ their absolute values, and eliminating zeroes.
+
+ Only one mutable iterator can be active on a given vector at any
+ time. Furthermore, no changes should be done directly to the
+ vector while the iterator is active (as opposed to through the
+ iterator), since this could invalidate the iterator and lead to
+ undefined behavior.
+
+ \sa QVectorIterator, QVector::iterator
+*/
+
+/*!
+ \class QMutableSetIterator
+ \inmodule QtCore
+ \since 4.2
+
+ \brief The QMutableSetIterator class provides a Java-style non-const iterator for QSet.
+
+ QSet has both \l{Java-style iterators} and \l{STL-style
+ iterators}. The Java-style iterators are more high-level and
+ easier to use than the STL-style iterators; on the other hand,
+ they are slightly less efficient.
+
+ QMutableSetIterator\<T\> allows you to iterate over a QSet\<T\>
+ and remove items from the set as you iterate. If you don't want
+ to modify the set (or have a const QSet), use the slightly faster
+ QSetIterator\<T\> instead.
+
+ The QMutableSetIterator constructor takes a QSet as argument.
+ After construction, the iterator is located at the very beginning
+ of the set (before the first item). Here's how to iterate over
+ all the elements sequentially:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.qdoc 17
+
+ The next() function returns the next item in the set and
+ advances the iterator. Unlike STL-style iterators, Java-style
+ iterators point \e between items rather than directly \e at
+ items. The first call to next() advances the iterator to the
+ position between the first and second item, and returns the first
+ item; the second call to next() advances the iterator to the
+ position between the second and third item, returning the second
+ item; and so on.
+
+ \img javaiterators1.png
+
+ Here's how to iterate over the elements in reverse order:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.qdoc 18
+
+ If you want to remove items as you iterate over the set, use
+ remove().
+
+ Only one mutable iterator can be active on a given set at any
+ time. Furthermore, no changes should be done directly to the set
+ while the iterator is active (as opposed to through the
+ iterator), since this could invalidate the iterator and lead to
+ undefined behavior.
+
+ \sa QSetIterator, QSet::iterator
+*/
+
+/*!
+ \fn QListIterator::QListIterator(const QList<T> &list)
+ \fn QLinkedListIterator::QLinkedListIterator(const QLinkedList<T> &list)
+ \fn QMutableListIterator::QMutableListIterator(QList<T> &list)
+ \fn QMutableLinkedListIterator::QMutableLinkedListIterator(QLinkedList<T> &list)
+
+ Constructs an iterator for traversing \a list. The iterator is
+ set to be at the front of the list (before the first item).
+
+ \sa operator=()
+*/
+
+/*!
+ \fn QVectorIterator::QVectorIterator(const QVector<T> &vector)
+ \fn QMutableVectorIterator::QMutableVectorIterator(QVector<T> &vector)
+
+ Constructs an iterator for traversing \a vector. The iterator is
+ set to be at the front of the vector (before the first item).
+
+ \sa operator=()
+*/
+
+/*!
+ \fn QSetIterator::QSetIterator(const QSet<T> &set)
+ \fn QMutableSetIterator::QMutableSetIterator(QSet<T> &set)
+
+ Constructs an iterator for traversing \a set. The iterator is
+ set to be at the front of the set (before the first item).
+
+ \sa operator=()
+*/
+
+/*!
+ \fn QMutableListIterator::~QMutableListIterator()
+ \fn QMutableLinkedListIterator::~QMutableLinkedListIterator()
+ \fn QMutableVectorIterator::~QMutableVectorIterator()
+ \fn QMutableSetIterator::~QMutableSetIterator()
+
+ Destroys the iterator.
+
+ \sa operator=()
+*/
+
+/*! \fn QMutableListIterator &QMutableListIterator::operator=(QList<T> &list)
+ \fn QMutableLinkedListIterator &QMutableLinkedListIterator::operator=(QLinkedList<T> &list)
+ \fn QListIterator &QListIterator::operator=(const QList<T> &list)
+ \fn QLinkedListIterator &QLinkedListIterator::operator=(const QLinkedList<T> &list)
+
+ Makes the iterator operate on \a list. The iterator is set to be
+ at the front of the list (before the first item).
+
+ \sa toFront(), toBack()
+*/
+
+/*! \fn QVectorIterator &QVectorIterator::operator=(const QVector<T> &vector)
+ \fn QMutableVectorIterator &QMutableVectorIterator::operator=(QVector<T> &vector)
+
+ Makes the iterator operate on \a vector. The iterator is set to be
+ at the front of the vector (before the first item).
+
+ \sa toFront(), toBack()
+*/
+
+/*! \fn QSetIterator &QSetIterator::operator=(const QSet<T> &set)
+ \fn QMutableSetIterator &QMutableSetIterator::operator=(QSet<T> &set)
+
+ Makes the iterator operate on \a set. The iterator is set to be
+ at the front of the set (before the first item).
+
+ \sa toFront(), toBack()
+*/
+
+/*! \fn void QListIterator::toFront()
+ \fn void QLinkedListIterator::toFront()
+ \fn void QVectorIterator::toFront()
+ \fn void QSetIterator::toFront()
+ \fn void QMutableListIterator::toFront()
+ \fn void QMutableLinkedListIterator::toFront()
+ \fn void QMutableVectorIterator::toFront()
+ \fn void QMutableSetIterator::toFront()
+
+ Moves the iterator to the front of the container (before the
+ first item).
+
+ \sa toBack(), next()
+*/
+
+/*! \fn void QListIterator::toBack()
+ \fn void QLinkedListIterator::toBack()
+ \fn void QVectorIterator::toBack()
+ \fn void QSetIterator::toBack()
+ \fn void QMutableListIterator::toBack()
+ \fn void QMutableLinkedListIterator::toBack()
+ \fn void QMutableVectorIterator::toBack()
+ \fn void QMutableSetIterator::toBack()
+
+ Moves the iterator to the back of the container (after the last
+ item).
+
+ \sa toFront(), previous()
+*/
+
+/*! \fn bool QListIterator::hasNext() const
+ \fn bool QLinkedListIterator::hasNext() const
+ \fn bool QVectorIterator::hasNext() const
+ \fn bool QSetIterator::hasNext() const
+ \fn bool QMutableListIterator::hasNext() const
+ \fn bool QMutableLinkedListIterator::hasNext() const
+ \fn bool QMutableVectorIterator::hasNext() const
+ \fn bool QMutableSetIterator::hasNext() const
+
+ Returns true if there is at least one item ahead of the iterator,
+ i.e. the iterator is \e not at the back of the container;
+ otherwise returns false.
+
+ \sa hasPrevious(), next()
+*/
+
+/*! \fn const T &QListIterator::next()
+ \fn const T &QLinkedListIterator::next()
+ \fn const T &QVectorIterator::next()
+ \fn const T &QSetIterator::next()
+ \fn const T &QMutableSetIterator::next()
+
+ Returns the next item and advances the iterator by one position.
+
+ Calling this function on an iterator located at the back of the
+ container leads to undefined results.
+
+ \sa hasNext(), peekNext(), previous()
+*/
+
+/*! \fn T &QMutableListIterator::next()
+ \fn T &QMutableLinkedListIterator::next()
+ \fn T &QMutableVectorIterator::next()
+
+ Returns a reference to the next item, and advances the iterator
+ by one position.
+
+ Calling this function on an iterator located at the back of the
+ container leads to undefined results.
+
+ \sa hasNext(), peekNext(), previous()
+*/
+
+/*! \fn const T &QListIterator::peekNext() const
+ \fn const T &QLinkedListIterator::peekNext() const
+ \fn const T &QVectorIterator::peekNext() const
+ \fn const T &QSetIterator::peekNext() const
+ \fn const T &QMutableSetIterator::peekNext() const
+
+ Returns the next item without moving the iterator.
+
+ Calling this function on an iterator located at the back of the
+ container leads to undefined results.
+
+ \sa hasNext(), next(), peekPrevious()
+*/
+
+/*! \fn T &QMutableListIterator::peekNext() const
+ \fn T &QMutableLinkedListIterator::peekNext() const
+ \fn T &QMutableVectorIterator::peekNext() const
+
+ Returns a reference to the next item, without moving the iterator.
+
+ Calling this function on an iterator located at the back of the
+ container leads to undefined results.
+
+ \sa hasNext(), next(), peekPrevious()
+*/
+
+/*! \fn bool QListIterator::hasPrevious() const
+ \fn bool QLinkedListIterator::hasPrevious() const
+ \fn bool QVectorIterator::hasPrevious() const
+ \fn bool QSetIterator::hasPrevious() const
+ \fn bool QMutableListIterator::hasPrevious() const
+ \fn bool QMutableLinkedListIterator::hasPrevious() const
+ \fn bool QMutableVectorIterator::hasPrevious() const
+ \fn bool QMutableSetIterator::hasPrevious() const
+
+ Returns true if there is at least one item behind the iterator,
+ i.e. the iterator is \e not at the front of the container;
+ otherwise returns false.
+
+ \sa hasNext(), previous()
+*/
+
+/*! \fn const T &QListIterator::previous()
+ \fn const T &QLinkedListIterator::previous()
+ \fn const T &QVectorIterator::previous()
+ \fn const T &QSetIterator::previous()
+ \fn const T &QMutableSetIterator::previous()
+
+ Returns the previous item and moves the iterator back by one
+ position.
+
+ Calling this function on an iterator located at the front of the
+ container leads to undefined results.
+
+ \sa hasPrevious(), peekPrevious(), next()
+*/
+
+/*! \fn T &QMutableListIterator::previous()
+ \fn T &QMutableLinkedListIterator::previous()
+ \fn T &QMutableVectorIterator::previous()
+
+ Returns a reference to the previous item and moves the iterator
+ back by one position.
+
+ Calling this function on an iterator located at the front of the
+ container leads to undefined results.
+
+ \sa hasPrevious(), peekPrevious(), next()
+*/
+
+/*! \fn const T &QListIterator::peekPrevious() const
+ \fn const T &QLinkedListIterator::peekPrevious() const
+ \fn const T &QVectorIterator::peekPrevious() const
+ \fn const T &QSetIterator::peekPrevious() const
+ \fn const T &QMutableSetIterator::peekPrevious() const
+
+ Returns the previous item without moving the iterator.
+
+ Calling this function on an iterator located at the front of the
+ container leads to undefined results.
+
+ \sa hasPrevious(), previous(), peekNext()
+*/
+
+/*! \fn T &QMutableListIterator::peekPrevious() const
+ \fn T &QMutableLinkedListIterator::peekPrevious() const
+ \fn T &QMutableVectorIterator::peekPrevious() const
+
+ Returns a reference to the previous item, without moving the iterator.
+
+ Calling this function on an iterator located at the front of the
+ container leads to undefined results.
+
+ \sa hasPrevious(), previous(), peekNext()
+*/
+
+/*! \fn bool QListIterator::findNext(const T &value)
+ \fn bool QLinkedListIterator::findNext(const T &value)
+ \fn bool QVectorIterator::findNext(const T &value)
+ \fn bool QSetIterator::findNext(const T &value)
+ \fn bool QMutableListIterator::findNext(const T &value)
+ \fn bool QMutableLinkedListIterator::findNext(const T &value)
+ \fn bool QMutableVectorIterator::findNext(const T &value)
+ \fn bool QMutableSetIterator::findNext(const T &value)
+
+ Searches for \a value starting from the current iterator position
+ forward. Returns true if \a value is found; otherwise returns false.
+
+ After the call, if \a value was found, the iterator is positioned
+ just after the matching item; otherwise, the iterator is
+ positioned at the back of the container.
+
+ \sa findPrevious()
+*/
+
+/*! \fn bool QListIterator::findPrevious(const T &value)
+ \fn bool QLinkedListIterator::findPrevious(const T &value)
+ \fn bool QVectorIterator::findPrevious(const T &value)
+ \fn bool QSetIterator::findPrevious(const T &value)
+ \fn bool QMutableListIterator::findPrevious(const T &value)
+ \fn bool QMutableLinkedListIterator::findPrevious(const T &value)
+ \fn bool QMutableVectorIterator::findPrevious(const T &value)
+ \fn bool QMutableSetIterator::findPrevious(const T &value)
+
+ Searches for \a value starting from the current iterator position
+ backward. Returns true if \a value is found; otherwise returns
+ false.
+
+ After the call, if \a value was found, the iterator is positioned
+ just before the matching item; otherwise, the iterator is
+ positioned at the front of the container.
+
+ \sa findNext()
+*/
+
+/*! \fn void QMutableListIterator::remove()
+
+ Removes the last item that was jumped over using one of the
+ traversal functions (next(), previous(), findNext(), findPrevious()).
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qiterator.qdoc 19
+
+ \sa insert(), setValue()
+*/
+
+/*! \fn void QMutableLinkedListIterator::remove()
+
+ Removes the last item that was jumped over using one of the
+ traversal functions (next(), previous(), findNext(), findPrevious()).
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qiterator.qdoc 20
+
+ \sa insert(), setValue()
+*/
+
+/*! \fn void QMutableVectorIterator::remove()
+
+ Removes the last item that was jumped over using one of the
+ traversal functions (next(), previous(), findNext(), findPrevious()).
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qiterator.qdoc 21
+
+ \sa insert(), setValue()
+*/
+
+/*! \fn void QMutableSetIterator::remove()
+
+ Removes the last item that was jumped over using one of the
+ traversal functions (next(), previous(), findNext(), findPrevious()).
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qiterator.qdoc 22
+
+ \sa value()
+*/
+
+/*! \fn void QMutableListIterator::setValue(const T &value) const
+
+ Replaces the value of the last item that was jumped over using
+ one of the traversal functions with \a value.
+
+ The traversal functions are next(), previous(), findNext(), and
+ findPrevious().
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qiterator.qdoc 23
+
+ \sa value(), remove(), insert()
+*/
+
+/*! \fn void QMutableLinkedListIterator::setValue(const T &value) const
+
+ Replaces the value of the last item that was jumped over using
+ one of the traversal functions with \a value.
+
+ The traversal functions are next(), previous(), findNext(), and
+ findPrevious().
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qiterator.qdoc 24
+
+ \sa value(), remove(), insert()
+*/
+
+/*! \fn void QMutableVectorIterator::setValue(const T &value) const
+
+ Replaces the value of the last item that was jumped over using
+ one of the traversal functions with \a value.
+
+ The traversal functions are next(), previous(), findNext(), and
+ findPrevious().
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qiterator.qdoc 25
+
+ \sa value(), remove(), insert()
+*/
+
+/*! \fn const T &QMutableListIterator::value() const
+ \fn const T &QMutableLinkedListIterator::value() const
+ \fn const T &QMutableVectorIterator::value() const
+ \fn const T &QMutableSetIterator::value() const
+
+ Returns the value of the last item that was jumped over using one
+ of the traversal functions (next(), previous(), findNext(),
+ findPrevious()).
+
+ After a call to next() or findNext(), value() is equivalent to
+ peekPrevious(). After a call to previous() or findPrevious(), value() is
+ equivalent to peekNext().
+*/
+
+/*!
+ \fn T &QMutableListIterator::value()
+ \fn T &QMutableLinkedListIterator::value()
+ \fn T &QMutableVectorIterator::value()
+ \overload
+
+ Returns a non-const reference to the value of the last item that
+ was jumped over using one of the traversal functions.
+*/
+
+/*! \fn void QMutableListIterator::insert(const T &value)
+ \fn void QMutableLinkedListIterator::insert(const T &value)
+ \fn void QMutableVectorIterator::insert(const T &value)
+
+ Inserts \a value at the current iterator position. After the
+ call, the iterator is located just after the inserted item.
+
+ \sa remove(), setValue()
+*/
+
+/*!
+ \class QMapIterator
+ \inmodule QtCore
+
+ \brief The QMapIterator class provides a Java-style const iterator for QMap and QMultiMap.
+
+ QMap has both \l{Java-style iterators} and \l{STL-style
+ iterators}. The Java-style iterators are more high-level and
+ easier to use than the STL-style iterators; on the other hand,
+ they are slightly less efficient.
+
+ QMapIterator\<Key, T\> allows you to iterate over a QMap (or a
+ QMultiMap). If you want to modify the map as you iterate over
+ it, use QMutableMapIterator instead.
+
+ The QMapIterator constructor takes a QMap as argument. After
+ construction, the iterator is located at the very beginning of
+ the map (before the first item). Here's how to iterate over all
+ the elements sequentially:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.qdoc 26
+
+ The next() function returns the next item in the map and
+ advances the iterator. The key() and value() functions return the
+ key and value of the last item that was jumped over.
+
+ Unlike STL-style iterators, Java-style iterators point \e between
+ items rather than directly \e at items. The first call to next()
+ advances the iterator to the position between the first and
+ second item, and returns the first item; the second call to
+ next() advances the iterator to the position between the second
+ and third item; and so on.
+
+ \img javaiterators1.png
+
+ Here's how to iterate over the elements in reverse order:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.qdoc 27
+
+ If you want to find all occurrences of a particular value, use
+ findNext() or findPrevious() in a loop. For example:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.qdoc 28
+
+ Multiple iterators can be used on the same map. If the map is
+ modified while a QMapIterator is active, the QMapIterator will
+ continue iterating over the original map, ignoring the modified
+ copy.
+
+ \sa QMutableMapIterator, QMap::const_iterator
+*/
+
+/*!
+ \class QHashIterator
+ \inmodule QtCore
+
+ \brief The QHashIterator class provides a Java-style const iterator for QHash and QMultiHash.
+
+ QHash has both \l{Java-style iterators} and \l{STL-style
+ iterators}. The Java-style iterators are more high-level and
+ easier to use than the STL-style iterators; on the other hand,
+ they are slightly less efficient.
+
+ QHashIterator\<Key, T\> allows you to iterate over a QHash (or a
+ QMultiHash). If you want to modify the hash as you iterate over
+ it, use QMutableHashIterator instead.
+
+ The QHashIterator constructor takes a QHash as argument. After
+ construction, the iterator is located at the very beginning of
+ the hash (before the first item). Here's how to iterate over all
+ the elements sequentially:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.qdoc 29
+
+ The next() function returns the next item in the hash and
+ advances the iterator. The key() and value() functions return the
+ key and value of the last item that was jumped over.
+
+ Unlike STL-style iterators, Java-style iterators point \e between
+ items rather than directly \e at items. The first call to next()
+ advances the iterator to the position between the first and
+ second item, and returns the first item; the second call to
+ next() advances the iterator to the position between the second
+ and third item; and so on.
+
+ \img javaiterators1.png
+
+ Here's how to iterate over the elements in reverse order:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.qdoc 30
+
+ If you want to find all occurrences of a particular value, use
+ findNext() or findPrevious() in a loop. For example:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.qdoc 31
+
+ Multiple iterators can be used on the same hash. If the hash is
+ modified while a QHashIterator is active, the QHashIterator will
+ continue iterating over the original hash, ignoring the modified
+ copy.
+
+ \sa QMutableHashIterator, QHash::const_iterator
+*/
+
+/*!
+ \class QMutableMapIterator
+ \inmodule QtCore
+
+ \brief The QMutableMapIterator class provides a Java-style non-const iterator for QMap and QMultiMap.
+
+ QMap has both \l{Java-style iterators} and \l{STL-style
+ iterators}. The Java-style iterators are more high-level and
+ easier to use than the STL-style iterators; on the other hand,
+ they are slightly less efficient.
+
+ QMutableMapIterator\<Key, T\> allows you to iterate over a QMap
+ (or a QMultiMap) and modify the map. If you don't want to modify
+ the map (or have a const QMap), use the slightly faster
+ QMapIterator instead.
+
+ The QMutableMapIterator constructor takes a QMap as argument.
+ After construction, the iterator is located at the very beginning
+ of the map (before the first item). Here's how to iterate over
+ all the elements sequentially:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.qdoc 32
+
+ The next() function returns the next item in the map and
+ advances the iterator. The key() and value() functions return the
+ key and value of the last item that was jumped over.
+
+ Unlike STL-style iterators, Java-style iterators point \e between
+ items rather than directly \e at items. The first call to next()
+ advances the iterator to the position between the first and
+ second item, and returns the first item; the second call to
+ next() advances the iterator to the position between the second
+ and third item; and so on.
+
+ \img javaiterators1.png
+
+ Here's how to iterate over the elements in reverse order:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.qdoc 33
+
+ If you want to find all occurrences of a particular value, use
+ findNext() or findPrevious() in a loop. For example:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.qdoc 34
+
+ If you want to remove items as you iterate over the map, use
+ remove(). If you want to modify the value of an item, use
+ setValue().
+
+ Example:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.qdoc 35
+
+ The example removes all (key, value) pairs where the key and the
+ value are the same.
+
+ Only one mutable iterator can be active on a given map at any
+ time. Furthermore, no changes should be done directly to the map
+ while the iterator is active (as opposed to through the
+ iterator), since this could invalidate the iterator and lead to
+ undefined behavior.
+
+ \sa QMapIterator, QMap::iterator
+*/
+
+/*!
+ \class QMutableHashIterator
+ \inmodule QtCore
+
+ \brief The QMutableHashIterator class provides a Java-style non-const iterator for QHash and QMultiHash.
+
+ QHash has both \l{Java-style iterators} and \l{STL-style
+ iterators}. The Java-style iterators are more high-level and
+ easier to use than the STL-style iterators; on the other hand,
+ they are slightly less efficient.
+
+ QMutableHashIterator\<Key, T\> allows you to iterate over a QHash
+ (or a QMultiHash) and modify the hash. If you don't want to modify
+ the hash (or have a const QHash), use the slightly faster
+ QHashIterator instead.
+
+ The QMutableHashIterator constructor takes a QHash as argument.
+ After construction, the iterator is located at the very beginning
+ of the hash (before the first item). Here's how to iterate over
+ all the elements sequentially:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.qdoc 36
+
+ The next() function returns the next item in the hash and
+ advances the iterator. The key() and value() functions return the
+ key and value of the last item that was jumped over.
+
+ Unlike STL-style iterators, Java-style iterators point \e between
+ items rather than directly \e at items. The first call to next()
+ advances the iterator to the position between the first and
+ second item, and returns the first item; the second call to
+ next() advances the iterator to the position between the second
+ and third item; and so on.
+
+ \img javaiterators1.png
+
+ Here's how to iterate over the elements in reverse order:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.qdoc 37
+
+ If you want to find all occurrences of a particular value, use
+ findNext() or findPrevious() in a loop. For example:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.qdoc 38
+
+ If you want to remove items as you iterate over the hash, use
+ remove(). If you want to modify the value of an item, use
+ setValue().
+
+ Example:
+
+ \snippet doc/src/snippets/code/doc_src_qiterator.qdoc 39
+
+ The example removes all (key, value) pairs where the key and the
+ value are the same.
+
+ Only one mutable iterator can be active on a given hash at any
+ time. Furthermore, no changes should be done directly to the hash
+ while the iterator is active (as opposed to through the
+ iterator), since this could invalidate the iterator and lead to
+ undefined behavior.
+
+ \sa QHashIterator, QHash::iterator
+*/
+
+/*! \fn QMapIterator::QMapIterator(const QMap<Key, T> &map)
+ \fn QMutableMapIterator::QMutableMapIterator(QMap<Key, T> &map)
+
+ Constructs an iterator for traversing \a map. The iterator is set
+ to be at the front of the map (before the first item).
+
+ \sa operator=()
+*/
+
+/*! \fn QHashIterator::QHashIterator(const QHash<Key, T> &hash)
+ \fn QMutableHashIterator::QMutableHashIterator(QHash<Key, T> &hash)
+
+ Constructs an iterator for traversing \a hash. The iterator is
+ set to be at the front of the hash (before the first item).
+
+ \sa operator=()
+*/
+
+/*!
+ \fn QMutableMapIterator::~QMutableMapIterator()
+ \fn QMutableHashIterator::~QMutableHashIterator()
+
+ Destroys the iterator.
+
+ \sa operator=()
+*/
+
+/*! \fn QMapIterator &QMapIterator::operator=(const QMap<Key, T> &map)
+ \fn QMutableMapIterator &QMutableMapIterator::operator=(QMap<Key, T> &map)
+
+ Makes the iterator operate on \a map. The iterator is set to be
+ at the front of the map (before the first item).
+
+ \sa toFront(), toBack()
+*/
+
+/*! \fn QHashIterator &QHashIterator::operator=(const QHash<Key, T> &hash)
+ \fn QMutableHashIterator &QMutableHashIterator::operator=(QHash<Key, T> &hash)
+
+ Makes the iterator operate on \a hash. The iterator is set to be
+ at the front of the hash (before the first item).
+
+ \sa toFront(), toBack()
+*/
+
+/*! \fn void QMapIterator::toFront()
+ \fn void QHashIterator::toFront()
+ \fn void QMutableMapIterator::toFront()
+ \fn void QMutableHashIterator::toFront()
+
+ Moves the iterator to the front of the container (before the
+ first item).
+
+ \sa toBack(), next()
+*/
+
+/*! \fn void QMapIterator::toBack()
+ \fn void QHashIterator::toBack()
+ \fn void QMutableMapIterator::toBack()
+ \fn void QMutableHashIterator::toBack()
+
+ Moves the iterator to the back of the container (after the last
+ item).
+
+ \sa toFront(), previous()
+*/
+
+/*! \fn bool QMapIterator::hasNext() const
+ \fn bool QHashIterator::hasNext() const
+ \fn bool QMutableMapIterator::hasNext() const
+ \fn bool QMutableHashIterator::hasNext() const
+
+ Returns true if there is at least one item ahead of the iterator,
+ i.e. the iterator is \e not at the back of the container;
+ otherwise returns false.
+
+ \sa hasPrevious(), next()
+*/
+
+/*! \fn QMapIterator::Item QMapIterator::next()
+ \fn QHashIterator::Item QHashIterator::next()
+
+ Returns the next item and advances the iterator by one position.
+
+ Call key() on the return value to obtain the item's key, and
+ value() to obtain the value.
+
+ Calling this function on an iterator located at the back of the
+ container leads to undefined results.
+
+ \sa hasNext(), peekNext(), previous()
+*/
+
+/*! \fn QMutableMapIterator::Item QMutableMapIterator::next()
+ \fn QMutableHashIterator::Item QMutableHashIterator::next()
+
+ Returns the next item and advances the iterator by one position.
+
+ Call key() on the return value to obtain the item's key, and
+ value() to obtain the value.
+
+ Calling this function on an iterator located at the back of the
+ container leads to undefined results.
+
+ \sa hasNext(), peekNext(), previous()
+*/
+
+/*! \fn QMapIterator::Item QMapIterator::peekNext() const
+ \fn QHashIterator::Item QHashIterator::peekNext() const
+
+ Returns the next item without moving the iterator.
+
+ Call key() on the return value to obtain the item's key, and
+ value() to obtain the value.
+
+ Calling this function on an iterator located at the back of the
+ container leads to undefined results.
+
+ \sa hasNext(), next(), peekPrevious()
+*/
+
+/*! \fn QMutableMapIterator::Item QMutableMapIterator::peekNext() const
+ \fn QMutableHashIterator::Item QMutableHashIterator::peekNext() const
+
+ Returns a reference to the next item without moving the iterator.
+
+ Call key() on the return value to obtain the item's key, and
+ value() to obtain the value.
+
+ Calling this function on an iterator located at the back of the
+ container leads to undefined results.
+
+ \sa hasNext(), next(), peekPrevious()
+*/
+
+/*! \fn bool QMapIterator::hasPrevious() const
+ \fn bool QHashIterator::hasPrevious() const
+ \fn bool QMutableMapIterator::hasPrevious() const
+ \fn bool QMutableHashIterator::hasPrevious() const
+
+ Returns true if there is at least one item behind the iterator,
+ i.e. the iterator is \e not at the front of the container;
+ otherwise returns false.
+
+ \sa hasNext(), previous()
+*/
+
+/*! \fn QMapIterator::Item QMapIterator::previous()
+ \fn QHashIterator::Item QHashIterator::previous()
+
+ Returns the previous item and moves the iterator back by one
+ position.
+
+ Call key() on the return value to obtain the item's key, and
+ value() to obtain the value.
+
+ Calling this function on an iterator located at the front of the
+ container leads to undefined results.
+
+ \sa hasPrevious(), peekPrevious(), next()
+*/
+
+/*! \fn QMutableMapIterator::Item QMutableMapIterator::previous()
+ \fn QMutableHashIterator::Item QMutableHashIterator::previous()
+
+ Returns the previous item and moves the iterator back by one
+ position.
+
+ Call key() on the return value to obtain the item's key, and
+ value() to obtain the value.
+
+ Calling this function on an iterator located at the front of the
+ container leads to undefined results.
+
+ \sa hasPrevious(), peekPrevious(), next()
+*/
+
+/*! \fn QMapIterator::Item QMapIterator::peekPrevious() const
+ \fn QHashIterator::Item QHashIterator::peekPrevious() const
+
+ Returns the previous item without moving the iterator.
+
+ Call key() on the return value to obtain the item's key, and
+ value() to obtain the value.
+
+ Calling this function on an iterator located at the front of the
+ container leads to undefined results.
+
+ \sa hasPrevious(), previous(), peekNext()
+*/
+
+/*! \fn QMutableMapIterator::Item QMutableMapIterator::peekPrevious() const
+ \fn QMutableHashIterator::Item QMutableHashIterator::peekPrevious() const
+
+ Returns the previous item without moving the iterator.
+
+ Call key() on the return value to obtain the item's key, and
+ value() to obtain the value.
+
+ Calling this function on an iterator located at the front of the
+ container leads to undefined results.
+
+ \sa hasPrevious(), previous(), peekNext()
+*/
+
+/*! \fn const T &QMapIterator::value() const
+ \fn const T &QHashIterator::value() const
+
+ Returns the value of the last item that was jumped over using one
+ of the traversal functions (next(), previous(), findNext(),
+ findPrevious()).
+
+ After a call to next() or findNext(), value() is
+ equivalent to peekPrevious().value(). After a call to previous()
+ or findPrevious(), value() is equivalent to peekNext().value().
+
+ \sa key()
+*/
+
+/*!
+ \fn const T &QMutableMapIterator::value() const
+ \fn const T &QMutableHashIterator::value() const
+
+ Returns the value of the last item that was jumped over using one
+ of the traversal functions (next(), previous(), findNext(),
+ findPrevious()).
+
+ After a call to next() or findNext(), value() is
+ equivalent to peekPrevious().value(). After a call to previous()
+ or findPrevious(), value() is equivalent to peekNext().value().
+
+ \sa key(), setValue()
+*/
+
+/*!
+ \fn T &QMutableMapIterator::value()
+ \fn T &QMutableHashIterator::value()
+ \overload
+
+ Returns a non-const reference to the value of
+ the last item that was jumped over using one
+ of the traversal functions.
+*/
+
+/*! \fn const Key &QMapIterator::key() const
+ \fn const Key &QHashIterator::key() const
+ \fn const Key &QMutableMapIterator::key() const
+ \fn const Key &QMutableHashIterator::key() const
+
+ Returns the key of the last item that was jumped over using one
+ of the traversal functions (next(), previous(), findNext(),
+ findPrevious()).
+
+ After a call to next() or findNext(), key() is
+ equivalent to peekPrevious().key(). After a call to previous() or
+ findPrevious(), key() is equivalent to peekNext().key().
+
+ \sa value()
+*/
+
+/*! \fn bool QMapIterator::findNext(const T &value)
+ \fn bool QHashIterator::findNext(const T &value)
+ \fn bool QMutableMapIterator::findNext(const T &value)
+ \fn bool QMutableHashIterator::findNext(const T &value)
+
+ Searches for \a value starting from the current iterator position
+ forward. Returns true if a (key, value) pair with value \a value
+ is found; otherwise returns false.
+
+ After the call, if \a value was found, the iterator is positioned
+ just after the matching item; otherwise, the iterator is
+ positioned at the back of the container.
+
+ \sa findPrevious()
+*/
+
+/*! \fn bool QMapIterator::findPrevious(const T &value)
+ \fn bool QHashIterator::findPrevious(const T &value)
+ \fn bool QMutableMapIterator::findPrevious(const T &value)
+ \fn bool QMutableHashIterator::findPrevious(const T &value)
+
+ Searches for \a value starting from the current iterator position
+ backward. Returns true if a (key, value) pair with value \a value
+ is found; otherwise returns false.
+
+ After the call, if \a value was found, the iterator is positioned
+ just before the matching item; otherwise, the iterator is
+ positioned at the front of the container.
+
+ \sa findNext()
+*/
+
+/*! \fn void QMutableMapIterator::remove()
+ \fn void QMutableHashIterator::remove()
+
+ Removes the last item that was jumped over using one of the
+ traversal functions (next(), previous(), findNext(), findPrevious()).
+
+ \sa setValue()
+*/
+
+/*! \fn void QMutableMapIterator::setValue(const T &value)
+ \fn void QMutableHashIterator::setValue(const T &value)
+
+ Replaces the value of the last item that was jumped over using
+ one of the traversal functions with \a value.
+
+ The traversal functions are next(), previous(), findNext(), and
+ findPrevious().
+
+ \sa key(), value(), remove()
+*/
diff --git a/src/corelib/tools/qline.cpp b/src/corelib/tools/qline.cpp
index 8f01043152..838e55b22f 100644
--- a/src/corelib/tools/qline.cpp
+++ b/src/corelib/tools/qline.cpp
@@ -49,7 +49,7 @@ QT_BEGIN_NAMESPACE
/*!
\class QLine
- \ingroup multimedia
+ \ingroup painting
\brief The QLine class provides a two-dimensional vector using
integer precision.
@@ -260,7 +260,7 @@ QT_BEGIN_NAMESPACE
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug d, const QLine &p)
{
- d << "QLine(" << p.p1() << "," << p.p2() << ")";
+ d << "QLine(" << p.p1() << ',' << p.p2() << ')';
return d;
}
#endif
@@ -309,7 +309,7 @@ QDataStream &operator>>(QDataStream &stream, QLine &line)
/*!
\class QLineF
- \ingroup multimedia
+ \ingroup painting
\brief The QLineF class provides a two-dimensional vector using
floating point precision.
@@ -822,7 +822,7 @@ qreal QLineF::angle(const QLineF &l) const
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug d, const QLineF &p)
{
- d << "QLineF(" << p.p1() << "," << p.p2() << ")";
+ d << "QLineF(" << p.p1() << ',' << p.p2() << ')';
return d;
}
#endif
diff --git a/src/corelib/tools/qlinkedlist.cpp b/src/corelib/tools/qlinkedlist.cpp
index 1ca4930160..0d4711ba7c 100644
--- a/src/corelib/tools/qlinkedlist.cpp
+++ b/src/corelib/tools/qlinkedlist.cpp
@@ -53,7 +53,7 @@ QLinkedListData QLinkedListData::shared_null = {
\ingroup tools
\ingroup shared
- \mainclass
+
\reentrant
QLinkedList\<T\> is one of Qt's generic \l{container classes}. It
diff --git a/src/corelib/tools/qlinkedlist.h b/src/corelib/tools/qlinkedlist.h
index aeb14be8dc..f7ae421e7b 100644
--- a/src/corelib/tools/qlinkedlist.h
+++ b/src/corelib/tools/qlinkedlist.h
@@ -265,15 +265,22 @@ void QLinkedList<T>::detach_helper()
x.d->ref = 1;
x.d->size = d->size;
x.d->sharable = true;
- Node *i = e->n, *j = x.e;
- while (i != e) {
- j->n = new Node(i->t);
- j->n->p = j;
- i = i->n;
- j = j->n;
+ Node *original = e->n;
+ Node *copy = x.e;
+ while (original != e) {
+ QT_TRY {
+ copy->n = new Node(original->t);
+ copy->n->p = copy;
+ original = original->n;
+ copy = copy->n;
+ } QT_CATCH(...) {
+ copy->n = x.e;
+ free(x.d);
+ QT_RETHROW;
+ }
}
- j->n = x.e;
- x.e->p = j;
+ copy->n = x.e;
+ x.e->p = copy;
if (!d->ref.deref())
free(d);
d = x.d;
@@ -474,14 +481,21 @@ QLinkedList<T> &QLinkedList<T>::operator+=(const QLinkedList<T> &l)
detach();
int n = l.d->size;
d->size += n;
- Node *o = l.e->n;
+ Node *original = l.e->n;
while (n--) {
- Node *i = new Node(o->t);
- o = o->n;
- i->n = e;
- i->p = e->p;
- i->p->n = i;
- e->p = i;
+ QT_TRY {
+ Node *copy = new Node(original->t);
+ original = original->n;
+ copy->n = e;
+ copy->p = e->p;
+ copy->p->n = copy;
+ e->p = copy;
+ } QT_CATCH(...) {
+ // restore the original list
+ while (n++<d->size)
+ removeLast();
+ QT_RETHROW;
+ }
}
return *this;
}
diff --git a/src/corelib/tools/qlistdata.cpp b/src/corelib/tools/qlist.cpp
index 872bdd8076..e63d46dd9b 100644
--- a/src/corelib/tools/qlistdata.cpp
+++ b/src/corelib/tools/qlist.cpp
@@ -39,6 +39,7 @@
**
****************************************************************************/
+#include <new>
#include "qlist.h"
#include "qtools_p.h"
#include <string.h>
@@ -71,15 +72,18 @@ static int grow(int size)
QListData::Data *QListData::detach()
{
Data *x = static_cast<Data *>(qMalloc(DataHeaderSize + d->alloc * sizeof(void *)));
- if (!x)
- qFatal("QList: Out of memory");
+ Q_CHECK_PTR(x);
- ::memcpy(x, d, DataHeaderSize + d->alloc * sizeof(void *));
- x->alloc = d->alloc;
x->ref = 1;
x->sharable = true;
- if (!x->alloc)
- x->begin = x->end = 0;
+ x->alloc = d->alloc;
+ if (!x->alloc) {
+ x->begin = 0;
+ x->end = 0;
+ } else {
+ x->begin = d->begin;
+ x->end = d->end;
+ }
qSwap(d, x);
if (!x->ref.deref())
@@ -87,20 +91,63 @@ QListData::Data *QListData::detach()
return 0;
}
-// Returns the old (shared) data, it is up to the caller to deref() and free()
+/*!
+ * Detaches the QListData by reallocating new memory.
+ * Returns the old (shared) data, it is up to the caller to deref() and free()
+ * For the new data node_copy needs to be called.
+ *
+ * \internal
+ */
+#if QT_VERSION >= 0x050000
+# error "Remove QListData::detach2(), it is only required for binary compatibility for 4.3.x to 4.5.x"
+#endif
QListData::Data *QListData::detach2()
{
Data *x = d;
- d = static_cast<Data *>(qMalloc(DataHeaderSize + x->alloc * sizeof(void *)));
- if (!d)
- qFatal("QList: Out of memory");
-
- ::memcpy(d, x, DataHeaderSize + x->alloc * sizeof(void *));
- d->alloc = x->alloc;
- d->ref = 1;
- d->sharable = true;
- if (!d->alloc)
- d->begin = d->end = 0;
+ Data* t = static_cast<Data *>(qMalloc(DataHeaderSize + x->alloc * sizeof(void *)));
+ Q_CHECK_PTR(t);
+
+ ::memcpy(t, d, DataHeaderSize + d->alloc * sizeof(void *));
+
+ t->ref = 1;
+ t->sharable = true;
+ t->alloc = x->alloc;
+ if (!t->alloc) {
+ t->begin = 0;
+ t->end = 0;
+ } else {
+ t->begin = x->begin;
+ t->end = x->end;
+ }
+ d = t;
+
+ return x;
+}
+
+/*!
+ * Detaches the QListData by reallocating new memory.
+ * Returns the old (shared) data, it is up to the caller to deref() and free()
+ * For the new data node_copy needs to be called.
+ *
+ * \internal
+ */
+QListData::Data *QListData::detach3()
+{
+ Data *x = d;
+ Data* t = static_cast<Data *>(qMalloc(DataHeaderSize + x->alloc * sizeof(void *)));
+ Q_CHECK_PTR(t);
+
+ t->ref = 1;
+ t->sharable = true;
+ t->alloc = x->alloc;
+ if (!t->alloc) {
+ t->begin = 0;
+ t->end = 0;
+ } else {
+ t->begin = x->begin;
+ t->end = x->end;
+ }
+ d = t;
return x;
}
@@ -109,8 +156,7 @@ void QListData::realloc(int alloc)
{
Q_ASSERT(d->ref == 1);
Data *x = static_cast<Data *>(qRealloc(d, DataHeaderSize + alloc * sizeof(void *)));
- if (!x)
- qFatal("QList: Out of memory");
+ Q_CHECK_PTR(x);
d = x;
d->alloc = alloc;
@@ -118,12 +164,14 @@ void QListData::realloc(int alloc)
d->begin = d->end = 0;
}
+// ensures that enough space is available to append one element
void **QListData::append()
{
Q_ASSERT(d->ref == 1);
if (d->end == d->alloc) {
int n = d->end - d->begin;
if (d->begin > 2 * d->alloc / 3) {
+ // we have enough space. Just not at the end -> move it.
::memcpy(d->array + n, d->array + d->begin, n * sizeof(void *));
d->begin = n;
d->end = n * 2;
@@ -134,6 +182,10 @@ void **QListData::append()
return d->array + d->end++;
}
+// ensures that enough space is available to append the list
+#if QT_VERSION >= 0x050000
+# error "Remove QListData::append(), it is only required for binary compatibility up to 4.5.x"
+#endif
void **QListData::append(const QListData& l)
{
Q_ASSERT(d->ref == 1);
@@ -142,7 +194,21 @@ void **QListData::append(const QListData& l)
if (n) {
if (e + n > d->alloc)
realloc(grow(e + l.d->end - l.d->begin));
- ::memcpy(d->array + d->end, l.d->array + l.d->begin, n * sizeof(void*));
+ ::memcpy(d->array + d->end, l.d->array + l.d->begin, n*sizeof(void*));
+ d->end += n;
+ }
+ return d->array + e;
+}
+
+// ensures that enough space is available to append the list
+void **QListData::append2(const QListData& l)
+{
+ Q_ASSERT(d->ref == 1);
+ int e = d->end;
+ int n = l.d->end - l.d->begin;
+ if (n) {
+ if (e + n > d->alloc)
+ realloc(grow(e + l.d->end - l.d->begin));
d->end += n;
}
return d->array + e;
@@ -289,7 +355,7 @@ void **QListData::erase(void **xi)
\ingroup tools
\ingroup shared
- \mainclass
+
\reentrant
QList\<T\> is one of Qt's generic \l{container classes}. It
@@ -514,6 +580,15 @@ void **QListData::erase(void **xi)
\internal
*/
+/*! \fn void QList::detachShared()
+
+ \internal
+
+ like detach(), but does nothing if we're shared_null.
+ This prevents needless mallocs, and makes QList more exception safe
+ in case of cleanup work done in destructors on empty lists.
+*/
+
/*! \fn bool QList::isDetached() const
\internal
diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h
index fcab7c1c5c..ba8ae567a1 100644
--- a/src/corelib/tools/qlist.h
+++ b/src/corelib/tools/qlist.h
@@ -72,13 +72,15 @@ struct Q_CORE_EXPORT QListData {
enum { DataHeaderSize = sizeof(Data) - sizeof(void *) };
Data *detach(); // remove in 5.0
- Data *detach2();
+ Data *detach2(); // remove in 5.0
+ Data *detach3();
void realloc(int alloc);
static Data shared_null;
Data *d;
void **erase(void **xi);
void **append();
void **append(const QListData &l);
+ void **append2(const QListData &l); // remove in 5.0
void **prepend();
void **insert(int i);
void remove(int i);
@@ -117,6 +119,14 @@ public:
inline int size() const { return p.size(); }
inline void detach() { if (d->ref != 1) detach_helper(); }
+
+ inline void detachShared()
+ {
+ // The "this->" qualification is needed for GCCE.
+ if (d->ref != 1 && this->d != &QListData::shared_null)
+ detach_helper();
+ }
+
inline bool isDetached() const { return d->ref == 1; }
inline void setSharable(bool sharable) { if (!sharable) detach(); d->sharable = sharable; }
@@ -352,12 +362,31 @@ Q_INLINE_TEMPLATE void QList<T>::node_destruct(Node *n)
template <typename T>
Q_INLINE_TEMPLATE void QList<T>::node_copy(Node *from, Node *to, Node *src)
{
- if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic)
- while(from != to)
- (from++)->v = new T(*reinterpret_cast<T*>((src++)->v));
- else if (QTypeInfo<T>::isComplex)
- while(from != to)
- new (from++) T(*reinterpret_cast<T*>(src++));
+ Node *current = from;
+ if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) {
+ QT_TRY {
+ while(current != to) {
+ (current++)->v = new T(*reinterpret_cast<T*>((src++)->v));
+ }
+ } QT_CATCH(...) {
+ while (current != from)
+ delete reinterpret_cast<T*>(current--);
+ QT_RETHROW;
+ }
+
+ } else if (QTypeInfo<T>::isComplex) {
+ QT_TRY {
+ while(current != to)
+ new (current++) T(*reinterpret_cast<T*>(src++));
+ } QT_CATCH(...) {
+ while (current != from)
+ (reinterpret_cast<T*>(current--))->~T();
+ QT_RETHROW;
+ }
+ } else {
+ if (src != from && to - from > 0)
+ memcpy(from, src, (to - from) * sizeof(Node *));
+ }
}
template <typename T>
@@ -384,8 +413,17 @@ Q_INLINE_TEMPLATE QList<T> &QList<T>::operator=(const QList<T> &l)
}
template <typename T>
inline typename QList<T>::iterator QList<T>::insert(iterator before, const T &t)
-{ Node *n = reinterpret_cast<Node *>(p.insert(before.i-reinterpret_cast<Node *>(p.begin())));
- node_construct(n,t); return n; }
+{
+ int iBefore = before.i - reinterpret_cast<Node *>(p.begin());
+ Node *n = reinterpret_cast<Node *>(p.insert(iBefore));
+ QT_TRY {
+ node_construct(n, t);
+ } QT_CATCH(...) {
+ p.remove(iBefore);
+ QT_RETHROW;
+ }
+ return n;
+}
template <typename T>
inline typename QList<T>::iterator QList<T>::erase(iterator it)
{ node_destruct(it.i);
@@ -423,10 +461,22 @@ Q_OUTOFLINE_TEMPLATE void QList<T>::append(const T &t)
{
detach();
if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) {
- node_construct(reinterpret_cast<Node *>(p.append()), t);
+ Node *n = reinterpret_cast<Node *>(p.append());
+ QT_TRY {
+ node_construct(n, t);
+ } QT_CATCH(...) {
+ --d->end;
+ QT_RETHROW;
+ }
} else {
const T cpy(t);
- node_construct(reinterpret_cast<Node *>(p.append()), cpy);
+ Node *n = reinterpret_cast<Node *>(p.append());
+ QT_TRY {
+ node_construct(n, cpy);
+ } QT_CATCH(...) {
+ --d->end;
+ QT_RETHROW;
+ }
}
}
@@ -435,10 +485,22 @@ inline void QList<T>::prepend(const T &t)
{
detach();
if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) {
- node_construct(reinterpret_cast<Node *>(p.prepend()), t);
+ Node *n = reinterpret_cast<Node *>(p.prepend());
+ QT_TRY {
+ node_construct(n, t);
+ } QT_CATCH(...) {
+ ++d->begin;
+ QT_RETHROW;
+ }
} else {
const T cpy(t);
- node_construct(reinterpret_cast<Node *>(p.prepend()), cpy);
+ Node *n = reinterpret_cast<Node *>(p.prepend());
+ QT_TRY {
+ node_construct(n, cpy);
+ } QT_CATCH(...) {
+ ++d->begin;
+ QT_RETHROW;
+ }
}
}
@@ -447,10 +509,22 @@ inline void QList<T>::insert(int i, const T &t)
{
detach();
if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) {
- node_construct(reinterpret_cast<Node *>(p.insert(i)), t);
+ Node *n = reinterpret_cast<Node *>(p.insert(i));
+ QT_TRY {
+ node_construct(n, t);
+ } QT_CATCH(...) {
+ p.remove(i);
+ QT_RETHROW;
+ }
} else {
const T cpy(t);
- node_construct(reinterpret_cast<Node *>(p.insert(i)), cpy);
+ Node *n = reinterpret_cast<Node *>(p.insert(i));
+ QT_TRY {
+ node_construct(n, cpy);
+ } QT_CATCH(...) {
+ p.remove(i);
+ QT_RETHROW;
+ }
}
}
@@ -521,8 +595,15 @@ template <typename T>
Q_OUTOFLINE_TEMPLATE void QList<T>::detach_helper()
{
Node *n = reinterpret_cast<Node *>(p.begin());
- QListData::Data *x = p.detach2();
- node_copy(reinterpret_cast<Node *>(p.begin()), reinterpret_cast<Node *>(p.end()), n);
+ QListData::Data *x = p.detach3();
+ QT_TRY {
+ node_copy(reinterpret_cast<Node *>(p.begin()), reinterpret_cast<Node *>(p.end()), n);
+ } QT_CATCH(...) {
+ qFree(d);
+ d = x;
+ QT_RETHROW;
+ }
+
if (!x->ref.deref())
free(x);
}
@@ -572,7 +653,7 @@ Q_OUTOFLINE_TEMPLATE void QList<T>::clear()
template <typename T>
Q_OUTOFLINE_TEMPLATE int QList<T>::removeAll(const T &_t)
{
- detach();
+ detachShared();
const T t = _t;
int removedCount=0, i=0;
Node *n;
@@ -590,7 +671,7 @@ Q_OUTOFLINE_TEMPLATE int QList<T>::removeAll(const T &_t)
template <typename T>
Q_OUTOFLINE_TEMPLATE bool QList<T>::removeOne(const T &_t)
{
- detach();
+ detachShared();
int index = indexOf(_t);
if (index != -1) {
removeAt(index);
@@ -614,8 +695,14 @@ template <typename T>
Q_OUTOFLINE_TEMPLATE QList<T> &QList<T>::operator+=(const QList<T> &l)
{
detach();
- Node *n = reinterpret_cast<Node *>(p.append(l.p));
- node_copy(n, reinterpret_cast<Node *>(p.end()), reinterpret_cast<Node *>(l.p.begin()));
+ Node *n = reinterpret_cast<Node *>(p.append2(l.p));
+ QT_TRY{
+ node_copy(n, reinterpret_cast<Node *>(p.end()), reinterpret_cast<Node *>(l.p.begin()));
+ } QT_CATCH(...) {
+ // restore the old end
+ d->end -= (reinterpret_cast<Node *>(p.end()) - n);
+ QT_RETHROW;
+ }
return *this;
}
diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp
index 1ebebf81c3..ded36c2db9 100644
--- a/src/corelib/tools/qlocale.cpp
+++ b/src/corelib/tools/qlocale.cpp
@@ -42,7 +42,6 @@
#include "qglobal.h"
#ifndef QT_NO_SYSTEMLOCALE
-#define QLOCALE_CPP
QT_BEGIN_NAMESPACE
class QSystemLocale;
static QSystemLocale *QSystemLocale_globalSystemLocale();
@@ -120,9 +119,16 @@ static char *_qdtoa( NEEDS_VOLATILE double d, int mode, int ndigits, int *decpt,
Q_CORE_EXPORT char *qdtoa(double d, int mode, int ndigits, int *decpt,
int *sign, char **rve, char **digits_str);
Q_CORE_EXPORT double qstrtod(const char *s00, char const **se, bool *ok);
-Q_CORE_EXPORT qlonglong qstrtoll(const char *nptr, const char **endptr, register int base, bool *ok);
+static qlonglong qstrtoll(const char *nptr, const char **endptr, register int base, bool *ok);
static qulonglong qstrtoull(const char *nptr, const char **endptr, register int base, bool *ok);
+#if defined(Q_CC_MWERKS) && defined(Q_OS_WIN32)
+inline bool isascii(int c)
+{
+ return (c >= 0 && c <=127);
+}
+#endif
+
/******************************************************************************
** Helpers for accessing Qt locale database
*/
@@ -186,8 +192,7 @@ static QString languageToCode(QLocale::Language language)
const unsigned char *c = language_code_list + 3*(uint(language));
- QString code;
- code.resize(c[2] == 0 ? 2 : 3);
+ QString code(c[2] == 0 ? 2 : 3, Qt::Uninitialized);
code[0] = ushort(c[0]);
code[1] = ushort(c[1]);
@@ -202,8 +207,7 @@ static QString countryToCode(QLocale::Country country)
if (country == QLocale::AnyCountry)
return QString();
- QString code;
- code.resize(2);
+ QString code(2, Qt::Uninitialized);
const unsigned char *c = country_code_list + 2*(uint(country));
code[0] = ushort(c[0]);
code[1] = ushort(c[1]);
@@ -291,7 +295,7 @@ static bool splitLocaleName(const QString &name, QChar *lang_begin, QChar *cntry
return lang_len == 2 || lang_len == 3;
}
-static void getLangAndCountry(const QString &name, QLocale::Language &lang, QLocale::Country &cntry)
+void getLangAndCountry(const QString &name, QLocale::Language &lang, QLocale::Country &cntry)
{
lang = QLocale::C;
cntry = QLocale::AnyCountry;
@@ -321,7 +325,7 @@ static QString readEscapedFormatString(const QString &format, int *idx)
{
int &i = *idx;
- Q_ASSERT(format.at(i).unicode() == '\'');
+ Q_ASSERT(format.at(i) == QLatin1Char('\''));
++i;
if (i == format.size())
return QString();
@@ -389,15 +393,8 @@ static QString winIso3116CtryName(LCID id = LOCALE_USER_DEFAULT);
static QString getWinLocaleInfo(LCTYPE type)
{
- int cnt = 0;
-
LCID id = GetUserDefaultLCID();
-
- QT_WA({
- cnt = GetLocaleInfoW(id, type, 0, 0)*2;
- } , {
- cnt = GetLocaleInfoA(id, type, 0, 0);
- });
+ int cnt = GetLocaleInfo(id, type, 0, 0) * 2;
if (cnt == 0) {
qWarning("QLocale: empty windows locale info (%d)", (int)type);
@@ -406,27 +403,14 @@ static QString getWinLocaleInfo(LCTYPE type)
QByteArray buff(cnt, 0);
- QT_WA({
- cnt = GetLocaleInfoW(id, type,
- reinterpret_cast<wchar_t*>(buff.data()),
- buff.size()/2);
- } , {
- cnt = GetLocaleInfoA(id, type,
- buff.data(), buff.size());
- });
+ cnt = GetLocaleInfo(id, type, reinterpret_cast<wchar_t*>(buff.data()), buff.size() / 2);
if (cnt == 0) {
qWarning("QLocale: empty windows locale info (%d)", (int)type);
return QString();
}
- QString result;
- QT_WA({
- result = QString::fromUtf16(reinterpret_cast<ushort*>(buff.data()));
- } , {
- result = QString::fromLocal8Bit(buff.data());
- });
- return result;
+ return QString::fromWCharArray(reinterpret_cast<const wchar_t *>(buff.data()));
}
QByteArray getWinLocaleName(LCID id = LOCALE_USER_DEFAULT)
@@ -436,8 +420,8 @@ QByteArray getWinLocaleName(LCID id = LOCALE_USER_DEFAULT)
result = envVarLocale();
QChar lang[3];
QChar cntry[2];
- if ( result == "C" || !result.isEmpty()
- && splitLocaleName(QString::fromLocal8Bit(result), lang, cntry) ) {
+ if ( result == "C" || (!result.isEmpty()
+ && splitLocaleName(QString::fromLocal8Bit(result), lang, cntry)) ) {
long id = 0;
bool ok = false;
id = qstrtoll(result.data(), 0, 0, &ok);
@@ -448,20 +432,19 @@ QByteArray getWinLocaleName(LCID id = LOCALE_USER_DEFAULT)
}
}
- if (QSysInfo::WindowsVersion == QSysInfo::WV_95
- || (QSysInfo::WindowsVersion & QSysInfo::WV_CE_based)) {
- result = winLangCodeToIsoName(id != LOCALE_USER_DEFAULT ? id : GetUserDefaultLCID());
- } else {
- if (id == LOCALE_USER_DEFAULT)
- id = GetUserDefaultLCID();
- QString resultuage = winIso639LangName(id);
- QString country = winIso3116CtryName(id);
- result = resultuage.toLatin1();
- if (!country.isEmpty()) {
- result += '_';
- result += country.toLatin1();
- }
+#if defined(Q_OS_WINCE)
+ result = winLangCodeToIsoName(id != LOCALE_USER_DEFAULT ? id : GetUserDefaultLCID());
+#else
+ if (id == LOCALE_USER_DEFAULT)
+ id = GetUserDefaultLCID();
+ QString resultuage = winIso639LangName(id);
+ QString country = winIso3116CtryName(id);
+ result = resultuage.toLatin1();
+ if (!country.isEmpty()) {
+ result += '_';
+ result += country.toLatin1();
}
+#endif
return result;
}
@@ -547,15 +530,9 @@ static QString winDateToString(const QDate &date, DWORD flags)
LCID id = GetUserDefaultLCID();
- QT_WA({
- TCHAR buf[255];
- if (GetDateFormatW(id, flags, &st, 0, buf, 255))
- return QString::fromUtf16((ushort*)buf);
- } , {
- char buf[255];
- if (GetDateFormatA(id, flags, &st, 0, (char*)&buf, 255))
- return QString::fromLocal8Bit(buf);
- });
+ wchar_t buf[255];
+ if (GetDateFormat(id, flags, &st, 0, buf, 255))
+ return QString::fromWCharArray(buf);
return QString();
}
@@ -572,15 +549,9 @@ static QString winTimeToString(const QTime &time)
DWORD flags = 0;
LCID id = GetUserDefaultLCID();
- QT_WA({
- TCHAR buf[255];
- if (GetTimeFormatW(id, flags, &st, 0, buf, 255))
- return QString::fromUtf16((ushort*)buf);
- } , {
- char buf[255];
- if (GetTimeFormatA(id, flags, &st, 0, (char*)&buf, 255))
- return QString::fromLocal8Bit(buf);
- });
+ wchar_t buf[255];
+ if (GetTimeFormat(id, flags, &st, 0, buf, 255))
+ return QString::fromWCharArray(buf);
return QString();
}
@@ -629,13 +600,11 @@ static QString winMonthName(int month, bool short_format)
static QLocale::MeasurementSystem winSystemMeasurementSystem()
{
LCID id = GetUserDefaultLCID();
- TCHAR output[2];
+ wchar_t output[2];
if (GetLocaleInfo(id, LOCALE_IMEASURE, output, 2)) {
- QString iMeasure = QT_WA_INLINE(
- QString::fromUtf16(reinterpret_cast<ushort*>(output)),
- QString::fromLocal8Bit(reinterpret_cast<char*>(output)));
- if (iMeasure == QString::fromLatin1("1")) {
+ QString iMeasure = QString::fromWCharArray(output);
+ if (iMeasure == QLatin1String("1")) {
return QLocale::ImperialSystem;
}
}
@@ -646,12 +615,10 @@ static QLocale::MeasurementSystem winSystemMeasurementSystem()
static QString winSystemAMText()
{
LCID id = GetUserDefaultLCID();
- TCHAR output[15]; // maximum length including terminating zero character for Win2003+
+ wchar_t output[15]; // maximum length including terminating zero character for Win2003+
if (GetLocaleInfo(id, LOCALE_S1159, output, 15)) {
- return QT_WA_INLINE(
- QString::fromUtf16(reinterpret_cast<ushort*>(output)),
- QString::fromLocal8Bit(reinterpret_cast<char*>(output)));
+ return QString::fromWCharArray(output);
}
return QString();
@@ -660,12 +627,10 @@ static QString winSystemAMText()
static QString winSystemPMText()
{
LCID id = GetUserDefaultLCID();
- TCHAR output[15]; // maximum length including terminating zero character for Win2003+
+ wchar_t output[15]; // maximum length including terminating zero character for Win2003+
if (GetLocaleInfo(id, LOCALE_S2359, output, 15)) {
- return QT_WA_INLINE(
- QString::fromUtf16(reinterpret_cast<ushort*>(output)),
- QString::fromLocal8Bit(reinterpret_cast<char*>(output)));
+ return QString::fromWCharArray(output);
}
return QString();
@@ -769,11 +734,8 @@ QVariant QSystemLocale::query(QueryType type, QVariant in = QVariant()) const
return QVariant();
}
-/* Win95 doesn't have a function to return the ISO lang/country name of the user's locale.
- Instead it can return a "Windows code". This maps windows codes to ISO country names. */
-
struct WindowsToISOListElt {
- int windows_code;
+ ushort windows_code;
char iso_name[6];
};
@@ -927,15 +889,9 @@ static QString winIso639LangName(LCID id)
// Windows returns the wrong ISO639 for some languages, we need to detect them here using
// the language code
QString lang_code;
- QT_WA({
- TCHAR out[256];
- if (GetLocaleInfoW(id, LOCALE_ILANGUAGE, out, 255))
- lang_code = QString::fromUtf16((ushort*)out);
- } , {
- char out[256];
- if (GetLocaleInfoA(id, LOCALE_ILANGUAGE, out, 255))
- lang_code = QString::fromLocal8Bit(out);
- });
+ wchar_t out[256];
+ if (GetLocaleInfo(id, LOCALE_ILANGUAGE, out, 255))
+ lang_code = QString::fromWCharArray(out);
if (!lang_code.isEmpty()) {
const char *endptr;
@@ -957,15 +913,8 @@ static QString winIso639LangName(LCID id)
return result;
// not one of the problematic languages - do the usual lookup
- QT_WA({
- TCHAR out[256];
- if (GetLocaleInfoW(id, LOCALE_SISO639LANGNAME , out, 255))
- result = QString::fromUtf16((ushort*)out);
- } , {
- char out[256];
- if (GetLocaleInfoA(id, LOCALE_SISO639LANGNAME, out, 255))
- result = QString::fromLocal8Bit(out);
- });
+ if (GetLocaleInfo(id, LOCALE_SISO639LANGNAME , out, 255))
+ result = QString::fromWCharArray(out);
return result;
}
@@ -974,15 +923,9 @@ static QString winIso3116CtryName(LCID id)
{
QString result;
- QT_WA({
- TCHAR out[256];
- if (GetLocaleInfoW(id, LOCALE_SISO3166CTRYNAME, out, 255))
- result = QString::fromUtf16((ushort*)out);
- } , {
- char out[256];
- if (GetLocaleInfoA(id, LOCALE_SISO3166CTRYNAME, out, 255))
- result = QString::fromLocal8Bit(out);
- });
+ wchar_t out[256];
+ if (GetLocaleInfo(id, LOCALE_SISO3166CTRYNAME, out, 255))
+ result = QString::fromWCharArray(out);
return result;
}
@@ -1014,21 +957,17 @@ static QString macMonthName(int month, bool short_format)
if (month < 0 || month > 11)
return QString();
-#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) {
- QCFType<CFDateFormatterRef> formatter
- = CFDateFormatterCreate(0, QCFType<CFLocaleRef>(CFLocaleCopyCurrent()),
- kCFDateFormatterNoStyle, kCFDateFormatterNoStyle);
- QCFType<CFArrayRef> values
- = static_cast<CFArrayRef>(CFDateFormatterCopyProperty(formatter,
- short_format ? kCFDateFormatterShortMonthSymbols
- : kCFDateFormatterMonthSymbols));
- if (values != 0) {
- CFStringRef cfstring = static_cast<CFStringRef>(CFArrayGetValueAtIndex(values, month));
- return QCFString::toQString(cfstring);
- }
+ QCFType<CFDateFormatterRef> formatter
+ = CFDateFormatterCreate(0, QCFType<CFLocaleRef>(CFLocaleCopyCurrent()),
+ kCFDateFormatterNoStyle, kCFDateFormatterNoStyle);
+ QCFType<CFArrayRef> values
+ = static_cast<CFArrayRef>(CFDateFormatterCopyProperty(formatter,
+ short_format ? kCFDateFormatterShortMonthSymbols
+ : kCFDateFormatterMonthSymbols));
+ if (values != 0) {
+ CFStringRef cfstring = static_cast<CFStringRef>(CFArrayGetValueAtIndex(values, month));
+ return QCFString::toQString(cfstring);
}
-#endif
return QString();
}
@@ -1038,20 +977,16 @@ static QString macDayName(int day, bool short_format)
if (day < 1 || day > 7)
return QString();
-#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) {
- QCFType<CFDateFormatterRef> formatter
- = CFDateFormatterCreate(0, QCFType<CFLocaleRef>(CFLocaleCopyCurrent()),
- kCFDateFormatterNoStyle, kCFDateFormatterNoStyle);
- QCFType<CFArrayRef> values = static_cast<CFArrayRef>(CFDateFormatterCopyProperty(formatter,
- short_format ? kCFDateFormatterShortWeekdaySymbols
- : kCFDateFormatterWeekdaySymbols));
- if (values != 0) {
- CFStringRef cfstring = static_cast<CFStringRef>(CFArrayGetValueAtIndex(values, day % 7));
- return QCFString::toQString(cfstring);
- }
+ QCFType<CFDateFormatterRef> formatter
+ = CFDateFormatterCreate(0, QCFType<CFLocaleRef>(CFLocaleCopyCurrent()),
+ kCFDateFormatterNoStyle, kCFDateFormatterNoStyle);
+ QCFType<CFArrayRef> values = static_cast<CFArrayRef>(CFDateFormatterCopyProperty(formatter,
+ short_format ? kCFDateFormatterShortWeekdaySymbols
+ : kCFDateFormatterWeekdaySymbols));
+ if (values != 0) {
+ CFStringRef cfstring = static_cast<CFStringRef>(CFArrayGetValueAtIndex(values, day % 7));
+ return QCFString::toQString(cfstring);
}
-#endif
return QString();
}
@@ -1136,7 +1071,7 @@ static QString macToQtFormat(const QString &sys_fmt)
break;
case 'S': // fractional second
if (repeat < 3)
- result += QLatin1String("z");
+ result += QLatin1Char('z');
else
result += QLatin1String("zzz");
break;
@@ -1150,7 +1085,7 @@ static QString macToQtFormat(const QString &sys_fmt)
if (repeat >= 2)
result += QLatin1String("dd");
else
- result += QLatin1String("d");
+ result += QLatin1Char('d');
break;
case 'a':
result += QLatin1String("AP");
@@ -1271,7 +1206,7 @@ QVariant QSystemLocale::query(QueryType type, QVariant in = QVariant()) const
return QVariant();
}
-#elif defined(Q_OS_UNIX)
+#elif defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN)
static uint unixGetSystemMeasurementSystem()
{
@@ -1315,7 +1250,7 @@ QVariant QSystemLocale::query(QueryType type, QVariant /* in */) const
}
}
-#else
+#elif !defined(Q_OS_SYMBIAN)
/*!
Returns a fallback locale, that will get used for everything that
@@ -1534,7 +1469,7 @@ QDataStream &operator>>(QDataStream &ds, QLocale &l)
l = QLocale(s);
return ds;
}
-#endif
+#endif // QT_NO_DATASTREAM
/*!
@@ -1544,9 +1479,9 @@ QDataStream &operator>>(QDataStream &ds, QLocale &l)
\reentrant
\ingroup i18n
- \ingroup text
+ \ingroup string-processing
\ingroup shared
- \mainclass
+
QLocale is initialized with a language/country pair in its
constructor and offers number-to-string and string-to-number
@@ -1602,6 +1537,8 @@ QDataStream &operator>>(QDataStream &ds, QLocale &l)
This constructor converts the locale name to a language/country
pair; it does not use the system locale database.
+ QLocale's data is based on Common Locale Data Repository v1.6.1.
+
The double-to-string and string-to-double conversion functions are
covered by the following licenses:
@@ -1622,8 +1559,6 @@ QDataStream &operator>>(QDataStream &ds, QLocale &l)
This product includes software developed by the University of
California, Berkeley and its contributors.
- QLocale's data is based on Common Locale Data Repository v1.6.1.
-
\sa QString::arg(), QString::toInt(), QString::toDouble()
*/
@@ -2700,7 +2635,7 @@ static QString timeZone()
DWORD res = GetTimeZoneInformation(&info);
if (res == TIME_ZONE_ID_UNKNOWN)
return QString();
- return QString::fromUtf16(reinterpret_cast<const ushort *> (info.StandardName));
+ return QString::fromWCharArray(info.StandardName);
#elif defined(Q_OS_WIN)
_tzset();
# if defined(_MSC_VER) && _MSC_VER >= 1400
@@ -2712,6 +2647,8 @@ static QString timeZone()
# else
return QString::fromLocal8Bit(_tzname[1]);
# endif
+#elif defined(Q_OS_VXWORKS)
+ return QString();
#else
tzset();
return QString::fromLocal8Bit(tzname[1]);
@@ -3947,7 +3884,13 @@ QString QLocalePrivate::doubleToString(double d,
char *rve = 0;
char *buff = 0;
- digits = QLatin1String(qdtoa(d, mode, pr, &decpt, &sign, &rve, &buff));
+ QT_TRY {
+ digits = QLatin1String(qdtoa(d, mode, pr, &decpt, &sign, &rve, &buff));
+ } QT_CATCH(...) {
+ if (buff != 0)
+ free(buff);
+ QT_RETHROW;
+ }
if (buff != 0)
free(buff);
#endif // QT_QLOCALE_USES_FCVT
@@ -4671,7 +4614,7 @@ static qulonglong qstrtoull(const char *nptr, const char **endptr, register int
* Ignores `locale' stuff. Assumes that the upper and lower case
* alphabets and digits are each contiguous.
*/
-Q_CORE_EXPORT qlonglong qstrtoll(const char *nptr, const char **endptr, register int base, bool *ok)
+static qlonglong qstrtoll(const char *nptr, const char **endptr, register int base, bool *ok)
{
register const char *s;
register qulonglong acc;
@@ -5010,6 +4953,9 @@ static inline void Storeinc(ULong *&a, const ULong &b, const ULong &c)
#define Bletch 0x10
#define Bndry_mask 0xfffff
#define Bndry_mask1 0xfffff
+#if defined(LSB) && defined(Q_OS_VXWORKS)
+#undef LSB
+#endif
#define LSB 1
#define Sign_bit 0x80000000
#define Log2P 1
@@ -5117,6 +5063,7 @@ static Bigint *Balloc(int k)
x = 1 << k;
rv = static_cast<Bigint *>(MALLOC(sizeof(Bigint) + (x-1)*sizeof(Long)));
+ Q_CHECK_PTR(rv);
rv->k = k;
rv->maxwds = x;
rv->sign = rv->wds = 0;
@@ -5367,6 +5314,18 @@ static Bigint *mult(Bigint *a, Bigint *b)
static Bigint *p5s;
+struct p5s_deleter
+{
+ ~p5s_deleter()
+ {
+ while (p5s) {
+ Bigint *next = p5s->next;
+ Bfree(p5s);
+ p5s = next;
+ }
+ }
+};
+
static Bigint *pow5mult(Bigint *b, int k)
{
Bigint *b1, *p5, *p51;
@@ -5388,6 +5347,7 @@ static Bigint *pow5mult(Bigint *b, int k)
return b;
if (!(p5 = p5s)) {
/* first time */
+ static p5s_deleter deleter;
p5 = p5s = i2b(625);
p5->next = 0;
}
@@ -6780,7 +6740,13 @@ static char *_qdtoa( NEEDS_VOLATILE double d, int mode, int ndigits, int *decpt,
if (i <= 0)
i = 1;
}
- *resultp = static_cast<char *>(malloc(i + 1));
+ QT_TRY {
+ *resultp = static_cast<char *>(malloc(i + 1));
+ Q_CHECK_PTR(*resultp);
+ } QT_CATCH(...) {
+ Bfree(b);
+ QT_RETHROW;
+ }
s = s0 = *resultp;
if (ilim >= 0 && ilim <= Quick_max && try_quick) {
@@ -7202,6 +7168,7 @@ Q_CORE_EXPORT char *qdtoa( double d, int mode, int ndigits, int *decpt, int *sig
n = i + 1;
}
*resultp = static_cast<char*>(malloc(n + 1));
+ Q_CHECK_PTR(resultp);
qstrncpy(*resultp, res, n + 1);
return *resultp;
}
diff --git a/src/corelib/tools/qlocale.h b/src/corelib/tools/qlocale.h
index 313d9ff9f1..4248a3d1e0 100644
--- a/src/corelib/tools/qlocale.h
+++ b/src/corelib/tools/qlocale.h
@@ -99,11 +99,9 @@ public:
virtual QVariant query(QueryType type, QVariant in) const;
virtual QLocale fallbackLocale() const;
-#ifdef QLOCALE_CPP
private:
QSystemLocale(bool);
friend QSystemLocale *QSystemLocale_globalSystemLocale();
-#endif
};
#endif
diff --git a/src/corelib/tools/qlocale_data_p.h b/src/corelib/tools/qlocale_data_p.h
index 7a0c89d60f..8f931c0211 100644
--- a/src/corelib/tools/qlocale_data_p.h
+++ b/src/corelib/tools/qlocale_data_p.h
@@ -60,8 +60,8 @@ QT_BEGIN_NAMESPACE
*/
struct CountryLanguage
{
- quint32 languageId;
- quint32 countryId;
+ quint16 languageId;
+ quint16 countryId;
};
static const CountryLanguage ImperialMeasurementSystems[] = {
{ 31, 225 },
@@ -83,7 +83,7 @@ static const int ImperialMeasurementSystemsCount =
*/
-static const uint locale_index[] = {
+static const quint16 locale_index[] = {
0, // unused
0, // C
0, // Abkhazian
@@ -2313,7 +2313,7 @@ static const char language_name_list[] =
"Chewa\0"
;
-static const uint language_name_index[] = {
+static const quint16 language_name_index[] = {
0, // Unused
8, // C
10, // Abkhazian
@@ -2727,7 +2727,7 @@ static const char country_name_list[] =
"SerbiaAndMontenegro\0"
;
-static const uint country_name_index[] = {
+static const quint16 country_name_index[] = {
0, // AnyCountry
8, // Afghanistan
20, // Albania
diff --git a/src/corelib/tools/qlocale_p.h b/src/corelib/tools/qlocale_p.h
index fadd3a1a1d..a1e79a1156 100644
--- a/src/corelib/tools/qlocale_p.h
+++ b/src/corelib/tools/qlocale_p.h
@@ -96,7 +96,7 @@ public:
ShowBase = 0x80,
UppercaseBase = 0x100,
- ForcePoint = Alternate,
+ ForcePoint = Alternate
};
enum GroupSeparatorMode {
@@ -140,29 +140,29 @@ public:
QString dateTimeToString(const QString &format, const QDate *date, const QTime *time,
const QLocale *q) const;
- quint32 m_language_id, m_country_id;
+ quint16 m_language_id, m_country_id;
quint16 m_decimal, m_group, m_list, m_percent,
m_zero, m_minus, m_plus, m_exponential;
- quint32 m_short_date_format_idx, m_short_date_format_size;
- quint32 m_long_date_format_idx, m_long_date_format_size;
- quint32 m_short_time_format_idx, m_short_time_format_size;
- quint32 m_long_time_format_idx, m_long_time_format_size;
- quint32 m_standalone_short_month_names_idx, m_standalone_short_month_names_size;
- quint32 m_standalone_long_month_names_idx, m_standalone_long_month_names_size;
- quint32 m_standalone_narrow_month_names_idx, m_standalone_narrow_month_names_size;
- quint32 m_short_month_names_idx, m_short_month_names_size;
- quint32 m_long_month_names_idx, m_long_month_names_size;
- quint32 m_narrow_month_names_idx, m_narrow_month_names_size;
- quint32 m_standalone_short_day_names_idx, m_standalone_short_day_names_size;
- quint32 m_standalone_long_day_names_idx, m_standalone_long_day_names_size;
- quint32 m_standalone_narrow_day_names_idx, m_standalone_narrow_day_names_size;
- quint32 m_short_day_names_idx, m_short_day_names_size;
- quint32 m_long_day_names_idx, m_long_day_names_size;
- quint32 m_narrow_day_names_idx, m_narrow_day_names_size;
- quint32 m_am_idx, m_am_size;
- quint32 m_pm_idx, m_pm_size;
+ quint16 m_short_date_format_idx, m_short_date_format_size;
+ quint16 m_long_date_format_idx, m_long_date_format_size;
+ quint16 m_short_time_format_idx, m_short_time_format_size;
+ quint16 m_long_time_format_idx, m_long_time_format_size;
+ quint16 m_standalone_short_month_names_idx, m_standalone_short_month_names_size;
+ quint16 m_standalone_long_month_names_idx, m_standalone_long_month_names_size;
+ quint16 m_standalone_narrow_month_names_idx, m_standalone_narrow_month_names_size;
+ quint16 m_short_month_names_idx, m_short_month_names_size;
+ quint16 m_long_month_names_idx, m_long_month_names_size;
+ quint16 m_narrow_month_names_idx, m_narrow_month_names_size;
+ quint16 m_standalone_short_day_names_idx, m_standalone_short_day_names_size;
+ quint16 m_standalone_long_day_names_idx, m_standalone_long_day_names_size;
+ quint16 m_standalone_narrow_day_names_idx, m_standalone_narrow_day_names_size;
+ quint16 m_short_day_names_idx, m_short_day_names_size;
+ quint16 m_long_day_names_idx, m_long_day_names_size;
+ quint16 m_narrow_day_names_idx, m_narrow_day_names_size;
+ quint16 m_am_idx, m_am_size;
+ quint16 m_pm_idx, m_pm_size;
};
inline char QLocalePrivate::digitToCLocale(const QChar &in) const
diff --git a/src/corelib/tools/qlocale_symbian.cpp b/src/corelib/tools/qlocale_symbian.cpp
new file mode 100644
index 0000000000..2da768b07c
--- /dev/null
+++ b/src/corelib/tools/qlocale_symbian.cpp
@@ -0,0 +1,879 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QDate>
+#include <QLocale>
+#include <QTime>
+#include <QVariant>
+
+#include <e32std.h>
+#include "private/qcore_symbian_p.h"
+
+
+QT_BEGIN_NAMESPACE
+
+// Located in qlocale.cpp
+extern void getLangAndCountry(const QString &name, QLocale::Language &lang, QLocale::Country &cntry);
+
+static TExtendedLocale _s60Locale;
+
+// Type definitions for runtime resolved function pointers
+typedef void (*FormatFunc)(TTime&, TDes&, const TDesC&, const TLocale&);
+typedef TPtrC (*FormatSpecFunc)(TExtendedLocale&);
+
+// Runtime resolved functions
+static FormatFunc ptrTimeFormatL = NULL;
+static FormatSpecFunc ptrGetTimeFormatSpec = NULL;
+static FormatSpecFunc ptrGetLongDateFormatSpec = NULL;
+static FormatSpecFunc ptrGetShortDateFormatSpec = NULL;
+
+// Default functions if functions cannot be resolved
+static void defaultTimeFormatL(TTime&, TDes& des, const TDesC&, const TLocale&)
+{
+ des.Zero();
+}
+
+static TPtrC defaultFormatSpec(TExtendedLocale&)
+{
+ return TPtrC(KNullDesC);
+}
+
+/*
+ Definition of struct for mapping Symbian to ISO locale
+*/
+struct symbianToISO {
+ int symbian_language;
+ char iso_name[8];
+};
+
+
+/*
+ Mapping from Symbian to ISO locale
+*/
+static const symbianToISO symbian_to_iso_list[] = {
+ { ELangEnglish, "en_GB" },
+ { ELangFrench, "fr_FR" },
+ { ELangGerman, "de_DE" },
+ { ELangSpanish, "es_ES" },
+ { ELangItalian, "it_IT" },
+ { ELangSwedish, "sv_SE" },
+ { ELangDanish, "da_DK" },
+ { ELangNorwegian, "no_NO" },
+ { ELangFinnish, "fi_FI" },
+ { ELangAmerican, "en_US" },
+ { ELangPortuguese, "pt_PT" },
+ { ELangTurkish, "tr_TR" },
+ { ELangIcelandic, "is_IS" },
+ { ELangRussian, "ru_RU" },
+ { ELangHungarian, "hu_HU" },
+ { ELangDutch, "nl_NL" },
+ { ELangBelgianFlemish, "nl_BE" },
+ { ELangCzech, "cs_CZ" },
+ { ELangSlovak, "sk_SK" },
+ { ELangPolish, "pl_PL" },
+ { ELangSlovenian, "sl_SI" },
+ { ELangTaiwanChinese, "zh_TW" },
+ { ELangHongKongChinese, "zh_HK" },
+ { ELangPrcChinese, "zh_CN" },
+ { ELangJapanese, "ja_JP" },
+ { ELangThai, "th_TH" },
+ { ELangArabic, "ar_AE" },
+ { ELangTagalog, "tl_PH" },
+ { ELangBulgarian, "bg_BG" },
+ { ELangCatalan, "ca_ES" },
+ { ELangCroatian, "hr_HR" },
+ { ELangEstonian, "et_EE" },
+ { ELangFarsi, "fa_IR" },
+ { ELangCanadianFrench, "fr_CA" },
+ { ELangGreek, "el_GR" },
+ { ELangHebrew, "he_IL" },
+ { ELangHindi, "hi_IN" },
+ { ELangIndonesian, "id_ID" },
+ { ELangLatvian, "lv_LV" },
+ { ELangLithuanian, "lt_LT" },
+ { ELangMalay, "ms_MY" },
+ { ELangBrazilianPortuguese, "pt_BR" },
+ { ELangRomanian, "ro_RO" },
+ { ELangSerbian, "sr_YU" },
+ { ELangLatinAmericanSpanish, "es" },
+ { ELangUkrainian, "uk_UA" },
+ { ELangUrdu, "ur_PK" }, // India/Pakistan
+ { ELangVietnamese, "vi_VN" },
+#ifdef __E32LANG_H__
+// 5.0
+ { ELangBasque, "eu_ES" },
+ { ELangGalician, "gl_ES" },
+#endif
+#if !defined(__SERIES60_31__)
+ { ELangEnglish_Apac, "en" },
+ { ELangEnglish_Taiwan, "en_TW" },
+ { ELangEnglish_HongKong, "en_HK" },
+ { ELangEnglish_Prc, "en_CN" },
+ { ELangEnglish_Japan, "en_JP"},
+ { ELangEnglish_Thailand, "en_TH" },
+ { ELangMalay_Apac, "ms" }
+#endif
+};
+
+/*!
+ Returns ISO name corresponding to the Symbian locale code \a sys_fmt.
+*/
+QByteArray qt_symbianLocaleName(int code)
+{
+ //Number of Symbian to ISO locale mappings
+ static const int symbian_to_iso_count
+ = sizeof(symbian_to_iso_list)/sizeof(symbianToISO);
+
+ int cmp = code - symbian_to_iso_list[0].symbian_language;
+ if (cmp < 0)
+ return 0;
+
+ if (cmp == 0)
+ return symbian_to_iso_list[0].iso_name;
+
+ int begin = 0;
+ int end = symbian_to_iso_count;
+
+ while (end - begin > 1) {
+ uint mid = (begin + end)/2;
+
+ const symbianToISO *elt = symbian_to_iso_list + mid;
+ int cmp = code - elt->symbian_language;
+ if (cmp < 0)
+ end = mid;
+ else if (cmp > 0)
+ begin = mid;
+ else
+ return elt->iso_name;
+ }
+
+ return 0;
+}
+
+
+// order is: normal, abbr, nmode, nmode+abbr
+static const char *us_locale_dep[] = {
+ "MM", "dd", "yyyy", "MM", "dd",
+ "M", "d", "yy", "M", "d",
+ "MMMM", "dd", "yyyy", "MMMM", "dd",
+ "MMM", "d", "yy", "MMM", "d" };
+
+static const char *eu_locale_dep[] = {
+ "dd", "MM", "yyyy", "dd", "MM",
+ "d", "M", "yy", "d", "M",
+ "dd", "MMMM", "yyyy", "dd", "MMMM",
+ "d", "MMM", "yy", "d", "MMM" };
+
+static const char *jp_locale_dep[] = {
+ "yyyy", "MM", "dd", "MM", "dd",
+ "yy", "M", "d", "M", "d",
+ "yyyy", "MMMM", "dd", "MMMM", "dd",
+ "yy", "MMM", "d", "MMM", "d" };
+
+/*!
+ Returns a Qt version of the given \a sys_fmt Symbian locale format string.
+*/
+static QString s60ToQtFormat(const QString &sys_fmt)
+{
+ TLocale *locale = _s60Locale.GetLocale();
+
+ QString result;
+ QString other;
+ QString qtformatchars = QString::fromLatin1("adhmsyzAHM");
+
+ QChar c;
+ int i = 0;
+ bool open_escape = false;
+ bool abbrev_next = false;
+ bool locale_indep_ordering = false;
+ bool minus_mode = false;
+ bool plus_mode = false;
+ bool n_mode = false;
+ TTimeFormat tf = locale->TimeFormat();
+
+ while (i < sys_fmt.size()) {
+
+ c = sys_fmt.at(i);
+
+ // let formatting thru
+ if (c.unicode() == '%') {
+ // if we have gathered string, concat it
+ if (!other.isEmpty()) {
+ result += other;
+ other.clear();
+ }
+ // if we have open escape, end it
+ if (open_escape) {
+ result += QLatin1Char('\'');
+ open_escape = false;
+ }
+
+ ++i;
+ if (i >= sys_fmt.size())
+ break;
+
+ c = sys_fmt.at(i);
+
+ // process specials
+ abbrev_next = c.unicode() == '*';
+ plus_mode = c.unicode() == '+';
+ minus_mode = c.unicode() == '-';
+
+ if (abbrev_next || plus_mode || minus_mode) {
+ ++i;
+ if (i >= sys_fmt.size())
+ break;
+
+ c = sys_fmt.at(i);
+
+ if (plus_mode || minus_mode) {
+ // break on undefined plus/minus mode
+ if (c.unicode() != 'A' && c.unicode() != 'B')
+ break;
+ }
+ }
+
+ switch (c.unicode()) {
+ case 'F':
+ {
+ // locale indep mode on
+ locale_indep_ordering = true;
+ break;
+ }
+
+ case '/':
+ {
+ // date sep 0-3
+ ++i;
+ if (i >= sys_fmt.size())
+ break;
+
+ c = sys_fmt.at(i);
+ if (c.isDigit() && c.digitValue() <= 3) {
+ TChar s = locale->DateSeparator(c.digitValue());
+ TUint val = s;
+ // some indexes return zero for empty
+ if (val > 0)
+ result += QChar(val);
+ }
+ break;
+ }
+
+ case 'D':
+ {
+ if (!locale_indep_ordering)
+ break;
+
+ if (!abbrev_next)
+ result += QLatin1String("dd");
+ else
+ result += QLatin1Char('d');
+
+ break;
+ }
+
+ case 'M':
+ {
+ if (!locale_indep_ordering)
+ break;
+
+ if (!n_mode) {
+ if (!abbrev_next)
+ result += QLatin1String("MM");
+ else
+ result += QLatin1String("M");
+ } else {
+ if (!abbrev_next)
+ result += QLatin1String("MMMM");
+ else
+ result += QLatin1String("MMM");
+ }
+
+ break;
+ }
+
+ case 'N':
+ {
+ n_mode = true;
+
+ if (!locale_indep_ordering)
+ break;
+
+ if (!abbrev_next)
+ result += QLatin1String("MMMM");
+ else
+ result += QLatin1String("MMM");
+
+ break;
+ }
+
+ case 'Y':
+ {
+ if (!locale_indep_ordering)
+ break;
+
+ if (!abbrev_next)
+ result += QLatin1String("yyyy");
+ else
+ result += QLatin1String("yy");
+
+ break;
+ }
+
+ case 'E':
+ {
+ if (!abbrev_next)
+ result += QLatin1String("dddd");
+ else
+ result += QLatin1String("ddd");
+
+ break;
+ }
+
+ case ':':
+ {
+ // timesep 0-3
+ ++i;
+ if (i >= sys_fmt.size())
+ break;
+
+ c = sys_fmt.at(i);
+ if (c.isDigit() && c.digitValue() <= 3) {
+ TChar s = locale->TimeSeparator(c.digitValue());
+ TUint val = s;
+ // some indexes return zero for empty
+ if (val > 0)
+ result += QChar(val);
+ }
+
+ break;
+ }
+
+ case 'J':
+ {
+ if (tf == ETime24 && !abbrev_next)
+ result += QLatin1String("hh");
+ else
+ result += QLatin1Char('h');
+
+ break;
+ }
+
+ case 'H':
+ {
+ if (!abbrev_next)
+ result += QLatin1String("hh");
+ else
+ result += QLatin1Char('h');
+
+ break;
+ }
+
+ case 'I':
+ {
+ result += QLatin1Char('h');
+ break;
+ }
+
+ case 'T':
+ {
+ if (!abbrev_next)
+ result += QLatin1String("mm");
+ else
+ result += QLatin1Char('m');
+
+ break;
+ }
+
+ case 'S':
+ {
+ if (!abbrev_next)
+ result += QLatin1String("ss");
+ else
+ result += QLatin1Char('s');
+
+ break;
+ }
+
+ case 'B':
+ {
+ // only done for 12h clock
+ if (tf == ETime24)
+ break;
+ }
+
+ // fallthru to A
+ case 'A': {
+ // quickie to get capitalization, can't use s60 string as is because Qt 'hh' format's am/pm logic
+ TAmPmName ampm = TAmPmName();
+ TChar first(ampm[0]);
+ QString qtampm = QString::fromLatin1(first.IsUpper() ? "AP" : "ap");
+
+ int pos = locale->AmPmSymbolPosition();
+
+ if ((minus_mode && pos != ELocaleBefore) ||
+ (plus_mode && pos != ELocaleAfter))
+ break;
+
+ if (!abbrev_next && locale->AmPmSpaceBetween()) {
+ if (pos == ELocaleBefore)
+ qtampm.append(QLatin1Char(' '));
+ else
+ qtampm.prepend(QLatin1Char(' '));
+ }
+
+ result += qtampm;
+ }
+ break;
+
+ case '.': {
+ // decimal sep
+ TChar s = locale->DecimalSeparator();
+ TUint val = s;
+ if (val > 0)
+ result += QChar(val);
+ }
+ break;
+
+ case 'C':
+ {
+ // six digits in s60, three digits in qt
+ if (!abbrev_next) {
+ result += QLatin1String("zzz");
+ } else {
+ // next char is number from 0-6, how many digits to display
+ ++i;
+ if (i >= sys_fmt.size())
+ break;
+
+ c = sys_fmt.at(i);
+
+ if (c.isDigit()) {
+ // try to match wanted digits
+ QChar val(c.digitValue());
+
+ if (val >= 3) {
+ result += QLatin1String("zzz");
+ } else if (val > 0) {
+ result += QLatin1Char('z');
+ }
+ }
+ }
+ break;
+ }
+
+ // these cases fallthru
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ {
+
+ // shouldn't parse these with %F
+ if (locale_indep_ordering)
+ break;
+
+ TDateFormat df = locale->DateFormat();
+
+ const char **locale_dep;
+ switch (df) {
+ default: // fallthru to american
+ case EDateAmerican:
+ locale_dep = us_locale_dep;
+ break;
+ case EDateEuropean:
+ locale_dep = eu_locale_dep;
+ break;
+ case EDateJapanese:
+ locale_dep = jp_locale_dep;
+ break;
+ }
+ int offset = 0;
+ if (abbrev_next)
+ offset += 5;
+ if (n_mode)
+ offset += 10;
+
+ result += QLatin1String(locale_dep[offset + (c.digitValue()-1)]);
+ break;
+ }
+
+ case '%': // fallthru percent
+ {
+ // any junk gets copied as is
+ }
+ default:
+ {
+ result += c;
+ break;
+ }
+
+ case 'Z': // Qt doesn't support these :(
+ case 'X':
+ case 'W':
+ {
+ break;
+ }
+ }
+ } else {
+ // double any single quotes, don't begin escape
+ if (c.unicode() == '\'') {
+ // end open escape
+ if (open_escape) {
+ result += other;
+ other.clear();
+ result += QLatin1Char('\'');
+ open_escape = false;
+ }
+
+ other += c;
+ }
+
+ // gather chars and escape them in one go if any format chars are found
+ if (!open_escape && qtformatchars.indexOf(c) != -1) {
+ result += QLatin1Char('\'');
+ open_escape = true;
+ }
+ other += c;
+ }
+
+ ++i;
+ }
+
+ if (!other.isEmpty())
+ result += other;
+ if (open_escape)
+ result += QLatin1Char('\'');
+
+ return result;
+}
+
+/*!
+ Retrieves Symbian locale decimal separator.
+*/
+static QString symbianDecimalPoint()
+{
+ TLocale *locale = _s60Locale.GetLocale();
+
+ TChar decPoint = locale->DecimalSeparator();
+ int val = decPoint;
+ return QChar(val);
+}
+
+/*!
+ Retrieves Symbian locale group separator.
+*/
+static QString symbianGroupSeparator()
+{
+ TLocale *locale = _s60Locale.GetLocale();
+
+ TChar grpSep = locale->ThousandsSeparator();
+ int val = grpSep;
+ return QChar(val);
+}
+
+/*!
+ Retrieves Symbian locale zero digit.
+*/
+static QString symbianZeroDigit()
+{
+ TLocale *locale = _s60Locale.GetLocale();
+
+ // TDigitType enumeration value returned by TLocale
+ // will always correspond to zero digit unicode value.
+ TDigitType digit = locale->DigitType();
+ return QChar(digit);
+}
+
+/*!
+ Retrieves a day name from Symbian locale. The \a day is an integer
+ from 1 to 7. When \a short_format is true the method returns
+ the day in short format. Otherwise it returns the day in a long format.
+*/
+static QString symbianDayName(int day, bool short_format)
+{
+ day -= 1;
+
+ if (day < 0 || day > 6)
+ return QString();
+
+ if (short_format) {
+ return qt_TDes2QString(TDayNameAbb(TDay(day)));
+ } else {
+ return qt_TDes2QString(TDayName(TDay(day)));
+ }
+}
+
+/*!
+ Retrieves a month name from Symbian locale. The \a month is an integer
+ from 1 to 12. When \a short_format is true the method returns
+ the month in short format. Otherwise it returns the month in a long format.
+*/
+static QString symbianMonthName(int month, bool short_format)
+{
+ month -= 1;
+ if (month < 0 || month > 11)
+ return QString();
+
+ if (short_format) {
+ return qt_TDes2QString(TMonthNameAbb(TMonth(month)));
+ } else {
+ return qt_TDes2QString(TMonthName(TMonth(month)));
+ }
+}
+
+/*!
+ Retrieves date format from Symbian locale and
+ transforms it to Qt format.
+
+ When \a short_format is true the method returns
+ short date format. Otherwise it returns the long format.
+*/
+static QString symbianDateFormat(bool short_format)
+{
+ TPtrC dateFormat;
+
+ if (short_format) {
+ dateFormat.Set(ptrGetShortDateFormatSpec(_s60Locale));
+ } else {
+ dateFormat.Set(ptrGetLongDateFormatSpec(_s60Locale));
+ }
+
+ return s60ToQtFormat(qt_TDesC2QString(dateFormat));
+}
+
+/*!
+ Retrieves time format from Symbian locale and
+ transforms it to Qt format.
+*/
+static QString symbianTimeFormat()
+{
+ return s60ToQtFormat(qt_TDesC2QString(ptrGetTimeFormatSpec(_s60Locale)));
+}
+
+/*!
+ Returns localized string representation of given \a date
+ formatted with Symbian locale date format.
+
+ If \a short_format is true the format will be a short version.
+ Otherwise it uses a longer version.
+*/
+static QString symbianDateToString(const QDate &date, bool short_format)
+{
+ int month = date.month() - 1;
+ int day = date.day() - 1;
+ int year = date.year();
+
+ TDateTime dateTime;
+ dateTime.Set(year, TMonth(month), day, 0, 0, 0, 0);
+
+ TTime timeStr(dateTime);
+ TBuf<KMaxLongDateFormatSpec*2> buffer;
+
+ TPtrC dateFormat;
+ if (short_format) {
+ dateFormat.Set(ptrGetShortDateFormatSpec(_s60Locale));
+ } else {
+ dateFormat.Set(ptrGetLongDateFormatSpec(_s60Locale));
+ }
+
+ TRAPD(err, ptrTimeFormatL(timeStr, buffer, dateFormat, *_s60Locale.GetLocale());)
+
+ if (err == KErrNone)
+ return qt_TDes2QString(buffer);
+ else
+ return QString();
+}
+
+/*!
+ Returns localized string representation of given \a time
+ formatted with Symbian locale time format.
+*/
+static QString symbianTimeToString(const QTime &time)
+{
+ int hour = time.hour();
+ int minute = time.minute();
+ int second = time.second();
+ int milliseconds = 0;
+
+ TDateTime dateTime;
+ dateTime.Set(0, TMonth(0), 0, hour, minute, second, milliseconds);
+
+ TTime timeStr(dateTime);
+ TBuf<KMaxTimeFormatSpec*2> buffer;
+
+ TRAPD(err, ptrTimeFormatL(
+ timeStr,
+ buffer,
+ ptrGetTimeFormatSpec(_s60Locale),
+ *_s60Locale.GetLocale());
+ )
+
+ if (err == KErrNone)
+ return qt_TDes2QString(buffer);
+ else
+ return QString();
+}
+
+/*!
+ Returns the measurement system stored in Symbian locale
+
+ \sa QLocale::MeasurementSystem
+*/
+static QLocale::MeasurementSystem symbianMeasurementSystem()
+{
+ TLocale *locale = _s60Locale.GetLocale();
+
+ TUnitsFormat unitFormat = locale->UnitsGeneral();
+ if (unitFormat == EUnitsImperial)
+ return QLocale::ImperialSystem;
+ else
+ return QLocale::MetricSystem;
+}
+
+QLocale QSystemLocale::fallbackLocale() const
+{
+ // load system data before query calls
+ static bool initDone = false;
+ if (!initDone) {
+ _s60Locale.LoadSystemSettings();
+
+ // Initialize platform version dependent function pointers
+ ptrTimeFormatL = reinterpret_cast<FormatFunc>
+ (qt_resolveS60PluginFunc(S60Plugin_TimeFormatL));
+ ptrGetTimeFormatSpec = reinterpret_cast<FormatSpecFunc>
+ (qt_resolveS60PluginFunc(S60Plugin_GetTimeFormatSpec));
+ ptrGetLongDateFormatSpec = reinterpret_cast<FormatSpecFunc>
+ (qt_resolveS60PluginFunc(S60Plugin_GetLongDateFormatSpec));
+ ptrGetShortDateFormatSpec = reinterpret_cast<FormatSpecFunc>
+ (qt_resolveS60PluginFunc(S60Plugin_GetShortDateFormatSpec));
+ if (!ptrTimeFormatL)
+ ptrTimeFormatL = &defaultTimeFormatL;
+ if (!ptrGetTimeFormatSpec)
+ ptrGetTimeFormatSpec = &defaultFormatSpec;
+ if (!ptrGetLongDateFormatSpec)
+ ptrGetLongDateFormatSpec = &defaultFormatSpec;
+ if (!ptrGetShortDateFormatSpec)
+ ptrGetShortDateFormatSpec = &defaultFormatSpec;
+ }
+
+ TLanguage lang = User::Language();
+ QString locale = qt_symbianLocaleName(lang);
+ return QLocale(locale);
+}
+
+/*!
+ Generic query method for locale data. Provides indirection.
+ Denotes the \a type of the query
+ with \a in as input data depending on the query.
+
+ \sa QSystemLocale::QueryType
+*/
+QVariant QSystemLocale::query(QueryType type, QVariant in = QVariant()) const
+{
+ switch(type) {
+ case DecimalPoint:
+ return symbianDecimalPoint();
+ case GroupSeparator:
+ return symbianGroupSeparator();
+
+ case ZeroDigit:
+ return symbianZeroDigit();
+
+ case DayNameLong:
+ case DayNameShort:
+ return symbianDayName(in.toInt(), (type == DayNameShort) );
+
+ case MonthNameLong:
+ case MonthNameShort:
+ return symbianMonthName(in.toInt(), (type == MonthNameShort) );
+
+ case DateFormatLong:
+ case DateFormatShort:
+ return symbianDateFormat( (type == DateFormatShort) );
+ case TimeFormatLong:
+ case TimeFormatShort:
+ return symbianTimeFormat();
+ case DateTimeFormatLong:
+ case DateTimeFormatShort:
+ return symbianDateFormat( (type == DateTimeFormatShort) ) + QLatin1Char(' ') + symbianTimeFormat();
+ case DateToStringShort:
+ case DateToStringLong:
+ return symbianDateToString(in.toDate(), (type == DateToStringShort) );
+ case TimeToStringShort:
+ case TimeToStringLong:
+ return symbianTimeToString(in.toTime());
+ case DateTimeToStringShort:
+ case DateTimeToStringLong: {
+ const QDateTime dt = in.toDateTime();
+ return symbianDateToString(dt.date(), (type == DateTimeToStringShort) )
+ + QLatin1Char(' ') + symbianTimeToString(dt.time());
+ }
+ case MeasurementSystem:
+ return static_cast<int>(symbianMeasurementSystem());
+ case LanguageId:
+ case CountryId: {
+ TLanguage language = User::Language();
+ QString locale = qt_symbianLocaleName(language);
+ QLocale::Language lang;
+ QLocale::Country cntry;
+ getLangAndCountry(locale, lang, cntry);
+ if (type == LanguageId)
+ return lang;
+ // few iso codes have no country and will use this
+ if (cntry == QLocale::AnyCountry)
+ return fallbackLocale().country();
+
+ return cntry;
+ }
+ case NegativeSign:
+ case PositiveSign:
+ case AMText:
+ case PMText:
+ break;
+ default:
+ break;
+ }
+ return QVariant();
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qmap.cpp b/src/corelib/tools/qmap.cpp
index 34e093cfbb..abd9b00fb2 100644
--- a/src/corelib/tools/qmap.cpp
+++ b/src/corelib/tools/qmap.cpp
@@ -59,6 +59,7 @@ QMapData QMapData::shared_null = {
QMapData *QMapData::createData()
{
QMapData *d = new QMapData;
+ Q_CHECK_PTR(d);
Node *e = reinterpret_cast<Node *>(d);
e->backward = e;
e->forward[0] = e;
@@ -84,6 +85,18 @@ void QMapData::continueFreeData(int offset)
delete this;
}
+/*!
+ Creates a new node inside the data structure.
+
+ \a update is an array with pointers to the node after which the new node
+ should be inserted. Because of the strange skip list data structure there
+ could be several pointers to this node on different levels.
+ \a offset is an amount of bytes that needs to reserved just before the
+ QMapData::Node structure.
+
+ \internal
+ \since 4.6
+*/
QMapData::Node *QMapData::node_create(Node *update[], int offset)
{
int level = 0;
@@ -94,10 +107,6 @@ QMapData::Node *QMapData::node_create(Node *update[], int offset)
mask <<= Sparseness;
}
- ++randomBits;
- if (level == 3 && !insertInOrder)
- randomBits = qrand();
-
if (level > topLevel) {
Node *e = reinterpret_cast<Node *>(this);
level = ++topLevel;
@@ -105,7 +114,13 @@ QMapData::Node *QMapData::node_create(Node *update[], int offset)
update[level] = e;
}
+ ++randomBits;
+ if (level == 3 && !insertInOrder)
+ randomBits = qrand();
+
void *concreteNode = qMalloc(offset + sizeof(Node) + level * sizeof(Node *));
+ Q_CHECK_PTR(concreteNode);
+
Node *abstractNode = reinterpret_cast<Node *>(reinterpret_cast<char *>(concreteNode) + offset);
abstractNode->backward = update[0];
@@ -146,7 +161,7 @@ uint QMapData::adjust_ptr(Node *node)
void QMapData::dump()
{
- qDebug("Map data (ref = %d, size = %d, randomBits = %#.8x)", ref.atomic, size, randomBits);
+ qDebug("Map data (ref = %d, size = %d, randomBits = %#.8x)", int(ref), size, randomBits);
QString preOutput;
QVector<QString> output(topLevel + 1);
@@ -158,12 +173,12 @@ void QMapData::dump()
Node *update[LastLevel + 1];
for (int i = 0; i <= topLevel; ++i) {
- str.sprintf("%d: [%.8x] -", i, adjust_ptr(forward[i]));
+ str.sprintf("%d: [%.8x] -", i, adjust_ptr(reinterpret_cast<Node *>(forward[i])));
output[i] += str;
- update[i] = forward[i];
+ update[i] = reinterpret_cast<Node *>(forward[i]);
}
- Node *node = forward[0];
+ Node *node = reinterpret_cast<Node *>(forward[0]);
while (node != e) {
int level = 0;
while (level < topLevel && update[level + 1] == node)
@@ -178,13 +193,13 @@ void QMapData::dump()
update[i] = node->forward[i];
}
for (int j = level + 1; j <= topLevel; ++j)
- output[j] += "---------------";
+ output[j] += QLatin1String("---------------");
node = node->forward[0];
}
- qDebug(preOutput.ascii());
+ qDebug("%s", preOutput.ascii());
for (int i = 0; i <= topLevel; ++i)
- qDebug(output[i].ascii());
+ qDebug("%s", output[i].ascii());
}
#endif
@@ -194,7 +209,7 @@ void QMapData::dump()
\ingroup tools
\ingroup shared
- \mainclass
+
\reentrant
QMap\<Key, T\> is one of Qt's generic \l{container classes}. It
@@ -1317,7 +1332,7 @@ void QMapData::dump()
\ingroup tools
\ingroup shared
- \mainclass
+
\reentrant
QMultiMap\<Key, T\> is one of Qt's generic \l{container classes}.
diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h
index b55a046bbd..0c197f6605 100644
--- a/src/corelib/tools/qmap.h
+++ b/src/corelib/tools/qmap.h
@@ -416,9 +416,29 @@ Q_INLINE_TEMPLATE typename QMapData::Node *
QMap<Key, T>::node_create(QMapData *adt, QMapData::Node *aupdate[], const Key &akey, const T &avalue)
{
QMapData::Node *abstractNode = adt->node_create(aupdate, payload());
- Node *concreteNode = concrete(abstractNode);
- new (&concreteNode->key) Key(akey);
- new (&concreteNode->value) T(avalue);
+ QT_TRY {
+ Node *concreteNode = concrete(abstractNode);
+ new (&concreteNode->key) Key(akey);
+ QT_TRY {
+ new (&concreteNode->value) T(avalue);
+ } QT_CATCH(...) {
+ concreteNode->key.~Key();
+ QT_RETHROW;
+ }
+ } QT_CATCH(...) {
+ adt->node_delete(aupdate, payload(), abstractNode);
+ QT_RETHROW;
+ }
+
+ // clean up the update array for further insertions
+ /*
+ for (int i = 0; i <= d->topLevel; ++i) {
+ if ( aupdate[i]==reinterpret_cast<QMapData::Node *>(adt) || aupdate[i]->forward[i] != abstractNode)
+ break;
+ aupdate[i] = abstractNode;
+ }
+*/
+
return abstractNode;
}
@@ -704,8 +724,13 @@ Q_OUTOFLINE_TEMPLATE void QMap<Key, T>::detach_helper()
QMapData::Node *cur = e->forward[0];
update[0] = x.e;
while (cur != e) {
- Node *concreteNode = concrete(cur);
- node_create(x.d, update, concreteNode->key, concreteNode->value);
+ QT_TRY {
+ Node *concreteNode = concrete(cur);
+ node_create(x.d, update, concreteNode->key, concreteNode->value);
+ } QT_CATCH(...) {
+ freeData(x.d);
+ QT_RETHROW;
+ }
cur = cur->forward[0];
}
x.d->insertInOrder = false;
@@ -923,7 +948,8 @@ public:
inline QMultiMap operator+(const QMultiMap &other) const
{ QMultiMap result = *this; result += other; return result; }
-#ifndef Q_NO_USING_KEYWORD
+#if !defined(Q_NO_USING_KEYWORD) && !defined(Q_CC_RVCT)
+ // RVCT compiler doesn't handle using-keyword right when used functions are overloaded in child class
using QMap<Key, T>::contains;
using QMap<Key, T>::remove;
using QMap<Key, T>::count;
@@ -990,10 +1016,15 @@ Q_INLINE_TEMPLATE int QMultiMap<Key, T>::remove(const Key &key, const T &value)
{
int n = 0;
typename QMap<Key, T>::iterator i(find(key));
- typename QMap<Key, T>::const_iterator end(QMap<Key, T>::constEnd());
+ typename QMap<Key, T>::iterator end(QMap<Key, T>::end());
while (i != end && !qMapLessThanKey<Key>(key, i.key())) {
if (i.value() == value) {
+#if defined(Q_CC_RVCT)
+ // RVCT has problems with scoping, apparently.
+ i = QMap<Key, T>::erase(i);
+#else
i = erase(i);
+#endif
++n;
} else {
++i;
diff --git a/src/corelib/tools/qpair.qdoc b/src/corelib/tools/qpair.qdoc
new file mode 100644
index 0000000000..2bb075402f
--- /dev/null
+++ b/src/corelib/tools/qpair.qdoc
@@ -0,0 +1,229 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QPair
+ \brief The QPair class is a template class that stores a pair of items.
+
+ \ingroup tools
+
+ QPair\<T1, T2\> can be used in your application if the STL \c
+ pair type is not available. It stores one value of type T1 and
+ one value of type T2. It can be used as a return value for a
+ function that needs to return two values, or as the value type of
+ a \l{generic container}.
+
+ Here's an example of a QPair that stores one QString and one \c
+ double value:
+
+ \snippet doc/src/snippets/code/doc_src_qpair.qdoc 0
+
+ The components are accessible as public data members called \l
+ first and \l second. For example:
+
+ \snippet doc/src/snippets/code/doc_src_qpair.qdoc 1
+
+ QPair's template data types (T1 and T2) must be \l{assignable
+ data types}. You cannot, for example, store a QWidget as a value;
+ instead, store a QWidget *. A few functions have additional
+ requirements; these requirements are documented on a per-function
+ basis.
+
+ \sa {Generic Containers}
+*/
+
+/*! \typedef QPair::first_type
+
+ The type of the first element in the pair (T1).
+
+ \sa first
+*/
+
+/*! \typedef QPair::second_type
+
+ The type of the second element in the pair (T2).
+
+ \sa second
+*/
+
+/*! \variable QPair::first
+
+ The first element in the pair.
+*/
+
+/*! \variable QPair::second
+
+ The second element in the pair.
+*/
+
+/*! \fn QPair::QPair()
+
+ Constructs an empty pair. The \c first and \c second elements are
+ initialized with \l{default-constructed values}.
+*/
+
+/*!
+ \fn QPair::QPair(const T1 &value1, const T2 &value2)
+
+ Constructs a pair and initializes the \c first element with \a
+ value1 and the \c second element with \a value2.
+
+ \sa qMakePair()
+*/
+
+/*!
+ \fn QPair<T1, T2> &QPair::operator=(const QPair<T1, T2> &other)
+
+ Assigns \a other to this pair.
+*/
+
+/*! \fn bool operator==(const QPair<T1, T2> &p1, const QPair<T1, T2> &p2)
+
+ \relates QPair
+
+ Returns true if \a p1 is equal to \a p2; otherwise returns false.
+ Two pairs compare equal if their \c first data members compare
+ equal and if their \c second data members compare equal.
+
+ This function requires the T1 and T2 types to have an
+ implementation of \c operator==().
+*/
+
+/*! \fn bool operator!=(const QPair<T1, T2> &p1, const QPair<T1, T2> &p2)
+
+ \relates QPair
+
+ Returns true if \a p1 is not equal to \a p2; otherwise returns
+ false. Two pairs compare as not equal if their \c first data
+ members are not equal or if their \c second data members are not
+ equal.
+
+ This function requires the T1 and T2 types to have an
+ implementation of \c operator==().
+*/
+
+/*! \fn bool operator<(const QPair<T1, T2> &p1, const QPair<T1, T2> &p2)
+
+ \relates QPair
+
+ Returns true if \a p1 is less than \a p2; otherwise returns
+ false. The comparison is done on the \c first members of \a p1
+ and \a p2; if they compare equal, the \c second members are
+ compared to break the tie.
+
+ This function requires the T1 and T2 types to have an
+ implementation of \c operator<().
+*/
+
+/*! \fn bool operator>(const QPair<T1, T2> &p1, const QPair<T1, T2> &p2)
+
+ \relates QPair
+
+ Returns true if \a p1 is greater than \a p2; otherwise returns
+ false. The comparison is done on the \c first members of \a p1
+ and \a p2; if they compare equal, the \c second members are
+ compared to break the tie.
+
+ This function requires the T1 and T2 types to have an
+ implementation of \c operator<().
+*/
+
+/*! \fn bool operator<=(const QPair<T1, T2> &p1, const QPair<T1, T2> &p2)
+
+ \relates QPair
+
+ Returns true if \a p1 is less than or equal to \a p2; otherwise
+ returns false. The comparison is done on the \c first members of
+ \a p1 and \a p2; if they compare equal, the \c second members are
+ compared to break the tie.
+
+ This function requires the T1 and T2 types to have an
+ implementation of \c operator<().
+*/
+
+/*! \fn bool operator>=(const QPair<T1, T2> &p1, const QPair<T1, T2> &p2)
+
+ \relates QPair
+
+ Returns true if \a p1 is greater than or equal to \a p2;
+ otherwise returns false. The comparison is done on the \c first
+ members of \a p1 and \a p2; if they compare equal, the \c second
+ members are compared to break the tie.
+
+ This function requires the T1 and T2 types to have an
+ implementation of \c operator<().
+*/
+
+/*!
+ \fn QPair<T1, T2> qMakePair(const T1 &value1, const T2 &value2)
+
+ \relates QPair
+
+ Returns a QPair\<T1, T2\> that contains \a value1 and \a value2.
+ Example:
+
+ \snippet doc/src/snippets/code/doc_src_qpair.qdoc 2
+
+ This is equivalent to QPair<T1, T2>(\a value1, \a value2), but
+ usually requires less typing.
+*/
+
+/*! \fn QDataStream &operator>>(QDataStream &in, QPair<T1, T2> &pair)
+
+ \relates QPair
+
+ Reads a pair from stream \a in into \a pair.
+
+ This function requires the T1 and T2 types to implement \c operator>>().
+
+ \sa {Format of the QDataStream operators}
+*/
+
+/*! \fn QDataStream &operator<<(QDataStream &out, const QPair<T1, T2> &pair)
+
+ \relates QPair
+
+ Writes the pair \a pair to stream \a out.
+
+ This function requires the T1 and T2 types to implement \c operator<<().
+
+ \sa {Format of the QDataStream operators}
+*/
diff --git a/src/corelib/tools/qpodlist_p.h b/src/corelib/tools/qpodlist_p.h
index ddd3d9e8e4..d907f41392 100644
--- a/src/corelib/tools/qpodlist_p.h
+++ b/src/corelib/tools/qpodlist_p.h
@@ -53,9 +53,7 @@
// We mean it.
//
-#include <QtCore/qcontainerfwd.h>
-#include <QtCore/qglobal.h>
-#include <new>
+#include <QtCore/qvarlengtharray.h>
QT_BEGIN_HEADER
@@ -63,87 +61,29 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Core)
-template<class T, int Prealloc>
-class QPodList
+template <typename T, int Prealloc>
+class QPodList : public QVarLengthArray<T, Prealloc>
{
+ using QVarLengthArray<T, Prealloc>::s;
+ using QVarLengthArray<T, Prealloc>::a;
+ using QVarLengthArray<T, Prealloc>::ptr;
+ using QVarLengthArray<T, Prealloc>::realloc;
public:
- inline explicit QPodList(int size = 0);
+ inline explicit QPodList(int size = 0)
+ : QVarLengthArray<T, Prealloc>(size)
+ {}
- inline QPodList(const QPodList<T, Prealloc> &other)
- : a(Prealloc), s(0), ptr(reinterpret_cast<T *>(array))
+ inline void insert(int idx, const T &t)
{
- append(other.constData(), other.size());
- }
-
- inline ~QPodList() {
- if (ptr != reinterpret_cast<T *>(array))
- qFree(ptr);
- }
- inline QPodList<T, Prealloc> &operator=(const QPodList<T, Prealloc> &other)
- {
- if (this != &other) {
- clear();
- append(other.constData(), other.size());
- }
- return *this;
- }
-
- inline int size() const { return s; }
- inline int count() const { return s; }
- inline bool isEmpty() const { return (s == 0); }
- inline void resize(int size);
- inline void clear() { resize(0); }
-
- inline int capacity() const { return a; }
- inline void reserve(int size);
-
- inline T &operator[](int idx) {
- Q_ASSERT(idx >= 0 && idx < s);
- return ptr[idx];
- }
- inline const T &operator[](int idx) const {
- Q_ASSERT(idx >= 0 && idx < s);
- return ptr[idx];
- }
-
- inline const T &at(int idx) const {
- Q_ASSERT(idx >= 0 && idx < s);
- return ptr[idx];
- }
-
- inline const T &first() const {
- return at(0);
- }
-
- inline T& append() {
- const int idx = s++;
- if (s == a)
- realloc(s, s<<1);
- return ptr[idx];
- }
- inline void append(const T &t) {
- append() = t;
- }
-
- inline T& insert(int idx) {
- Q_ASSERT(idx >= 0 && idx <= s);
const int sz = s++;
if (s == a)
- realloc(s, s<<1);
+ realloc(s, s << 1);
::memmove(ptr + idx + 1, ptr + idx, (sz - idx) * sizeof(T));
- return ptr[idx];
- }
- inline void insert(int idx, const T &t) {
- insert(idx) = t;
+ ptr[idx] = t;
}
- inline void removeAt(int idx) {
- Q_ASSERT(idx >= 0 && idx < s);
- ::memmove(ptr + idx, ptr + idx + 1, (s - idx - 1) * sizeof(T));
- --s;
- }
-
- inline void removeAll(const T &t) {
+ inline void removeAll(const T &t)
+ {
int i = 0;
for (int j = 0; j < s; ++j) {
if (ptr[j] != t)
@@ -152,110 +92,22 @@ public:
s = i;
}
- inline int indexOf(const T &t, int from = 0) const {
- if (from < 0)
- from = qMax(from + s, 0);
- if (from < s) {
- const T *n = ptr + from - 1;
- const T *e = ptr + s;
- while (++n != e)
- if (*n == t)
- return n - ptr;
- }
- return -1;
- }
-
- inline bool contains(const T &t) const {
- return indexOf(t) >= 0;
+ inline void removeAt(int idx)
+ {
+ Q_ASSERT(idx >= 0 && idx < s);
+ ::memmove(ptr + idx, ptr + idx + 1, (s - idx - 1) * sizeof(T));
+ --s;
}
- inline T takeFirst() {
+ inline T takeFirst()
+ {
Q_ASSERT(s > 0);
T tmp = ptr[0];
removeAt(0);
return tmp;
}
-
- inline T *data() { return ptr; }
- inline const T *data() const { return ptr; }
- inline const T * constData() const { return ptr; }
-
-private:
- void append(const T *buf, int size);
- void realloc(int size, int alloc);
-
- int a;
- int s;
- T *ptr;
- union {
- // ### Qt 5: Use 'Prealloc * sizeof(T)' as array size
- char array[sizeof(qint64) * (((Prealloc * sizeof(T)) / sizeof(qint64)) + 1)];
- qint64 q_for_alignment_1;
- double q_for_alignment_2;
- };
};
-template <class T, int Prealloc>
-Q_INLINE_TEMPLATE QPodList<T, Prealloc>::QPodList(int asize)
- : s(asize) {
- if (s > Prealloc) {
- ptr = reinterpret_cast<T *>(qMalloc(s * sizeof(T)));
- a = s;
- } else {
- ptr = reinterpret_cast<T *>(array);
- a = Prealloc;
- }
-}
-
-template <class T, int Prealloc>
-Q_INLINE_TEMPLATE void QPodList<T, Prealloc>::resize(int asize)
-{ realloc(asize, qMax(asize, a)); }
-
-template <class T, int Prealloc>
-Q_INLINE_TEMPLATE void QPodList<T, Prealloc>::reserve(int asize)
-{ if (asize > a) realloc(s, asize); }
-
-template <class T, int Prealloc>
-Q_OUTOFLINE_TEMPLATE void QPodList<T, Prealloc>::append(const T *abuf, int asize)
-{
- Q_ASSERT(abuf);
- if (asize <= 0)
- return;
-
- const int idx = s;
- const int news = s + asize;
- if (news >= a)
- realloc(news, news<<1);
- else
- s = news;
-
- qMemCopy(&ptr[idx], abuf, asize * sizeof(T));
-}
-
-template <class T, int Prealloc>
-Q_OUTOFLINE_TEMPLATE void QPodList<T, Prealloc>::realloc(int asize, int aalloc)
-{
- Q_ASSERT(aalloc >= asize);
- T *oldPtr = ptr;
- int osize = s;
- s = asize;
-
- if (aalloc != a) {
- ptr = reinterpret_cast<T *>(qMalloc(aalloc * sizeof(T)));
- if (ptr) {
- a = aalloc;
- qMemCopy(ptr, oldPtr, osize * sizeof(T));
- } else {
- ptr = oldPtr;
- s = 0;
- asize = 0;
- }
- }
-
- if (oldPtr != reinterpret_cast<T *>(array) && oldPtr != ptr)
- qFree(oldPtr);
-}
-
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/corelib/tools/qpoint.cpp b/src/corelib/tools/qpoint.cpp
index cd94aec55f..f3af5f3e89 100644
--- a/src/corelib/tools/qpoint.cpp
+++ b/src/corelib/tools/qpoint.cpp
@@ -47,7 +47,7 @@ QT_BEGIN_NAMESPACE
/*!
\class QPoint
- \ingroup multimedia
+ \ingroup painting
\brief The QPoint class defines a point in the plane using integer
precision.
@@ -373,14 +373,14 @@ QDebug operator<<(QDebug dbg, const QPoint &p) {
QDebug operator<<(QDebug d, const QPointF &p)
{
- d.nospace() << "QPointF(" << p.x() << ", " << p.y() << ")";
+ d.nospace() << "QPointF(" << p.x() << ", " << p.y() << ')';
return d;
}
#endif
/*!
\class QPointF
- \ingroup multimedia
+ \ingroup painting
\brief The QPointF class defines a point in the plane using
floating point precision.
@@ -442,6 +442,21 @@ QDebug operator<<(QDebug d, const QPointF &p)
otherwise returns false.
*/
+
+/*!
+ \since 4.6
+
+ Returns the sum of the absolute values of x() and y(),
+ traditionally known as the "Manhattan length" of the vector from
+ the origin to the point.
+
+ \sa QPoint::manhattanLength()
+*/
+qreal QPointF::manhattanLength() const
+{
+ return qAbs(x())+qAbs(y());
+}
+
/*!
\fn qreal QPointF::x() const
diff --git a/src/corelib/tools/qpoint.h b/src/corelib/tools/qpoint.h
index 9bee5abb13..3e71055b06 100644
--- a/src/corelib/tools/qpoint.h
+++ b/src/corelib/tools/qpoint.h
@@ -192,6 +192,8 @@ public:
QPointF(const QPoint &p);
QPointF(qreal xpos, qreal ypos);
+ qreal manhattanLength() const;
+
bool isNull() const;
qreal x() const;
@@ -300,12 +302,12 @@ inline QPointF &QPointF::operator*=(qreal c)
inline bool operator==(const QPointF &p1, const QPointF &p2)
{
- return qFuzzyCompare(p1.xp, p2.xp) && qFuzzyCompare(p1.yp, p2.yp);
+ return qFuzzyIsNull(p1.xp - p2.xp) && qFuzzyIsNull(p1.yp - p2.yp);
}
inline bool operator!=(const QPointF &p1, const QPointF &p2)
{
- return !qFuzzyCompare(p1.xp, p2.xp) || !qFuzzyCompare(p1.yp, p2.yp);
+ return !qFuzzyIsNull(p1.xp - p2.xp) || !qFuzzyIsNull(p1.yp - p2.yp);
}
inline const QPointF operator+(const QPointF &p1, const QPointF &p2)
diff --git a/src/corelib/tools/qqueue.cpp b/src/corelib/tools/qqueue.cpp
index 4edbdf2ebf..2903dbea72 100644
--- a/src/corelib/tools/qqueue.cpp
+++ b/src/corelib/tools/qqueue.cpp
@@ -45,7 +45,7 @@
\ingroup tools
\ingroup shared
- \mainclass
+
\reentrant
QQueue\<T\> is one of Qt's generic \l{container classes}. It
diff --git a/src/corelib/tools/qrect.cpp b/src/corelib/tools/qrect.cpp
index 443bcc1779..b54ec31617 100644
--- a/src/corelib/tools/qrect.cpp
+++ b/src/corelib/tools/qrect.cpp
@@ -50,7 +50,7 @@ QT_BEGIN_NAMESPACE
/*!
\class QRect
- \ingroup multimedia
+ \ingroup painting
\brief The QRect class defines a rectangle in the plane using
integer precision.
@@ -1324,7 +1324,7 @@ QDebug operator<<(QDebug dbg, const QRect &r) {
/*!
\class QRectF
- \ingroup multimedia
+ \ingroup painting
\brief The QRectF class defines a rectangle in the plane using floating
point precision.
diff --git a/src/corelib/tools/qregexp.cpp b/src/corelib/tools/qregexp.cpp
index 5d4b2326a4..2572443ad8 100644
--- a/src/corelib/tools/qregexp.cpp
+++ b/src/corelib/tools/qregexp.cpp
@@ -52,6 +52,7 @@
#include "qstringlist.h"
#include "qstringmatcher.h"
#include "qvector.h"
+#include "private/qfunctions_p.h"
#include <limits.h>
@@ -70,6 +71,8 @@ int qFindString(const QChar *haystack, int haystackLen, int from,
#define RXERR_LEFTDELIM QT_TRANSLATE_NOOP("QRegExp", "missing left delim")
#define RXERR_END QT_TRANSLATE_NOOP("QRegExp", "unexpected end")
#define RXERR_LIMIT QT_TRANSLATE_NOOP("QRegExp", "met internal limit")
+#define RXERR_INTERVAL QT_TRANSLATE_NOOP("QRegExp", "invalid interval")
+#define RXERR_CATEGORY QT_TRANSLATE_NOOP("QRegExp", "invalid category")
/*
WARNING! Be sure to read qregexp.tex before modifying this file.
@@ -81,9 +84,8 @@ int qFindString(const QChar *haystack, int haystackLen, int from,
\brief The QRegExp class provides pattern matching using regular expressions.
\ingroup tools
- \ingroup misc
\ingroup shared
- \mainclass
+
\keyword regular expression
A regular expression, or "regexp", is a pattern for matching
@@ -686,6 +688,10 @@ int qFindString(const QChar *haystack, int haystackLen, int from,
{tools/regexp}{Regular Expression Example}
*/
+#if defined(Q_OS_VXWORKS) && defined(EOS)
+# undef EOS
+#endif
+
const int NumBadChars = 64;
#define BadChar(ch) ((ch).unicode() % NumBadChars)
@@ -827,7 +833,7 @@ struct QRegExpEngineKey
}
};
-bool operator==(const QRegExpEngineKey &key1, const QRegExpEngineKey &key2)
+Q_STATIC_GLOBAL_OPERATOR bool operator==(const QRegExpEngineKey &key1, const QRegExpEngineKey &key2)
{
return key1.pattern == key2.pattern && key1.patternSyntax == key2.patternSyntax
&& key1.cs == key2.cs;
@@ -1116,6 +1122,7 @@ private:
bool valid; // is the regular expression valid?
Qt::CaseSensitivity cs; // case sensitive?
bool greedyQuantifiers; // RegExp2?
+ bool xmlSchemaExtensions;
#ifndef QT_NO_REGEXP_BACKREF
int nbrefs; // number of back-references
#endif
@@ -1193,6 +1200,8 @@ private:
friend class Box;
+ void setupCategoriesRangeMap();
+
/*
This is the lexical analyzer for regular expressions.
*/
@@ -1216,7 +1225,7 @@ private:
int yyPos; // the position of the next character to read
int yyLen; // the length of yyIn
int yyCh; // the last character read
- QRegExpCharClass *yyCharClass; // attribute for Tok_CharClass tokens
+ QScopedPointer<QRegExpCharClass> yyCharClass; // attribute for Tok_CharClass tokens
int yyMinRep; // attribute for Tok_Quantifier
int yyMaxRep; // ditto
QString yyError; // syntax error or overflow during parsing?
@@ -1232,6 +1241,7 @@ private:
int yyTok; // the last token read
bool yyMayCapture; // set this to false to disable capturing
+ QHash<QByteArray, QPair<int, int> > categoriesRangeMap; // fast lookup hash for xml schema extensions
friend struct QRegExpMatchState;
};
@@ -1252,25 +1262,35 @@ struct QRegExpLookahead
};
#endif
-QRegExpEngine::QRegExpEngine(const QRegExpEngineKey &key)
- : cs(key.cs), greedyQuantifiers(key.patternSyntax == QRegExp::RegExp2)
-{
- setup();
+/*! \internal
+ convert the pattern string to the RegExp syntax.
- QString rx;
-
- switch (key.patternSyntax) {
- case QRegExp::Wildcard:
+ This is also used by QScriptEngine::newRegExp to convert to a pattern that JavaScriptCore can understan
+ */
+Q_CORE_EXPORT QString qt_regexp_toCanonical(const QString &pattern, QRegExp::PatternSyntax patternSyntax)
+{
+ switch (patternSyntax) {
#ifndef QT_NO_REGEXP_WILDCARD
- rx = wc2rx(key.pattern);
-#endif
+ case QRegExp::Wildcard:
+ return wc2rx(pattern);
break;
+#endif
case QRegExp::FixedString:
- rx = QRegExp::escape(key.pattern);
+ return QRegExp::escape(pattern);
break;
+ case QRegExp::W3CXmlSchema11:
default:
- rx = key.pattern;
+ return pattern;
}
+}
+
+QRegExpEngine::QRegExpEngine(const QRegExpEngineKey &key)
+ : cs(key.cs), greedyQuantifiers(key.patternSyntax == QRegExp::RegExp2),
+ xmlSchemaExtensions(key.patternSyntax == QRegExp::W3CXmlSchema11)
+{
+ setup();
+
+ QString rx = qt_regexp_toCanonical(key.pattern, key.patternSyntax);
valid = (parse(rx.unicode(), rx.length()) == rx.length());
if (!valid) {
@@ -1297,14 +1317,19 @@ void QRegExpMatchState::prepareForMatch(QRegExpEngine *eng)
int ns = eng->s.size(); // number of states
int ncap = eng->ncap;
#ifndef QT_NO_REGEXP_OPTIM
- slideTabSize = qMax(eng->minl + 1, 16);
+ int newSlideTabSize = qMax(eng->minl + 1, 16);
#else
- slideTabSize = 0;
+ int newSlideTabSize = 0;
#endif
int numCaptures = eng->numCaptures();
- capturedSize = 2 + 2 * numCaptures;
- bigArray = (int *)realloc(bigArray, ((3 + 4 * ncap) * ns + 4 * ncap + slideTabSize + capturedSize)*sizeof(int));
+ int newCapturedSize = 2 + 2 * numCaptures;
+ bigArray = q_check_ptr((int *)realloc(bigArray, ((3 + 4 * ncap) * ns + 4 * ncap + newSlideTabSize + newCapturedSize)*sizeof(int)));
+
+ // set all internal variables only _after_ bigArray is realloc'ed
+ // to prevent a broken regexp in oom case
+ slideTabSize = newSlideTabSize;
+ capturedSize = newCapturedSize;
inNextStack = bigArray;
memset(inNextStack, -1, ns * sizeof(int));
curStack = inNextStack + ns;
@@ -1479,9 +1504,8 @@ int QRegExpEngine::anchorAlternation(int a, int b)
return Anchor_Alternation | (n - 1);
#endif
- aa.resize(n + 1);
- aa[n].a = a;
- aa[n].b = b;
+ QRegExpAnchorAlternation element = {a, b};
+ aa.append(element);
return Anchor_Alternation | n;
}
@@ -2621,6 +2645,152 @@ void QRegExpEngine::Box::addAnchorsToEngine(const Box &to) const
}
}
+void QRegExpEngine::setupCategoriesRangeMap()
+{
+ categoriesRangeMap.insert("IsBasicLatin", qMakePair(0x0000, 0x007F));
+ categoriesRangeMap.insert("IsLatin-1Supplement", qMakePair(0x0080, 0x00FF));
+ categoriesRangeMap.insert("IsLatinExtended-A", qMakePair(0x0100, 0x017F));
+ categoriesRangeMap.insert("IsLatinExtended-B", qMakePair(0x0180, 0x024F));
+ categoriesRangeMap.insert("IsIPAExtensions", qMakePair(0x0250, 0x02AF));
+ categoriesRangeMap.insert("IsSpacingModifierLetters", qMakePair(0x02B0, 0x02FF));
+ categoriesRangeMap.insert("IsCombiningDiacriticalMarks", qMakePair(0x0300, 0x036F));
+ categoriesRangeMap.insert("IsGreek", qMakePair(0x0370, 0x03FF));
+ categoriesRangeMap.insert("IsCyrillic", qMakePair(0x0400, 0x04FF));
+ categoriesRangeMap.insert("IsCyrillicSupplement", qMakePair(0x0500, 0x052F));
+ categoriesRangeMap.insert("IsArmenian", qMakePair(0x0530, 0x058F));
+ categoriesRangeMap.insert("IsHebrew", qMakePair(0x0590, 0x05FF));
+ categoriesRangeMap.insert("IsArabic", qMakePair(0x0600, 0x06FF));
+ categoriesRangeMap.insert("IsSyriac", qMakePair(0x0700, 0x074F));
+ categoriesRangeMap.insert("IsArabicSupplement", qMakePair(0x0750, 0x077F));
+ categoriesRangeMap.insert("IsThaana", qMakePair(0x0780, 0x07BF));
+ categoriesRangeMap.insert("IsDevanagari", qMakePair(0x0900, 0x097F));
+ categoriesRangeMap.insert("IsBengali", qMakePair(0x0980, 0x09FF));
+ categoriesRangeMap.insert("IsGurmukhi", qMakePair(0x0A00, 0x0A7F));
+ categoriesRangeMap.insert("IsGujarati", qMakePair(0x0A80, 0x0AFF));
+ categoriesRangeMap.insert("IsOriya", qMakePair(0x0B00, 0x0B7F));
+ categoriesRangeMap.insert("IsTamil", qMakePair(0x0B80, 0x0BFF));
+ categoriesRangeMap.insert("IsTelugu", qMakePair(0x0C00, 0x0C7F));
+ categoriesRangeMap.insert("IsKannada", qMakePair(0x0C80, 0x0CFF));
+ categoriesRangeMap.insert("IsMalayalam", qMakePair(0x0D00, 0x0D7F));
+ categoriesRangeMap.insert("IsSinhala", qMakePair(0x0D80, 0x0DFF));
+ categoriesRangeMap.insert("IsThai", qMakePair(0x0E00, 0x0E7F));
+ categoriesRangeMap.insert("IsLao", qMakePair(0x0E80, 0x0EFF));
+ categoriesRangeMap.insert("IsTibetan", qMakePair(0x0F00, 0x0FFF));
+ categoriesRangeMap.insert("IsMyanmar", qMakePair(0x1000, 0x109F));
+ categoriesRangeMap.insert("IsGeorgian", qMakePair(0x10A0, 0x10FF));
+ categoriesRangeMap.insert("IsHangulJamo", qMakePair(0x1100, 0x11FF));
+ categoriesRangeMap.insert("IsEthiopic", qMakePair(0x1200, 0x137F));
+ categoriesRangeMap.insert("IsEthiopicSupplement", qMakePair(0x1380, 0x139F));
+ categoriesRangeMap.insert("IsCherokee", qMakePair(0x13A0, 0x13FF));
+ categoriesRangeMap.insert("IsUnifiedCanadianAboriginalSyllabics", qMakePair(0x1400, 0x167F));
+ categoriesRangeMap.insert("IsOgham", qMakePair(0x1680, 0x169F));
+ categoriesRangeMap.insert("IsRunic", qMakePair(0x16A0, 0x16FF));
+ categoriesRangeMap.insert("IsTagalog", qMakePair(0x1700, 0x171F));
+ categoriesRangeMap.insert("IsHanunoo", qMakePair(0x1720, 0x173F));
+ categoriesRangeMap.insert("IsBuhid", qMakePair(0x1740, 0x175F));
+ categoriesRangeMap.insert("IsTagbanwa", qMakePair(0x1760, 0x177F));
+ categoriesRangeMap.insert("IsKhmer", qMakePair(0x1780, 0x17FF));
+ categoriesRangeMap.insert("IsMongolian", qMakePair(0x1800, 0x18AF));
+ categoriesRangeMap.insert("IsLimbu", qMakePair(0x1900, 0x194F));
+ categoriesRangeMap.insert("IsTaiLe", qMakePair(0x1950, 0x197F));
+ categoriesRangeMap.insert("IsNewTaiLue", qMakePair(0x1980, 0x19DF));
+ categoriesRangeMap.insert("IsKhmerSymbols", qMakePair(0x19E0, 0x19FF));
+ categoriesRangeMap.insert("IsBuginese", qMakePair(0x1A00, 0x1A1F));
+ categoriesRangeMap.insert("IsPhoneticExtensions", qMakePair(0x1D00, 0x1D7F));
+ categoriesRangeMap.insert("IsPhoneticExtensionsSupplement", qMakePair(0x1D80, 0x1DBF));
+ categoriesRangeMap.insert("IsCombiningDiacriticalMarksSupplement", qMakePair(0x1DC0, 0x1DFF));
+ categoriesRangeMap.insert("IsLatinExtendedAdditional", qMakePair(0x1E00, 0x1EFF));
+ categoriesRangeMap.insert("IsGreekExtended", qMakePair(0x1F00, 0x1FFF));
+ categoriesRangeMap.insert("IsGeneralPunctuation", qMakePair(0x2000, 0x206F));
+ categoriesRangeMap.insert("IsSuperscriptsandSubscripts", qMakePair(0x2070, 0x209F));
+ categoriesRangeMap.insert("IsCurrencySymbols", qMakePair(0x20A0, 0x20CF));
+ categoriesRangeMap.insert("IsCombiningMarksforSymbols", qMakePair(0x20D0, 0x20FF));
+ categoriesRangeMap.insert("IsLetterlikeSymbols", qMakePair(0x2100, 0x214F));
+ categoriesRangeMap.insert("IsNumberForms", qMakePair(0x2150, 0x218F));
+ categoriesRangeMap.insert("IsArrows", qMakePair(0x2190, 0x21FF));
+ categoriesRangeMap.insert("IsMathematicalOperators", qMakePair(0x2200, 0x22FF));
+ categoriesRangeMap.insert("IsMiscellaneousTechnical", qMakePair(0x2300, 0x23FF));
+ categoriesRangeMap.insert("IsControlPictures", qMakePair(0x2400, 0x243F));
+ categoriesRangeMap.insert("IsOpticalCharacterRecognition", qMakePair(0x2440, 0x245F));
+ categoriesRangeMap.insert("IsEnclosedAlphanumerics", qMakePair(0x2460, 0x24FF));
+ categoriesRangeMap.insert("IsBoxDrawing", qMakePair(0x2500, 0x257F));
+ categoriesRangeMap.insert("IsBlockElements", qMakePair(0x2580, 0x259F));
+ categoriesRangeMap.insert("IsGeometricShapes", qMakePair(0x25A0, 0x25FF));
+ categoriesRangeMap.insert("IsMiscellaneousSymbols", qMakePair(0x2600, 0x26FF));
+ categoriesRangeMap.insert("IsDingbats", qMakePair(0x2700, 0x27BF));
+ categoriesRangeMap.insert("IsMiscellaneousMathematicalSymbols-A", qMakePair(0x27C0, 0x27EF));
+ categoriesRangeMap.insert("IsSupplementalArrows-A", qMakePair(0x27F0, 0x27FF));
+ categoriesRangeMap.insert("IsBraillePatterns", qMakePair(0x2800, 0x28FF));
+ categoriesRangeMap.insert("IsSupplementalArrows-B", qMakePair(0x2900, 0x297F));
+ categoriesRangeMap.insert("IsMiscellaneousMathematicalSymbols-B", qMakePair(0x2980, 0x29FF));
+ categoriesRangeMap.insert("IsSupplementalMathematicalOperators", qMakePair(0x2A00, 0x2AFF));
+ categoriesRangeMap.insert("IsMiscellaneousSymbolsandArrows", qMakePair(0x2B00, 0x2BFF));
+ categoriesRangeMap.insert("IsGlagolitic", qMakePair(0x2C00, 0x2C5F));
+ categoriesRangeMap.insert("IsCoptic", qMakePair(0x2C80, 0x2CFF));
+ categoriesRangeMap.insert("IsGeorgianSupplement", qMakePair(0x2D00, 0x2D2F));
+ categoriesRangeMap.insert("IsTifinagh", qMakePair(0x2D30, 0x2D7F));
+ categoriesRangeMap.insert("IsEthiopicExtended", qMakePair(0x2D80, 0x2DDF));
+ categoriesRangeMap.insert("IsSupplementalPunctuation", qMakePair(0x2E00, 0x2E7F));
+ categoriesRangeMap.insert("IsCJKRadicalsSupplement", qMakePair(0x2E80, 0x2EFF));
+ categoriesRangeMap.insert("IsKangxiRadicals", qMakePair(0x2F00, 0x2FDF));
+ categoriesRangeMap.insert("IsIdeographicDescriptionCharacters", qMakePair(0x2FF0, 0x2FFF));
+ categoriesRangeMap.insert("IsCJKSymbolsandPunctuation", qMakePair(0x3000, 0x303F));
+ categoriesRangeMap.insert("IsHiragana", qMakePair(0x3040, 0x309F));
+ categoriesRangeMap.insert("IsKatakana", qMakePair(0x30A0, 0x30FF));
+ categoriesRangeMap.insert("IsBopomofo", qMakePair(0x3100, 0x312F));
+ categoriesRangeMap.insert("IsHangulCompatibilityJamo", qMakePair(0x3130, 0x318F));
+ categoriesRangeMap.insert("IsKanbun", qMakePair(0x3190, 0x319F));
+ categoriesRangeMap.insert("IsBopomofoExtended", qMakePair(0x31A0, 0x31BF));
+ categoriesRangeMap.insert("IsCJKStrokes", qMakePair(0x31C0, 0x31EF));
+ categoriesRangeMap.insert("IsKatakanaPhoneticExtensions", qMakePair(0x31F0, 0x31FF));
+ categoriesRangeMap.insert("IsEnclosedCJKLettersandMonths", qMakePair(0x3200, 0x32FF));
+ categoriesRangeMap.insert("IsCJKCompatibility", qMakePair(0x3300, 0x33FF));
+ categoriesRangeMap.insert("IsCJKUnifiedIdeographsExtensionA", qMakePair(0x3400, 0x4DB5));
+ categoriesRangeMap.insert("IsYijingHexagramSymbols", qMakePair(0x4DC0, 0x4DFF));
+ categoriesRangeMap.insert("IsCJKUnifiedIdeographs", qMakePair(0x4E00, 0x9FFF));
+ categoriesRangeMap.insert("IsYiSyllables", qMakePair(0xA000, 0xA48F));
+ categoriesRangeMap.insert("IsYiRadicals", qMakePair(0xA490, 0xA4CF));
+ categoriesRangeMap.insert("IsModifierToneLetters", qMakePair(0xA700, 0xA71F));
+ categoriesRangeMap.insert("IsSylotiNagri", qMakePair(0xA800, 0xA82F));
+ categoriesRangeMap.insert("IsHangulSyllables", qMakePair(0xAC00, 0xD7A3));
+ categoriesRangeMap.insert("IsPrivateUse", qMakePair(0xE000, 0xF8FF));
+ categoriesRangeMap.insert("IsCJKCompatibilityIdeographs", qMakePair(0xF900, 0xFAFF));
+ categoriesRangeMap.insert("IsAlphabeticPresentationForms", qMakePair(0xFB00, 0xFB4F));
+ categoriesRangeMap.insert("IsArabicPresentationForms-A", qMakePair(0xFB50, 0xFDFF));
+ categoriesRangeMap.insert("IsVariationSelectors", qMakePair(0xFE00, 0xFE0F));
+ categoriesRangeMap.insert("IsVerticalForms", qMakePair(0xFE10, 0xFE1F));
+ categoriesRangeMap.insert("IsCombiningHalfMarks", qMakePair(0xFE20, 0xFE2F));
+ categoriesRangeMap.insert("IsCJKCompatibilityForms", qMakePair(0xFE30, 0xFE4F));
+ categoriesRangeMap.insert("IsSmallFormVariants", qMakePair(0xFE50, 0xFE6F));
+ categoriesRangeMap.insert("IsArabicPresentationForms-B", qMakePair(0xFE70, 0xFEFF));
+ categoriesRangeMap.insert("IsHalfwidthandFullwidthForms", qMakePair(0xFF00, 0xFFEF));
+ categoriesRangeMap.insert("IsSpecials", qMakePair(0xFFF0, 0xFFFF));
+ categoriesRangeMap.insert("IsLinearBSyllabary", qMakePair(0x10000, 0x1007F));
+ categoriesRangeMap.insert("IsLinearBIdeograms", qMakePair(0x10080, 0x100FF));
+ categoriesRangeMap.insert("IsAegeanNumbers", qMakePair(0x10100, 0x1013F));
+ categoriesRangeMap.insert("IsAncientGreekNumbers", qMakePair(0x10140, 0x1018F));
+ categoriesRangeMap.insert("IsOldItalic", qMakePair(0x10300, 0x1032F));
+ categoriesRangeMap.insert("IsGothic", qMakePair(0x10330, 0x1034F));
+ categoriesRangeMap.insert("IsUgaritic", qMakePair(0x10380, 0x1039F));
+ categoriesRangeMap.insert("IsOldPersian", qMakePair(0x103A0, 0x103DF));
+ categoriesRangeMap.insert("IsDeseret", qMakePair(0x10400, 0x1044F));
+ categoriesRangeMap.insert("IsShavian", qMakePair(0x10450, 0x1047F));
+ categoriesRangeMap.insert("IsOsmanya", qMakePair(0x10480, 0x104AF));
+ categoriesRangeMap.insert("IsCypriotSyllabary", qMakePair(0x10800, 0x1083F));
+ categoriesRangeMap.insert("IsKharoshthi", qMakePair(0x10A00, 0x10A5F));
+ categoriesRangeMap.insert("IsByzantineMusicalSymbols", qMakePair(0x1D000, 0x1D0FF));
+ categoriesRangeMap.insert("IsMusicalSymbols", qMakePair(0x1D100, 0x1D1FF));
+ categoriesRangeMap.insert("IsAncientGreekMusicalNotation", qMakePair(0x1D200, 0x1D24F));
+ categoriesRangeMap.insert("IsTaiXuanJingSymbols", qMakePair(0x1D300, 0x1D35F));
+ categoriesRangeMap.insert("IsMathematicalAlphanumericSymbols", qMakePair(0x1D400, 0x1D7FF));
+ categoriesRangeMap.insert("IsCJKUnifiedIdeographsExtensionB", qMakePair(0x20000, 0x2A6DF));
+ categoriesRangeMap.insert("IsCJKCompatibilityIdeographsSupplement", qMakePair(0x2F800, 0x2FA1F));
+ categoriesRangeMap.insert("IsTags", qMakePair(0xE0000, 0xE007F));
+ categoriesRangeMap.insert("IsVariationSelectorsSupplement", qMakePair(0xE0100, 0xE01EF));
+ categoriesRangeMap.insert("IsSupplementaryPrivateUseArea-A", qMakePair(0xF0000, 0xFFFFF));
+ categoriesRangeMap.insert("IsSupplementaryPrivateUseArea-B", qMakePair(0x100000, 0x10FFFF));
+}
+
int QRegExpEngine::getChar()
{
return (yyPos == yyLen) ? EOS : yyIn[yyPos++].unicode();
@@ -2713,6 +2883,177 @@ int QRegExpEngine::getEscape()
yyCharClass->addCategories(0x000f807e);
yyCharClass->addSingleton(0x005f); // '_'
return Tok_CharClass;
+ case 'I':
+ if (xmlSchemaExtensions) {
+ yyCharClass->setNegative(!yyCharClass->negative());
+ // fall through
+ }
+ case 'i':
+ if (xmlSchemaExtensions) {
+ yyCharClass->addCategories(0x000f807e);
+ yyCharClass->addSingleton(0x003a); // ':'
+ yyCharClass->addSingleton(0x005f); // '_'
+ yyCharClass->addRange(0x0041, 0x005a); // [A-Z]
+ yyCharClass->addRange(0x0061, 0x007a); // [a-z]
+ yyCharClass->addRange(0xc0, 0xd6);
+ yyCharClass->addRange(0xd8, 0xf6);
+ yyCharClass->addRange(0xf8, 0x2ff);
+ yyCharClass->addRange(0x370, 0x37d);
+ yyCharClass->addRange(0x37f, 0x1fff);
+ yyCharClass->addRange(0x200c, 0x200d);
+ yyCharClass->addRange(0x2070, 0x218f);
+ yyCharClass->addRange(0x2c00, 0x2fef);
+ yyCharClass->addRange(0x3001, 0xd7ff);
+ yyCharClass->addRange(0xf900, 0xfdcf);
+ yyCharClass->addRange(0xfdf0, 0xfffd);
+ yyCharClass->addRange((ushort)0x10000, (ushort)0xeffff);
+ }
+ return Tok_CharClass;
+ case 'C':
+ if (xmlSchemaExtensions) {
+ yyCharClass->setNegative(!yyCharClass->negative());
+ // fall through
+ }
+ case 'c':
+ if (xmlSchemaExtensions) {
+ yyCharClass->addCategories(0x000f807e);
+ yyCharClass->addSingleton(0x002d); // '-'
+ yyCharClass->addSingleton(0x002e); // '.'
+ yyCharClass->addSingleton(0x003a); // ':'
+ yyCharClass->addSingleton(0x005f); // '_'
+ yyCharClass->addSingleton(0xb7);
+ yyCharClass->addRange(0x0030, 0x0039); // [0-9]
+ yyCharClass->addRange(0x0041, 0x005a); // [A-Z]
+ yyCharClass->addRange(0x0061, 0x007a); // [a-z]
+ yyCharClass->addRange(0xc0, 0xd6);
+ yyCharClass->addRange(0xd8, 0xf6);
+ yyCharClass->addRange(0xf8, 0x2ff);
+ yyCharClass->addRange(0x370, 0x37d);
+ yyCharClass->addRange(0x37f, 0x1fff);
+ yyCharClass->addRange(0x200c, 0x200d);
+ yyCharClass->addRange(0x2070, 0x218f);
+ yyCharClass->addRange(0x2c00, 0x2fef);
+ yyCharClass->addRange(0x3001, 0xd7ff);
+ yyCharClass->addRange(0xf900, 0xfdcf);
+ yyCharClass->addRange(0xfdf0, 0xfffd);
+ yyCharClass->addRange((ushort)0x10000, (ushort)0xeffff);
+ yyCharClass->addRange(0x0300, 0x036f);
+ yyCharClass->addRange(0x203f, 0x2040);
+ }
+ return Tok_CharClass;
+ case 'P':
+ if (xmlSchemaExtensions) {
+ yyCharClass->setNegative(!yyCharClass->negative());
+ // fall through
+ }
+ case 'p':
+ if (xmlSchemaExtensions) {
+ if (yyCh != '{') {
+ error(RXERR_CHARCLASS);
+ return Tok_CharClass;
+ }
+
+ QByteArray category;
+ yyCh = getChar();
+ while (yyCh != '}') {
+ if (yyCh == EOS) {
+ error(RXERR_END);
+ return Tok_CharClass;
+ }
+ category.append(yyCh);
+ yyCh = getChar();
+ }
+ yyCh = getChar(); // skip closing '}'
+
+ if (category == "M") {
+ yyCharClass->addCategories(0x0000000e);
+ } else if (category == "Mn") {
+ yyCharClass->addCategories(0x00000002);
+ } else if (category == "Mc") {
+ yyCharClass->addCategories(0x00000004);
+ } else if (category == "Me") {
+ yyCharClass->addCategories(0x00000008);
+ } else if (category == "N") {
+ yyCharClass->addCategories(0x00000070);
+ } else if (category == "Nd") {
+ yyCharClass->addCategories(0x00000010);
+ } else if (category == "Nl") {
+ yyCharClass->addCategories(0x00000020);
+ } else if (category == "No") {
+ yyCharClass->addCategories(0x00000040);
+ } else if (category == "Z") {
+ yyCharClass->addCategories(0x00000380);
+ } else if (category == "Zs") {
+ yyCharClass->addCategories(0x00000080);
+ } else if (category == "Zl") {
+ yyCharClass->addCategories(0x00000100);
+ } else if (category == "Zp") {
+ yyCharClass->addCategories(0x00000200);
+ } else if (category == "C") {
+ yyCharClass->addCategories(0x00006c00);
+ } else if (category == "Cc") {
+ yyCharClass->addCategories(0x00000400);
+ } else if (category == "Cf") {
+ yyCharClass->addCategories(0x00000800);
+ } else if (category == "Cs") {
+ yyCharClass->addCategories(0x00001000);
+ } else if (category == "Co") {
+ yyCharClass->addCategories(0x00002000);
+ } else if (category == "Cn") {
+ yyCharClass->addCategories(0x00004000);
+ } else if (category == "L") {
+ yyCharClass->addCategories(0x000f8000);
+ } else if (category == "Lu") {
+ yyCharClass->addCategories(0x00008000);
+ } else if (category == "Ll") {
+ yyCharClass->addCategories(0x00010000);
+ } else if (category == "Lt") {
+ yyCharClass->addCategories(0x00020000);
+ } else if (category == "Lm") {
+ yyCharClass->addCategories(0x00040000);
+ } else if (category == "Lo") {
+ yyCharClass->addCategories(0x00080000);
+ } else if (category == "P") {
+ yyCharClass->addCategories(0x4f580780);
+ } else if (category == "Pc") {
+ yyCharClass->addCategories(0x00100000);
+ } else if (category == "Pd") {
+ yyCharClass->addCategories(0x00200000);
+ } else if (category == "Ps") {
+ yyCharClass->addCategories(0x00400000);
+ } else if (category == "Pe") {
+ yyCharClass->addCategories(0x00800000);
+ } else if (category == "Pi") {
+ yyCharClass->addCategories(0x01000000);
+ } else if (category == "Pf") {
+ yyCharClass->addCategories(0x02000000);
+ } else if (category == "Po") {
+ yyCharClass->addCategories(0x04000000);
+ } else if (category == "S") {
+ yyCharClass->addCategories(0x78000000);
+ } else if (category == "Sm") {
+ yyCharClass->addCategories(0x08000000);
+ } else if (category == "Sc") {
+ yyCharClass->addCategories(0x10000000);
+ } else if (category == "Sk") {
+ yyCharClass->addCategories(0x20000000);
+ } else if (category == "So") {
+ yyCharClass->addCategories(0x40000000);
+ } else if (category.startsWith("Is")) {
+ if (categoriesRangeMap.isEmpty())
+ setupCategoriesRangeMap();
+
+ if (categoriesRangeMap.contains(category)) {
+ const QPair<int, int> range = categoriesRangeMap.value(category);
+ yyCharClass->addRange(range.first, range.second);
+ } else {
+ error(RXERR_CATEGORY);
+ }
+ } else {
+ error(RXERR_CATEGORY);
+ }
+ }
+ return Tok_CharClass;
#endif
#ifndef QT_NO_REGEXP_ESCAPE
case 'x':
@@ -2789,7 +3130,7 @@ void QRegExpEngine::startTokenizer(const QChar *rx, int len)
yyPos = 0;
yyLen = len;
yyCh = getChar();
- yyCharClass = new QRegExpCharClass;
+ yyCharClass.reset(new QRegExpCharClass);
yyMinRep = 0;
yyMaxRep = 0;
yyError = QString();
@@ -2934,7 +3275,7 @@ int QRegExpEngine::getToken()
yyMaxRep = getRep(InftyRep);
}
if (yyMaxRep < yyMinRep)
- qSwap(yyMinRep, yyMaxRep);
+ error(RXERR_INTERVAL);
if (yyCh != '}')
error(RXERR_REPETITION);
yyCh = getChar();
@@ -2983,8 +3324,7 @@ int QRegExpEngine::parse(const QChar *pattern, int len)
#endif
box.cat(middleBox);
box.cat(rightBox);
- delete yyCharClass;
- yyCharClass = 0;
+ yyCharClass.reset(0);
#ifndef QT_NO_REGEXP_CAPTURE
for (int i = 0; i < nf; ++i) {
@@ -3281,10 +3621,15 @@ static void derefEngine(QRegExpEngine *eng, const QRegExpEngineKey &key)
#if !defined(QT_NO_REGEXP_OPTIM)
if (globalEngineCache()) {
QMutexLocker locker(mutex());
- globalEngineCache()->insert(key, eng, 4 + key.pattern.length() / 4);
- }
- else
+ QT_TRY {
+ globalEngineCache()->insert(key, eng, 4 + key.pattern.length() / 4);
+ } QT_CATCH(const std::bad_alloc &) {
+ // in case of an exception (e.g. oom), just delete the engine
+ delete eng;
+ }
+ } else {
delete eng;
+ }
#else
Q_UNUSED(key);
delete eng;
@@ -3374,6 +3719,9 @@ static void invalidateEngine(QRegExpPrivate *priv)
equivalent to using the RegExp pattern on a string in
which all metacharacters are escaped using escape().
+ \value W3CXmlSchema11 The pattern is a regular expression as
+ defined by the W3C XML Schema 1.1 specification.
+
\sa setPatternSyntax()
*/
@@ -4065,6 +4413,6 @@ QDataStream &operator>>(QDataStream &in, QRegExp &regExp)
regExp = newRegExp;
return in;
}
-#endif
+#endif // QT_NO_DATASTREAM
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qregexp.h b/src/corelib/tools/qregexp.h
index d2bdd7ee9f..30f09496a5 100644
--- a/src/corelib/tools/qregexp.h
+++ b/src/corelib/tools/qregexp.h
@@ -61,7 +61,7 @@ class QStringList;
class Q_CORE_EXPORT QRegExp
{
public:
- enum PatternSyntax { RegExp, Wildcard, FixedString, RegExp2 };
+ enum PatternSyntax { RegExp, Wildcard, FixedString, RegExp2, W3CXmlSchema11 };
enum CaretMode { CaretAtZero, CaretAtOffset, CaretWontMatch };
QRegExp();
diff --git a/src/corelib/tools/qringbuffer_p.h b/src/corelib/tools/qringbuffer_p.h
index 75cbb1f6cf..544ea1a331 100644
--- a/src/corelib/tools/qringbuffer_p.h
+++ b/src/corelib/tools/qringbuffer_p.h
@@ -58,7 +58,7 @@
QT_BEGIN_NAMESPACE
-class Q_CORE_EXPORT QRingBuffer
+class QRingBuffer
{
public:
inline QRingBuffer(int growth = 4096) : basicBlockSize(growth) {
@@ -74,6 +74,52 @@ public:
return buffers.isEmpty() ? 0 : (buffers.first().constData() + head);
}
+ // access the bytes at a specified position
+ // the out-variable length will contain the amount of bytes readable
+ // from there, e.g. the amount still the same QByteArray
+ inline const char *readPointerAtPosition(qint64 pos, qint64 &length) const {
+ if (buffers.isEmpty()) {
+ length = 0;
+ return 0;
+ }
+
+ if (pos >= bufferSize) {
+ length = 0;
+ return 0;
+ }
+
+ // special case: it is in the first buffer
+ int nextDataBlockSizeValue = nextDataBlockSize();
+ if (pos - head < nextDataBlockSizeValue) {
+ length = nextDataBlockSizeValue - pos;
+ return buffers.at(0).constData() + head + pos;
+ }
+
+ // special case: we only had one buffer and tried to read over it
+ if (buffers.length() == 1) {
+ length = 0;
+ return 0;
+ }
+
+ // skip the first
+ pos -= nextDataBlockSizeValue;
+
+ // normal case: it is somewhere in the second to the-one-before-the-tailBuffer
+ for (int i = 1; i < tailBuffer; i++) {
+ if (pos >= buffers[i].size()) {
+ pos -= buffers[i].size();
+ continue;
+ }
+
+ length = buffers[i].length() - pos;
+ return buffers[i].constData() + pos;
+ }
+
+ // it is in the tail buffer
+ length = tail - pos;
+ return buffers[tailBuffer].constData() + pos;
+ }
+
inline void free(int bytes) {
bufferSize -= bytes;
if (bufferSize < 0)
@@ -199,9 +245,7 @@ public:
inline void clear() {
if(!buffers.isEmpty()) {
- QByteArray tmp = buffers[0];
- buffers.clear();
- buffers << tmp;
+ buffers.erase(buffers.begin() + 1, buffers.end());
if (buffers.at(0).size() != basicBlockSize)
buffers[0].resize(basicBlockSize);
}
@@ -255,6 +299,54 @@ public:
return read(size());
}
+ // read an unspecified amount (will read the first buffer)
+ inline QByteArray read() {
+ if (bufferSize == 0)
+ return QByteArray();
+
+ // multiple buffers, just take the first one
+ if (head == 0 && tailBuffer != 0) {
+ QByteArray qba = buffers.takeFirst();
+ --tailBuffer;
+ bufferSize -= qba.length();
+ return qba;
+ }
+
+ // one buffer with good value for head. Just take it.
+ if (head == 0 && tailBuffer == 0) {
+ QByteArray qba = buffers.takeFirst();
+ qba.resize(tail);
+ buffers << QByteArray();
+ bufferSize = 0;
+ tail = 0;
+ return qba;
+ }
+
+ // Bad case: We have to memcpy.
+ // We can avoid by initializing the QRingBuffer with basicBlockSize of 0
+ // and only using this read() function.
+ QByteArray qba(readPointer(), nextDataBlockSize());
+ buffers.removeFirst();
+ head = 0;
+ if (tailBuffer == 0) {
+ buffers << QByteArray();
+ tail = 0;
+ } else {
+ --tailBuffer;
+ }
+ bufferSize -= qba.length();
+ return qba;
+ }
+
+ // append a new buffer to the end
+ inline void append(const QByteArray &qba) {
+ buffers[tailBuffer].resize(tail);
+ buffers << qba;
+ ++tailBuffer;
+ tail = qba.length();
+ bufferSize += qba.length();
+ }
+
inline QByteArray peek(int maxLength) const {
int bytesToRead = qMin(size(), maxLength);
if(maxLength <= 0)
@@ -309,7 +401,7 @@ public:
private:
QList<QByteArray> buffers;
int head, tail;
- int tailBuffer;
+ int tailBuffer; // always buffers.size() - 1
int basicBlockSize;
int bufferSize;
};
diff --git a/src/corelib/tools/qscopedpointer.cpp b/src/corelib/tools/qscopedpointer.cpp
new file mode 100644
index 0000000000..5296bae6d4
--- /dev/null
+++ b/src/corelib/tools/qscopedpointer.cpp
@@ -0,0 +1,218 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qscopedpointer.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QScopedPointer
+ \brief The QScopedPointer class stores a pointer to a dynamically allocated object, and deletes it upon destruction.
+ \since 4.6
+ \reentrant
+ \ingroup misc
+
+ Managing heap allocated objects manually is hard and error prone, with the
+ common result that code leaks memory and is hard to maintain.
+ QScopedPointer is a small utility class that heavily simplifies this by
+ assigning stack-based memory ownership to heap allocations, more generally
+ called resource acquisition is initialization(RAII).
+
+ QScopedPointer guarantees that the object pointed to will get deleted when
+ the current scope dissapears.
+
+ Consider this function which does heap allocations, and have various exit points:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qscopedpointer.cpp 0
+
+ It's encumbered by the manual delete calls. With QScopedPointer, the code
+ can be simplified to:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qscopedpointer.cpp 1
+
+ The code the compiler generates for QScopedPointer is the same as when
+ writing it manually. Code that makes use of \a delete are candidates for
+ QScopedPointer usage (and if not, possibly another type of smart pointer
+ such as QSharedPointer). QScopedPointer intentionally has no copy
+ constructor or assignment operator, such that ownership and lifetime is
+ clearly communicated.
+
+ The const qualification on a regular C++ pointer can also be expressed with
+ a QScopedPointer:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qscopedpointer.cpp 2
+
+ \section1 Custom cleanup handlers
+
+ Arrays as well as pointers that have been allocated with \c malloc must
+ not be deleted using \c delete. QScopedPointer's second template parameter
+ can be used for custom cleanup handlers.
+
+ The following custom cleanup handlers exist:
+
+ \list
+ \i QScopedPointerDeleter - the default, deletes the pointer using \c delete
+ \i QScopedPointerArrayDeleter - deletes the pointer using \c{delete []}. Use
+ this handler for pointers that were allocated with \c{new []}.
+ \i QScopedPointerPodDeleter - deletes the pointer using \c{free()}. Use this
+ handler for pointers that were allocated with \c{malloc()}.
+ \endlist
+
+ You can pass your own classes as handlers, provided that they have a public
+ static function \c{void cleanup(T *pointer)}.
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qscopedpointer.cpp 5
+
+ \section1 Forward Declared Pointers
+
+ Classes that are forward declared can be used within QScopedPointer, as
+ long as the destructor of the forward declared class is available whenever
+ a QScopedPointer needs to clean up.
+
+ Concretely, this means that all classes containing a QScopedPointer that
+ points to a forward declared class must have non-inline constructors,
+ destructors and assignment operators:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qscopedpointer.cpp 4
+
+ Otherwise, the compiler output a warning about not being able to destruct
+ \c MyPrivateClass.
+
+ \sa QSharedPointer
+*/
+
+/*!
+ \fn QScopedPointer::QScopedPointer(T *p = 0)
+
+ Constructs this QScopedPointer instance and sets its pointer to \a p.
+*/
+
+/*!
+ \fn QScopedPointer::~QScopedPointer()
+
+ Destroys this QScopedPointer object. Delete the object its pointer points
+ to.
+*/
+
+/*!
+ \fn T *QScopedPointer::data() const
+
+ Returns the value of the pointer referenced by this object. QScopedPointer
+ still owns the object pointed to.
+*/
+
+/*!
+ \fn T &QScopedPointer::operator*() const
+
+ Provides access to the scoped pointer's object.
+
+ If the contained pointer is \c null, behavior is undefined.
+ \sa isNull()
+*/
+
+/*!
+ \fn T *QScopedPointer::operator->() const
+
+ Provides access to the scoped pointer's object.
+
+ If the contained pointer is \c null, behavior is undefined.
+
+ \sa isNull()
+*/
+
+/*!
+ \fn QScopedPointer::operator bool() const
+
+ Returns \c true if this object is not \c null. This function is suitable
+ for use in \tt if-constructs, like:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qscopedpointer.cpp 3
+
+ \sa isNull()
+*/
+
+/*!
+ \fn bool QScopedPointer::operator==(const QScopedPointer<T, Cleanup> &other) const
+
+ Equality operator. Returns true if the scoped pointer \a other
+ is pointing to the same object as this pointer, otherwise returns false.
+*/
+
+
+/*!
+ \fn bool QScopedPointer::operator!=(const QScopedPointer<T, Cleanup> &other) const
+
+ Inequality operator. Returns true if the scoped pointer \a other
+ is not pointing to the same object as this pointer, otherwise returns false.
+*/
+
+/*!
+ \fn bool QScopedPointer::isNull() const
+
+ Returns \c true if this object is holding a pointer that is \c null.
+*/
+
+/*!
+ \fn void QScopedPointer::reset(T *other = 0)
+
+ Deletes the existing object it is pointing to if any, and sets its pointer to
+ \a other. QScopedPointer now owns \a other and will delete it in its
+ destructor.
+*/
+
+/*!
+ \fn T *QScopedPointer::take()
+
+ Returns the value of the pointer referenced by this object. The pointer of this
+ QScopedPointer object will be reset to \c null.
+
+ Callers of this function take ownership of the pointer.
+*/
+
+/*! \fn bool QScopedPointer::operator!() const
+
+ Returns \c true if the pointer referenced by this object is \c null, otherwise
+ returns \c false.
+
+ \sa isNull()
+*/
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qscopedpointer.h b/src/corelib/tools/qscopedpointer.h
new file mode 100644
index 0000000000..f801366cbd
--- /dev/null
+++ b/src/corelib/tools/qscopedpointer.h
@@ -0,0 +1,307 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCOPEDPOINTER_H
+#define QSCOPEDPOINTER_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+QT_MODULE(Core)
+
+template <typename T>
+struct QScopedPointerDeleter
+{
+ static inline void cleanup(T *pointer)
+ {
+ // Enforce a complete type.
+ // If you get a compile error here, read the secion on forward declared
+ // classes in the QScopedPointer documentation.
+ typedef char IsIncompleteType[ sizeof(T) ? 1 : -1 ];
+ (void) sizeof(IsIncompleteType);
+
+ delete pointer;
+ }
+};
+
+template <typename T>
+struct QScopedPointerArrayDeleter
+{
+ static inline void cleanup(T *pointer)
+ {
+ // Enforce a complete type.
+ // If you get a compile error here, read the secion on forward declared
+ // classes in the QScopedPointer documentation.
+ typedef char IsIncompleteType[ sizeof(T) ? 1 : -1 ];
+ (void) sizeof(IsIncompleteType);
+
+ delete [] pointer;
+ }
+};
+
+struct QScopedPointerPodDeleter
+{
+ static inline void cleanup(void *pointer) { if (pointer) qFree(pointer); }
+};
+
+template <typename T, typename Cleanup = QScopedPointerDeleter<T> >
+class QScopedPointer
+{
+#ifndef Q_CC_NOKIAX86
+ typedef T *QScopedPointer:: *RestrictedBool;
+#endif
+public:
+ explicit inline QScopedPointer(T *p = 0) : d(p)
+ {
+ }
+
+ inline ~QScopedPointer()
+ {
+ T *oldD = this->d;
+ Cleanup::cleanup(oldD);
+ this->d = 0;
+ }
+
+ inline T &operator*() const
+ {
+ Q_ASSERT(d);
+ return *d;
+ }
+
+ inline T *operator->() const
+ {
+ Q_ASSERT(d);
+ return d;
+ }
+
+ inline bool operator==(const QScopedPointer<T, Cleanup> &other) const
+ {
+ return d == other.d;
+ }
+
+ inline bool operator!=(const QScopedPointer<T, Cleanup> &other) const
+ {
+ return d != other.d;
+ }
+
+ inline bool operator!() const
+ {
+ return !d;
+ }
+
+#if defined(Q_CC_NOKIAX86) || defined(Q_QDOC)
+ inline operator bool() const
+ {
+ return isNull() ? 0 : &QScopedPointer::d;
+ }
+#else
+ inline operator RestrictedBool() const
+ {
+ return isNull() ? 0 : &QScopedPointer::d;
+ }
+#endif
+
+ inline T *data() const
+ {
+ return d;
+ }
+
+ inline bool isNull() const
+ {
+ return !d;
+ }
+
+ inline void reset(T *other = 0)
+ {
+ if (d == other)
+ return;
+ T *oldD = d;
+ d = other;
+ Cleanup::cleanup(oldD);
+ }
+
+ inline T *take()
+ {
+ T *oldD = d;
+ d = 0;
+ return oldD;
+ }
+
+ inline void swap(QScopedPointer<T, Cleanup> &other)
+ {
+ qSwap(d, other.d);
+ }
+
+ typedef T *pointer;
+
+protected:
+ T *d;
+
+private:
+ Q_DISABLE_COPY(QScopedPointer)
+};
+
+template <class T, class Cleanup>
+Q_INLINE_TEMPLATE void qSwap(QScopedPointer<T, Cleanup> &p1, QScopedPointer<T, Cleanup> &p2)
+{ p1.swap(p2); }
+
+template <typename T, typename Cleanup = QScopedPointerArrayDeleter<T> >
+class QScopedArrayPointer : public QScopedPointer<T, Cleanup>
+{
+public:
+ explicit inline QScopedArrayPointer(T *p = 0)
+ : QScopedPointer<T, Cleanup>(p)
+ {
+ }
+
+ inline T &operator[](int i)
+ {
+ return this->d[i];
+ }
+
+ inline const T &operator[](int i) const
+ {
+ return this->d[i];
+ }
+
+ inline bool operator==(const QScopedArrayPointer<T, Cleanup> &other) const
+ {
+ return this->d == other.d;
+ }
+
+ inline bool operator!=(const QScopedArrayPointer<T, Cleanup> &other) const
+ {
+ return this->d != other.d;
+ }
+
+private:
+ Q_DISABLE_COPY(QScopedArrayPointer)
+};
+
+/* Internal helper class - exposes the data through data_ptr (legacy from QShared).
+ Required for some internal Qt classes, do not use otherwise. */
+template <typename T, typename Cleanup = QScopedPointerDeleter<T> >
+class QCustomScopedPointer : public QScopedPointer<T, Cleanup>
+{
+public:
+ explicit inline QCustomScopedPointer(T *p = 0)
+ : QScopedPointer<T, Cleanup>(p)
+ {
+ }
+
+ inline T *&data_ptr()
+ {
+ return this->d;
+ }
+
+ inline bool operator==(const QCustomScopedPointer<T, Cleanup> &other) const
+ {
+ return this->d == other.d;
+ }
+
+ inline bool operator!=(const QCustomScopedPointer<T, Cleanup> &other) const
+ {
+ return this->d != other.d;
+ }
+
+private:
+ Q_DISABLE_COPY(QCustomScopedPointer)
+};
+
+/* Internal helper class - a handler for QShared* classes, to be used in QCustomScopedPointer */
+template <typename T>
+class QScopedPointerSharedDeleter
+{
+public:
+ static inline void cleanup(T *d)
+ {
+ if (d && !d->ref.deref())
+ delete d;
+ }
+};
+
+/* Internal.
+ This class is basically a scoped pointer pointing to a ref-counted object
+ */
+template <typename T>
+class QScopedSharedPointer : public QCustomScopedPointer<T, QScopedPointerSharedDeleter<T> >
+{
+public:
+ explicit inline QScopedSharedPointer(T *p = 0)
+ : QCustomScopedPointer<T, QScopedPointerSharedDeleter<T> >(p)
+ {
+ }
+
+ inline void detach()
+ {
+ qAtomicDetach(this->d);
+ }
+
+ inline void assign(T *other)
+ {
+ if (this->d == other)
+ return;
+ if (other)
+ other->ref.ref();
+ T *oldD = this->d;
+ this->d = other;
+ QScopedPointerSharedDeleter<T>::cleanup(oldD);
+ }
+
+ inline bool operator==(const QScopedSharedPointer<T> &other) const
+ {
+ return this->d == other.d;
+ }
+
+ inline bool operator!=(const QScopedSharedPointer<T> &other) const
+ {
+ return this->d != other.d;
+ }
+
+private:
+ Q_DISABLE_COPY(QScopedSharedPointer)
+};
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QSCOPEDPOINTER_H
diff --git a/src/corelib/tools/qset.h b/src/corelib/tools/qset.h
index 04977823f5..18083d7632 100644
--- a/src/corelib/tools/qset.h
+++ b/src/corelib/tools/qset.h
@@ -85,6 +85,8 @@ public:
inline bool contains(const T &value) const { return q_hash.contains(value); }
+ bool contains(const QSet<T> &set) const;
+
class const_iterator;
class iterator
@@ -274,6 +276,18 @@ Q_INLINE_TEMPLATE QSet<T> &QSet<T>::subtract(const QSet<T> &other)
return *this;
}
+template <class T>
+Q_INLINE_TEMPLATE bool QSet<T>::contains(const QSet<T> &other) const
+{
+ typename QSet<T>::const_iterator i = other.constBegin();
+ while (i != other.constEnd()) {
+ if (!contains(*i))
+ return false;
+ ++i;
+ }
+ return true;
+}
+
template <typename T>
Q_OUTOFLINE_TEMPLATE QList<T> QSet<T>::toList() const
{
diff --git a/src/corelib/tools/qset.qdoc b/src/corelib/tools/qset.qdoc
new file mode 100644
index 0000000000..6e83b43f00
--- /dev/null
+++ b/src/corelib/tools/qset.qdoc
@@ -0,0 +1,953 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QSet
+ \brief The QSet class is a template class that provides a hash-table-based set.
+
+ \ingroup tools
+ \ingroup shared
+ \reentrant
+
+
+ QSet<T> is one of Qt's generic \l{container classes}. It stores
+ values in an unspecified order and provides very fast lookup of
+ the values. Internally, QSet<T> is implemented as a QHash.
+
+ Here's an example QSet with QString values:
+
+ \snippet doc/src/snippets/code/doc_src_qset.qdoc 0
+
+ To insert a value into the set, use insert():
+
+ \snippet doc/src/snippets/code/doc_src_qset.qdoc 1
+
+ Another way to insert items into the set is to use operator<<():
+
+ \snippet doc/src/snippets/code/doc_src_qset.qdoc 2
+
+ To test whether an item belongs to the set or not, use contains():
+
+ \snippet doc/src/snippets/code/doc_src_qset.qdoc 3
+
+ If you want to navigate through all the values stored in a QSet,
+ you can use an iterator. QSet supports both \l{Java-style
+ iterators} (QSetIterator and QMutableSetIterator) and \l{STL-style
+ iterators} (QSet::iterator and QSet::const_iterator). Here's how
+ to iterate over a QSet<QWidget *> using a Java-style iterator:
+
+ \snippet doc/src/snippets/code/doc_src_qset.qdoc 4
+
+ Here's the same code, but using an STL-style iterator:
+
+ \snippet doc/src/snippets/code/doc_src_qset.qdoc 5
+
+ QSet is unordered, so an iterator's sequence cannot be assumed to
+ be predictable. If ordering by key is required, use a QMap.
+
+ To navigate through a QSet, you can also use \l{foreach}:
+
+ \snippet doc/src/snippets/code/doc_src_qset.qdoc 6
+
+ Items can be removed from the set using remove(). There is also a
+ clear() function that removes all items.
+
+ QSet's value data type must be an \l{assignable data type}. You
+ cannot, for example, store a QWidget as a value; instead, store a
+ QWidget *. In addition, the type must provide \c operator==(), and
+ there must also be a global qHash() function that returns a hash
+ value for an argument of the key's type. See the QHash
+ documentation for a list of types supported by qHash().
+
+ Internally, QSet uses a hash table to perform lookups. The hash
+ table automatically grows and shrinks to provide fast lookups
+ without wasting memory. You can still control the size of the hash
+ table by calling reserve(), if you already know approximately how
+ many elements the QSet will contain, but this isn't necessary to
+ obtain good performance. You can also call capacity() to retrieve
+ the hash table's size.
+
+ \sa QSetIterator, QMutableSetIterator, QHash, QMap
+*/
+
+/*!
+ \fn QSet::QSet()
+
+ Constructs an empty set.
+
+ \sa clear()
+*/
+
+/*!
+ \fn QSet::QSet(const QSet<T> &other)
+
+ Constructs a copy of \a other.
+
+ This operation occurs in \l{constant time}, because QSet is
+ \l{implicitly shared}. This makes returning a QSet from a
+ function very fast. If a shared instance is modified, it will be
+ copied (copy-on-write), and this takes \l{linear time}.
+
+ \sa operator=()
+*/
+
+/*!
+ \fn QSet<T> &QSet::operator=(const QSet<T> &other)
+
+ Assigns the \a other set to this set and returns a reference to
+ this set.
+*/
+
+/*!
+ \fn bool QSet::operator==(const QSet<T> &other) const
+
+ Returns true if the \a other set is equal to this set; otherwise
+ returns false.
+
+ Two sets are considered equal if they contain the same elements.
+
+ This function requires the value type to implement \c operator==().
+
+ \sa operator!=()
+*/
+
+/*!
+ \fn bool QSet::operator!=(const QSet<T> &other) const
+
+ Returns true if the \a other set is not equal to this set; otherwise
+ returns false.
+
+ Two sets are considered equal if they contain the same elements.
+
+ This function requires the value type to implement \c operator==().
+
+ \sa operator==()
+*/
+
+/*!
+ \fn int QSet::size() const
+
+ Returns the number of items in the set.
+
+ \sa isEmpty(), count()
+*/
+
+/*!
+ \fn bool QSet::isEmpty() const
+
+ Returns true if the set contains no elements; otherwise returns
+ false.
+
+ \sa size()
+*/
+
+/*!
+ \fn int QSet::capacity() const
+
+ Returns the number of buckets in the set's internal hash
+ table.
+
+ The sole purpose of this function is to provide a means of fine
+ tuning QSet's memory usage. In general, you will rarely ever need
+ to call this function. If you want to know how many items are in
+ the set, call size().
+
+ \sa reserve(), squeeze()
+*/
+
+/*! \fn void QSet::reserve(int size)
+
+ Ensures that the set's internal hash table consists of at
+ least \a size buckets.
+
+ This function is useful for code that needs to build a huge set
+ and wants to avoid repeated reallocation. For example:
+
+ \snippet doc/src/snippets/code/doc_src_qset.qdoc 7
+
+ Ideally, \a size should be slightly more than the maximum number
+ of elements expected in the set. \a size doesn't have to be prime,
+ because QSet will use a prime number internally anyway. If \a size
+ is an underestimate, the worst that will happen is that the QSet
+ will be a bit slower.
+
+ In general, you will rarely ever need to call this function.
+ QSet's internal hash table automatically shrinks or grows to
+ provide good performance without wasting too much memory.
+
+ \sa squeeze(), capacity()
+*/
+
+/*!
+ \fn void QSet::squeeze()
+
+ Reduces the size of the set's internal hash table to save
+ memory.
+
+ The sole purpose of this function is to provide a means of fine
+ tuning QSet's memory usage. In general, you will rarely ever
+ need to call this function.
+
+ \sa reserve(), capacity()
+*/
+
+/*!
+ \fn void QSet::detach()
+
+ \internal
+
+ Detaches this set from any other sets with which it may share
+ data.
+
+ \sa isDetached()
+*/
+
+/*! \fn bool QSet::isDetached() const
+
+ \internal
+
+ Returns true if the set's internal data isn't shared with any
+ other set object; otherwise returns false.
+
+ \sa detach()
+*/
+
+/*!
+ \fn void QSet::setSharable(bool sharable)
+ \internal
+*/
+
+/*!
+ \fn void QSet::clear()
+
+ Removes all elements from the set.
+
+ \sa remove()
+*/
+
+/*!
+ \fn bool QSet::remove(const T &value)
+
+ Removes any occurrence of item \a value from the set. Returns
+ true if an item was actually removed; otherwise returns false.
+
+ \sa contains(), insert()
+*/
+
+/*!
+ \fn QSet::iterator QSet::erase(iterator pos)
+ \since 4.2
+
+ Removes the item at the iterator position \a pos from the set, and
+ returns an iterator positioned at the next item in the set.
+
+ Unlike remove(), this function never causes QSet to rehash its
+ internal data structure. This means that it can safely be called
+ while iterating, and won't affect the order of items in the set.
+
+ \sa remove(), find()
+*/
+
+/*! \fn QSet::const_iterator QSet::find(const T &value) const
+ \since 4.2
+
+ Returns a const iterator positioned at the item \a value in the
+ set. If the set contains no item \a value, the function returns
+ constEnd().
+
+ \sa constFind(), contains()
+*/
+
+/*! \fn QSet::iterator QSet::find(const T &value)
+ \since 4.2
+ \overload
+
+ Returns a non-const iterator positioned at the item \a value in
+ the set. If the set contains no item \a value, the function
+ returns end().
+*/
+
+/*! \fn QSet::const_iterator QSet::constFind(const T &value) const
+ \since 4.2
+
+ Returns a const iterator positioned at the item \a value in the
+ set. If the set contains no item \a value, the function returns
+ constEnd().
+
+ \sa find(), contains()
+*/
+
+/*!
+ \fn bool QSet::contains(const T &value) const
+
+ Returns true if the set contains item \a value; otherwise returns
+ false.
+
+ \sa insert(), remove(), find()
+*/
+
+/*!
+ \fn bool QSet::contains(const QSet<T> &other) const
+ \since 4.6
+
+ Returns true if the set contains all items from the \a other set;
+ otherwise returns false.
+
+ \sa insert(), remove(), find()
+*/
+
+/*! \fn QSet::const_iterator QSet::begin() const
+
+ Returns a const \l{STL-style iterator} positioned at the first
+ item in the set.
+
+ \sa constBegin(), end()
+*/
+
+/*! \fn QSet::iterator QSet::begin()
+ \since 4.2
+ \overload
+
+ Returns a non-const \l{STL-style iterator} positioned at the first
+ item in the set.
+*/
+
+/*! \fn QSet::const_iterator QSet::constBegin() const
+
+ Returns a const \l{STL-style iterator} positioned at the first
+ item in the set.
+
+ \sa begin(), constEnd()
+*/
+
+/*! \fn QSet::const_iterator QSet::end() const
+
+ Returns a const \l{STL-style iterator} positioned at the imaginary
+ item after the last item in the set.
+
+ \sa constEnd(), begin()
+*/
+
+/*! \fn QSet::iterator QSet::end()
+ \since 4.2
+ \overload
+
+ Returns a non-const \l{STL-style iterator} pointing to the
+ imaginary item after the last item in the set.
+*/
+
+/*! \fn QSet::const_iterator QSet::constEnd() const
+
+ Returns a const \l{STL-style iterator} pointing to the imaginary
+ item after the last item in the set.
+
+ \sa constBegin(), end()
+*/
+
+/*!
+ \typedef QSet::Iterator
+ \since 4.2
+
+ Qt-style synonym for QSet::iterator.
+*/
+
+/*!
+ \typedef QSet::ConstIterator
+
+ Qt-style synonym for QSet::const_iterator.
+*/
+
+/*!
+ \typedef QSet::const_pointer
+
+ Typedef for const T *. Provided for STL compatibility.
+*/
+
+/*!
+ \typedef QSet::const_reference
+
+ Typedef for const T &. Provided for STL compatibility.
+*/
+
+/*!
+ \typedef QSet::difference_type
+
+ Typedef for const ptrdiff_t. Provided for STL compatibility.
+*/
+
+/*!
+ \typedef QSet::key_type
+
+ Typedef for T. Provided for STL compatibility.
+*/
+
+/*!
+ \typedef QSet::pointer
+
+ Typedef for T *. Provided for STL compatibility.
+*/
+
+/*!
+ \typedef QSet::reference
+
+ Typedef for T &. Provided for STL compatibility.
+*/
+
+/*!
+ \typedef QSet::size_type
+
+ Typedef for int. Provided for STL compatibility.
+*/
+
+/*!
+ \typedef QSet::value_type
+
+ Typedef for T. Provided for STL compatibility.
+*/
+
+/*!
+ \fn QSet::const_iterator QSet::insert(const T &value)
+
+ Inserts item \a value into the set, if \a value isn't already
+ in the set, and returns an iterator pointing at the inserted
+ item.
+
+ \sa operator<<(), remove(), contains()
+*/
+
+/*!
+ \fn QSet<T> &QSet::unite(const QSet<T> &other)
+
+ Each item in the \a other set that isn't already in this set is
+ inserted into this set. A reference to this set is returned.
+
+ \sa operator|=(), intersect(), subtract()
+*/
+
+/*!
+ \fn QSet<T> &QSet::intersect(const QSet<T> &other)
+
+ Removes all items from this set that are not contained in the
+ \a other set. A reference to this set is returned.
+
+ \sa operator&=(), unite(), subtract()
+*/
+
+/*!
+ \fn QSet<T> &QSet::subtract(const QSet<T> &other)
+
+ Removes all items from this set that are contained in the
+ \a other set. Returns a reference to this set.
+
+ \sa operator-=(), unite(), intersect()
+*/
+
+/*!
+ \fn bool QSet::empty() const
+
+ Returns true if the set is empty. This function is provided
+ for STL compatibility. It is equivalent to isEmpty().
+*/
+
+/*!
+ \fn bool QSet::count() const
+
+ Same as size().
+*/
+
+/*!
+ \fn QSet<T> &QSet::operator<<(const T &value)
+ \fn QSet<T> &QSet::operator+=(const T &value)
+ \fn QSet<T> &QSet::operator|=(const T &value)
+
+ Inserts a new item \a value and returns a reference to the set.
+ If \a value already exists in the set, the set is left unchanged.
+
+ \sa insert()
+*/
+
+/*!
+ \fn QSet<T> &QSet::operator-=(const T &value)
+
+ Removes the occurrence of item \a value from the set, if
+ it is found, and returns a reference to the set. If the
+ \a value is not contained the set, nothing is removed.
+
+ \sa remove()
+*/
+
+/*!
+ \fn QSet<T> &QSet::operator|=(const QSet<T> &other)
+ \fn QSet<T> &QSet::operator+=(const QSet<T> &other)
+
+ Same as unite(\a other).
+
+ \sa operator|(), operator&=(), operator-=()
+*/
+
+/*!
+ \fn QSet<T> &QSet::operator&=(const QSet<T> &other)
+
+ Same as intersect(\a other).
+
+ \sa operator&(), operator|=(), operator-=()
+*/
+
+/*!
+ \fn QSet<T> &QSet::operator&=(const T &value)
+
+ \overload
+
+ Same as intersect(\e{other}), if we consider \e{other} to be a set
+ that contains the singleton \a value.
+*/
+
+
+/*!
+ \fn QSet<T> &QSet::operator-=(const QSet<T> &other)
+
+ Same as subtract(\a{other}).
+
+ \sa operator-(), operator|=(), operator&=()
+*/
+
+/*!
+ \fn QSet<T> QSet::operator|(const QSet<T> &other) const
+ \fn QSet<T> QSet::operator+(const QSet<T> &other) const
+
+ Returns a new QSet that is the union of this set and the
+ \a other set.
+
+ \sa unite(), operator|=(), operator&(), operator-()
+*/
+
+/*!
+ \fn QSet<T> QSet::operator&(const QSet<T> &other) const
+
+ Returns a new QSet that is the intersection of this set and the
+ \a other set.
+
+ \sa intersect(), operator&=(), operator|(), operator-()
+*/
+
+/*!
+ \fn QSet<T> QSet::operator-(const QSet<T> &other) const
+
+ Returns a new QSet that is the set difference of this set and
+ the \a other set, i.e., this set - \a other set.
+
+ \sa subtract(), operator-=(), operator|(), operator&()
+*/
+
+/*!
+ \fn QSet<T> QSet::operator-(const QSet<T> &other)
+ \fn QSet<T> QSet::operator|(const QSet<T> &other)
+ \fn QSet<T> QSet::operator+(const QSet<T> &other)
+ \fn QSet<T> QSet::operator&(const QSet<T> &other)
+ \internal
+
+ These will go away in Qt 5.
+*/
+
+/*!
+ \class QSet::iterator
+ \since 4.2
+ \brief The QSet::iterator class provides an STL-style non-const iterator for QSet.
+
+ QSet features both \l{STL-style iterators} and
+ \l{Java-style iterators}. The STL-style iterators are more
+ low-level and more cumbersome to use; on the other hand, they are
+ slightly faster and, for developers who already know STL, have
+ the advantage of familiarity.
+
+ QSet<T>::iterator allows you to iterate over a QSet and to remove
+ items (using QSet::erase()) while you iterate. (QSet doesn't let
+ you \e modify a value through an iterator, because that
+ would potentially require moving the value in the internal hash
+ table used by QSet.) If you want to iterate over a const QSet,
+ you should use QSet::const_iterator. It is generally good
+ practice to use QSet::const_iterator on a non-const QSet as well,
+ unless you need to change the QSet through the iterator. Const
+ iterators are slightly faster, and can improve code readability.
+
+ QSet\<T\>::iterator allows you to iterate over a QSet\<T\> and
+ modify it as you go (using QSet::erase()). However,
+
+ The default QSet::iterator constructor creates an uninitialized
+ iterator. You must initialize it using a function like
+ QSet::begin(), QSet::end(), or QSet::insert() before you can
+ start iterating. Here's a typical loop that prints all the items
+ stored in a set:
+
+ \snippet doc/src/snippets/code/doc_src_qset.qdoc 8
+
+ Here's a loop that removes certain items (all those that start
+ with 'J') from a set while iterating:
+
+ \snippet doc/src/snippets/code/doc_src_qset.qdoc 9
+
+ STL-style iterators can be used as arguments to \l{generic
+ algorithms}. For example, here's how to find an item in the set
+ using the qFind() algorithm:
+
+ \snippet doc/src/snippets/code/doc_src_qset.qdoc 10
+
+ Multiple iterators can be used on the same set. However, you may
+ not attempt to modify the container while iterating on it.
+
+ \sa QSet::const_iterator, QMutableSetIterator
+*/
+
+/*!
+ \class QSet::const_iterator
+ \brief The QSet::const_iterator class provides an STL-style const iterator for QSet.
+ \since 4.2
+
+ QSet features both \l{STL-style iterators} and
+ \l{Java-style iterators}. The STL-style iterators are more
+ low-level and more cumbersome to use; on the other hand, they are
+ slightly faster and, for developers who already know STL, have
+ the advantage of familiarity.
+
+ QSet\<Key, T\>::const_iterator allows you to iterate over a QSet.
+ If you want to modify the QSet as you iterate over it, you must
+ use QSet::iterator instead. It is generally good practice to use
+ QSet::const_iterator on a non-const QSet as well, unless you need
+ to change the QSet through the iterator. Const iterators are
+ slightly faster, and can improve code readability.
+
+ The default QSet::const_iterator constructor creates an
+ uninitialized iterator. You must initialize it using a function
+ like QSet::begin(), QSet::end(), or QSet::insert() before you can
+ start iterating. Here's a typical loop that prints all the items
+ stored in a set:
+
+ \snippet doc/src/snippets/code/doc_src_qset.qdoc 11
+
+ STL-style iterators can be used as arguments to \l{generic
+ algorithms}. For example, here's how to find an item in the set
+ using the qFind() algorithm:
+
+ \snippet doc/src/snippets/code/doc_src_qset.qdoc 12
+
+ Multiple iterators can be used on the same set. However, you may
+ not attempt to modify the container while iterating on it.
+
+ \sa QSet::iterator, QSetIterator
+*/
+
+/*!
+ \fn QSet::iterator::iterator()
+ \fn QSet::const_iterator::const_iterator()
+
+ Constructs an uninitialized iterator.
+
+ Functions like operator*() and operator++() should not be called
+ on an uninitialized iterator. Use operator=() to assign a value
+ to it before using it.
+
+ \sa QSet::begin(), QSet::end()
+*/
+
+/*!
+ \fn QSet::iterator::iterator(typename Hash::iterator i)
+ \fn QSet::const_iterator::const_iterator(typename Hash::const_iterator i)
+
+ \internal
+*/
+
+/*!
+ \typedef QSet::iterator::iterator_category
+ \typedef QSet::const_iterator::iterator_category
+
+ Synonyms for \e {std::bidirectional_iterator_tag} indicating
+ these iterators are bidirectional iterators.
+ */
+
+/*!
+ \typedef QSet::iterator::difference_type
+ \typedef QSet::const_iterator::difference_type
+
+ \internal
+*/
+
+/*!
+ \typedef QSet::iterator::value_type
+ \typedef QSet::const_iterator::value_type
+
+ \internal
+*/
+
+/*!
+ \typedef QSet::iterator::pointer
+ \typedef QSet::const_iterator::pointer
+
+ \internal
+*/
+
+/*!
+ \typedef QSet::iterator::reference
+ \typedef QSet::const_iterator::reference
+
+ \internal
+*/
+
+/*!
+ \fn QSet::iterator::iterator(const iterator &other)
+ \fn QSet::const_iterator::const_iterator(const const_iterator &other)
+
+ Constructs a copy of \a other.
+*/
+
+/*!
+ \fn QSet::const_iterator::const_iterator(const iterator &other)
+ \since 4.2
+ \overload
+
+ Constructs a copy of \a other.
+*/
+
+/*!
+ \fn QSet::iterator &QSet::iterator::operator=(const iterator &other)
+ \fn QSet::const_iterator &QSet::const_iterator::operator=(const const_iterator &other)
+
+ Assigns \a other to this iterator.
+*/
+
+/*!
+ \fn const T &QSet::iterator::operator*() const
+ \fn const T &QSet::const_iterator::operator*() const
+
+ Returns a reference to the current item.
+
+ \sa operator->()
+*/
+
+/*!
+ \fn const T *QSet::iterator::operator->() const
+ \fn const T *QSet::const_iterator::operator->() const
+
+ Returns a pointer to the current item.
+
+ \sa operator*()
+*/
+
+/*!
+ \fn bool QSet::iterator::operator==(const iterator &other) const
+ \fn bool QSet::const_iterator::operator==(const const_iterator &other) const
+
+ Returns true if \a other points to the same item as this
+ iterator; otherwise returns false.
+
+ \sa operator!=()
+*/
+
+/*!
+ \fn bool QSet::iterator::operator==(const const_iterator &other) const
+ \fn bool QSet::iterator::operator!=(const const_iterator &other) const
+
+ \overload
+*/
+
+/*!
+ \fn bool QSet::iterator::operator!=(const iterator &other) const
+ \fn bool QSet::const_iterator::operator!=(const const_iterator &other) const
+
+ Returns true if \a other points to a different item than this
+ iterator; otherwise returns false.
+
+ \sa operator==()
+*/
+
+/*!
+ \fn QSet::iterator &QSet::iterator::operator++()
+ \fn QSet::const_iterator &QSet::const_iterator::operator++()
+
+ The prefix ++ operator (\c{++it}) advances the iterator to the
+ next item in the set and returns an iterator to the new current
+ item.
+
+ Calling this function on QSet::constEnd() leads to
+ undefined results.
+
+ \sa operator--()
+*/
+
+/*!
+ \fn QSet::iterator QSet::iterator::operator++(int)
+ \fn QSet::const_iterator QSet::const_iterator::operator++(int)
+
+ \overload
+
+ The postfix ++ operator (\c{it++}) advances the iterator to the
+ next item in the set and returns an iterator to the previously
+ current item.
+*/
+
+/*!
+ \fn QSet::iterator &QSet::iterator::operator--()
+ \fn QSet::const_iterator &QSet::const_iterator::operator--()
+
+ The prefix -- operator (\c{--it}) makes the preceding item
+ current and returns an iterator to the new current item.
+
+ Calling this function on QSet::begin() leads to undefined
+ results.
+
+ \sa operator++()
+*/
+
+/*!
+ \fn QSet::iterator QSet::iterator::operator--(int)
+ \fn QSet::const_iterator QSet::const_iterator::operator--(int)
+
+ \overload
+
+ The postfix -- operator (\c{it--}) makes the preceding item
+ current and returns an iterator to the previously current item.
+*/
+
+/*!
+ \fn QSet::iterator QSet::iterator::operator+(int j) const
+ \fn QSet::const_iterator QSet::const_iterator::operator+(int j) const
+
+ Returns an iterator to the item at \a j positions forward from
+ this iterator. (If \a j is negative, the iterator goes backward.)
+
+ This operation can be slow for large \a j values.
+
+ \sa operator-()
+*/
+
+/*!
+ \fn QSet::iterator QSet::iterator::operator-(int j) const
+ \fn QSet::const_iterator QSet::const_iterator::operator-(int j) const
+
+ Returns an iterator to the item at \a j positions backward from
+ this iterator. (If \a j is negative, the iterator goes forward.)
+
+ This operation can be slow for large \a j values.
+
+ \sa operator+()
+*/
+
+/*!
+ \fn QSet::iterator &QSet::iterator::operator+=(int j)
+ \fn QSet::const_iterator &QSet::const_iterator::operator+=(int j)
+
+ Advances the iterator by \a j items. (If \a j is negative, the
+ iterator goes backward.)
+
+ This operation can be slow for large \a j values.
+
+ \sa operator-=(), operator+()
+*/
+
+/*!
+ \fn QSet::iterator &QSet::iterator::operator-=(int j)
+ \fn QSet::const_iterator &QSet::const_iterator::operator-=(int j)
+
+ Makes the iterator go back by \a j items. (If \a j is negative,
+ the iterator goes forward.)
+
+ This operation can be slow for large \a j values.
+
+ \sa operator+=(), operator-()
+*/
+
+/*! \fn QList<T> QSet<T>::toList() const
+
+ Returns a new QList containing the elements in the set. The
+ order of the elements in the QList is undefined.
+
+ Example:
+
+ \snippet doc/src/snippets/code/doc_src_qset.qdoc 13
+
+ \sa fromList(), QList::fromSet(), qSort()
+*/
+
+/*! \fn QList<T> QSet<T>::values() const
+
+ Returns a new QList containing the elements in the set. The
+ order of the elements in the QList is undefined.
+
+ This is the same as toList().
+
+ \sa fromList(), QList::fromSet(), qSort()
+*/
+
+
+/*! \fn QSet<T> QSet<T>::fromList(const QList<T> &list)
+
+ Returns a new QSet object containing the data contained in \a
+ list. Since QSet doesn't allow duplicates, the resulting QSet
+ might be smaller than the \a list, because QList can contain
+ duplicates.
+
+ Example:
+
+ \snippet doc/src/snippets/code/doc_src_qset.qdoc 14
+
+ \sa toList(), QList::toSet()
+*/
+
+/*!
+ \fn QDataStream &operator<<(QDataStream &out, const QSet<T> &set)
+ \relates QSet
+
+ Writes the \a set to stream \a out.
+
+ This function requires the value type to implement \c operator<<().
+
+ \sa \link datastreamformat.html Format of the QDataStream operators \endlink
+*/
+
+/*!
+ \fn QDataStream &operator>>(QDataStream &in, QSet<T> &set)
+ \relates QSet
+
+ Reads a set from stream \a in into \a set.
+
+ This function requires the value type to implement \c operator>>().
+
+ \sa \link datastreamformat.html Format of the QDataStream operators \endlink
+*/
diff --git a/src/corelib/tools/qshareddata.cpp b/src/corelib/tools/qshareddata.cpp
index 3cb11bdd47..3d1a33946a 100644
--- a/src/corelib/tools/qshareddata.cpp
+++ b/src/corelib/tools/qshareddata.cpp
@@ -44,507 +44,512 @@
QT_BEGIN_NAMESPACE
/*!
- \class QSharedData
- \brief The QSharedData class is a base class for shared data objects.
- \reentrant
- \ingroup misc
+ \class QSharedData
+ \brief The QSharedData class is a base class for shared data objects.
+ \reentrant
- QSharedData is designed to be used with QSharedDataPointer or
- QExplicitlySharedDataPointer to implement custom \l{implicitly
- shared} or \l {explicitly shared} classes. QSharedData provides
- \l{thread-safe} reference counting.
+ QSharedData is designed to be used with QSharedDataPointer or
+ QExplicitlySharedDataPointer to implement custom \l{implicitly
+ shared} or explicitly shared classes. QSharedData provides
+ \l{thread-safe} reference counting.
- See QSharedDataPointer and QExplicitlySharedDataPointer for details.
+ See QSharedDataPointer and QExplicitlySharedDataPointer for details.
*/
/*! \fn QSharedData::QSharedData()
- Constructs a QSharedData object with a reference count of 0.
+ Constructs a QSharedData object with a reference count of 0.
*/
/*! \fn QSharedData::QSharedData(const QSharedData& other)
- Constructs a QSharedData object with reference count 0.
- \a other is ignored.
+ Constructs a QSharedData object with reference count 0.
+ \a other is ignored.
*/
/*!
- \class QSharedDataPointer
- \brief The QSharedDataPointer class represents a pointer to an implicitly shared object.
- \since 4.0
- \reentrant
- \ingroup misc
- \mainclass
+ \class QSharedDataPointer
+ \brief The QSharedDataPointer class represents a pointer to an implicitly shared object.
+ \since 4.0
+ \reentrant
- QSharedDataPointer\<T\> makes writing your own \l {implicitly
- shared} classes easy. QSharedDataPointer implements \l {thread-safe}
- reference counting, ensuring that adding QSharedDataPointers to your
- \l {reentrant} classes won't make them non-reentrant.
+ QSharedDataPointer\<T\> makes writing your own \l {implicitly
+ shared} classes easy. QSharedDataPointer implements \l {thread-safe}
+ reference counting, ensuring that adding QSharedDataPointers to your
+ \l {reentrant} classes won't make them non-reentrant.
- \l {Implicit sharing} is used by many Qt classes to combine the
- speed and memory efficiency of pointers with the ease of use of
- classes. See the \l{Shared Classes} page for more information.
+ \l {Implicit sharing} is used by many Qt classes to combine the
+ speed and memory efficiency of pointers with the ease of use of
+ classes. See the \l{Shared Classes} page for more information.
- \target Employee example
- Suppose you want to make an \c Employee class implicitly shared. The
- procedure is:
+ \target Employee example
+ Suppose you want to make an \c Employee class implicitly shared. The
+ procedure is:
- \list
+ \list
- \o Define the class \c Employee to have a single data member of
+ \o Define the class \c Employee to have a single data member of
type \c {QSharedDataPointer<EmployeeData>}.
- \o Define the \c EmployeeData class derived from \l QSharedData to
+ \o Define the \c EmployeeData class derived from \l QSharedData to
contain all the data members you would normally have put in the
\c Employee class.
- \endlist
-
- To show this in practice, we review the source code for the
- implicitly shared \c Employee class. In the header file we define the
- two classes \c Employee and \c EmployeeData.
-
- \snippet doc/src/snippets/sharedemployee/employee.h 0
-
- In class \c Employee, note the single data member, a \e {d pointer}
- of type \c {QSharedDataPointer<EmployeeData>}. All accesses of
- employee data must go through the \e {d pointer's} \c
- {operator->()}. For write accesses, \c {operator->()} will
- automatically call detach(), which creates a copy of the shared data
- object if the shared data object's reference count is greater than
- 1. This ensures that writes to one \c Employee object don't affect
- any other \c Employee objects that share the same \c EmployeeData
- object.
-
- Class \c EmployeeData inherits QSharedData, which provides the
- \e{behind the scenes} reference counter. \c EmployeeData has a default
- constructor, a copy constructor, and a destructor. Normally, trivial
- implementations of these are all that is needed in the \e {data}
- class for an implicitly shared class.
-
- Implementing the two constructors for class \c Employee is also
- straightforward. Both create a new instance of \c EmployeeData
- and assign it to the \e{d pointer} .
-
- \snippet doc/src/snippets/sharedemployee/employee.h 1
- \codeline
- \snippet doc/src/snippets/sharedemployee/employee.h 2
-
- Note that class \c Employee also has a trivial copy constructor
- defined, which is not strictly required in this case.
-
- \snippet doc/src/snippets/sharedemployee/employee.h 7
-
- The copy constructor is not strictly required here, because class \c
- EmployeeData is included in the same file as class \c Employee
- (\c{employee.h}). However, including the private subclass of
- QSharedData in the same file as the public class containing the
- QSharedDataPointer is not typical. Normally, the idea is to hide the
- private subclass of QSharedData from the user by putting it in a
- separate file which would not be included in the public file. In
- this case, we would normally put class \c EmployeeData in a separate
- file, which would \e{not} be included in \c{employee.h}. Instead, we
- would just predeclare the private subclass \c EmployeeData in \c
- {employee.h} this way:
-
- \code
- class EmployeeData;
- \endcode
-
- If we had done it that way here, the copy constructor shown would be
- required. Since the copy constructor is trivial, you might as well
- just always include it.
-
- Behind the scenes, QSharedDataPointer automatically increments the
- reference count whenever an \c Employee object is copied, assigned,
- or passed as a parameter. It decrements the reference count whenever
- an \c Employee object is deleted or goes out of scope. The shared
- \c EmployeeData object is deleted automatically if and when the
- reference count reaches 0.
-
- In a non-const member function of \c Employee, whenever the \e {d
- pointer} is dereferenced, QSharedDataPointer automatically calls
- detach() to ensure that the function operates on its own copy of the
- data.
-
- \snippet doc/src/snippets/sharedemployee/employee.h 3
- \codeline
- \snippet doc/src/snippets/sharedemployee/employee.h 4
-
- Note that if detach() is called more than once in a member function
- due to multiple dereferences of the \e {d pointer}, detach() will
- only create a copy of the shared data the first time it is called,
- if at all, because on the second and subsequent calls of detach(),
- the reference count will be 1 again.
-
- But note that in the second \c Employee constructor, which takes an
- employee ID and a name, both setId() and setName() are called, but
- they don't cause \e{copy on write}, because the reference count for
- the newly constructed \c EmployeeData object has just been set to 1.
-
- In \c Employee's \e const member functions, dereferencing the \e {d
- pointer} does \e not cause detach() to be called.
-
- \snippet doc/src/snippets/sharedemployee/employee.h 5
- \codeline
- \snippet doc/src/snippets/sharedemployee/employee.h 6
-
- Notice that there is no need to implement a copy constructor or an
- assignment operator for the \c Employee class, because the copy
- constructor and assignment operator provided by the C++ compiler
- will do the \e{member by member} shallow copy required. The only
- member to copy is the \e {d pointer}, which is a QSharedDataPointer,
- whose \c {operator=()} just increments the reference count of the
- shared \c EmployeeData object.
-
- \target Implicit vs Explicit Sharing
- \section1 Implicit vs Explicit Sharing
-
- Implicit sharing might not be right for the \c Employee class.
- Consider a simple example that creates two instances of the
- implicitly shared \c Employee class.
-
- \snippet doc/src/snippets/sharedemployee/main.cpp 0
-
- After the second employee e2 is created and e1 is assigned to it,
- both \c e1 and \c e2 refer to Albrecht Durer, employee 1001. Both \c
- Employee objects point to the same instance of \c EmployeeData,
- which has reference count 2. Then \c {e1.setName("Hans Holbein")} is
- called to change the employee name, but because the reference count
- is greater than 1, a \e{copy on write} is performed before the name
- is changed. Now \c e1 and \c e2 point to different \c EmployeeData
- objects. They have different names, but both have ID 1001, which is
- probably not what you want. You can, of course, just continue with
- \c {e1.setId(1002)}, if you really mean to create a second, unique
- employee, but if you only want to change the employee's name
- everywhere, consider using \l {QExplicitlySharedDataPointer}
- {explicit sharing} in the \c Employee class instead of implicit
- sharing.
-
- If you declare the \e {d pointer} in the \c Employee class to be
- \c {QExplicitlySharedDataPointer<EmployeeData>}, then explicit
- sharing is used and \e{copy on write} operations are not performed
- automatically (i.e. detach() is not called in non-const
- functions). In that case, after \c {e1.setName("Hans Holbein")}, the
- employee's name has been changed, but both e1 and e2 still refer to
- the same instance of \c EmployeeData, so there is only one employee
- with ID 1001.
-
- In the member function documentation, \e{d pointer} always refers
- to the internal pointer to the shared data object.
-
- \sa QSharedData, QExplicitlySharedDataPointer
+ \endlist
+
+ To show this in practice, we review the source code for the
+ implicitly shared \c Employee class. In the header file we define the
+ two classes \c Employee and \c EmployeeData.
+
+ \snippet doc/src/snippets/sharedemployee/employee.h 0
+
+ In class \c Employee, note the single data member, a \e {d pointer}
+ of type \c {QSharedDataPointer<EmployeeData>}. All accesses of
+ employee data must go through the \e {d pointer's} \c
+ {operator->()}. For write accesses, \c {operator->()} will
+ automatically call detach(), which creates a copy of the shared data
+ object if the shared data object's reference count is greater than
+ 1. This ensures that writes to one \c Employee object don't affect
+ any other \c Employee objects that share the same \c EmployeeData
+ object.
+
+ Class \c EmployeeData inherits QSharedData, which provides the
+ \e{behind the scenes} reference counter. \c EmployeeData has a default
+ constructor, a copy constructor, and a destructor. Normally, trivial
+ implementations of these are all that is needed in the \e {data}
+ class for an implicitly shared class.
+
+ Implementing the two constructors for class \c Employee is also
+ straightforward. Both create a new instance of \c EmployeeData
+ and assign it to the \e{d pointer} .
+
+ \snippet doc/src/snippets/sharedemployee/employee.h 1
+ \codeline
+ \snippet doc/src/snippets/sharedemployee/employee.h 2
+
+ Note that class \c Employee also has a trivial copy constructor
+ defined, which is not strictly required in this case.
+
+ \snippet doc/src/snippets/sharedemployee/employee.h 7
+
+ The copy constructor is not strictly required here, because class \c
+ EmployeeData is included in the same file as class \c Employee
+ (\c{employee.h}). However, including the private subclass of
+ QSharedData in the same file as the public class containing the
+ QSharedDataPointer is not typical. Normally, the idea is to hide the
+ private subclass of QSharedData from the user by putting it in a
+ separate file which would not be included in the public file. In
+ this case, we would normally put class \c EmployeeData in a separate
+ file, which would \e{not} be included in \c{employee.h}. Instead, we
+ would just predeclare the private subclass \c EmployeeData in \c
+ {employee.h} this way:
+
+ \code
+ class EmployeeData;
+ \endcode
+
+ If we had done it that way here, the copy constructor shown would be
+ required. Since the copy constructor is trivial, you might as well
+ just always include it.
+
+ Behind the scenes, QSharedDataPointer automatically increments the
+ reference count whenever an \c Employee object is copied, assigned,
+ or passed as a parameter. It decrements the reference count whenever
+ an \c Employee object is deleted or goes out of scope. The shared
+ \c EmployeeData object is deleted automatically if and when the
+ reference count reaches 0.
+
+ In a non-const member function of \c Employee, whenever the \e {d
+ pointer} is dereferenced, QSharedDataPointer automatically calls
+ detach() to ensure that the function operates on its own copy of the
+ data.
+
+ \snippet doc/src/snippets/sharedemployee/employee.h 3
+ \codeline
+ \snippet doc/src/snippets/sharedemployee/employee.h 4
+
+ Note that if detach() is called more than once in a member function
+ due to multiple dereferences of the \e {d pointer}, detach() will
+ only create a copy of the shared data the first time it is called,
+ if at all, because on the second and subsequent calls of detach(),
+ the reference count will be 1 again.
+
+ But note that in the second \c Employee constructor, which takes an
+ employee ID and a name, both setId() and setName() are called, but
+ they don't cause \e{copy on write}, because the reference count for
+ the newly constructed \c EmployeeData object has just been set to 1.
+
+ In \c Employee's \e const member functions, dereferencing the \e {d
+ pointer} does \e not cause detach() to be called.
+
+ \snippet doc/src/snippets/sharedemployee/employee.h 5
+ \codeline
+ \snippet doc/src/snippets/sharedemployee/employee.h 6
+
+ Notice that there is no need to implement a copy constructor or an
+ assignment operator for the \c Employee class, because the copy
+ constructor and assignment operator provided by the C++ compiler
+ will do the \e{member by member} shallow copy required. The only
+ member to copy is the \e {d pointer}, which is a QSharedDataPointer,
+ whose \c {operator=()} just increments the reference count of the
+ shared \c EmployeeData object.
+
+ \target Implicit vs Explicit Sharing
+ \section1 Implicit vs Explicit Sharing
+
+ Implicit sharing might not be right for the \c Employee class.
+ Consider a simple example that creates two instances of the
+ implicitly shared \c Employee class.
+
+ \snippet doc/src/snippets/sharedemployee/main.cpp 0
+
+ After the second employee e2 is created and e1 is assigned to it,
+ both \c e1 and \c e2 refer to Albrecht Durer, employee 1001. Both \c
+ Employee objects point to the same instance of \c EmployeeData,
+ which has reference count 2. Then \c {e1.setName("Hans Holbein")} is
+ called to change the employee name, but because the reference count
+ is greater than 1, a \e{copy on write} is performed before the name
+ is changed. Now \c e1 and \c e2 point to different \c EmployeeData
+ objects. They have different names, but both have ID 1001, which is
+ probably not what you want. You can, of course, just continue with
+ \c {e1.setId(1002)}, if you really mean to create a second, unique
+ employee, but if you only want to change the employee's name
+ everywhere, consider using \l {QExplicitlySharedDataPointer}
+ {explicit sharing} in the \c Employee class instead of implicit
+ sharing.
+
+ If you declare the \e {d pointer} in the \c Employee class to be
+ \c {QExplicitlySharedDataPointer<EmployeeData>}, then explicit
+ sharing is used and \e{copy on write} operations are not performed
+ automatically (i.e. detach() is not called in non-const
+ functions). In that case, after \c {e1.setName("Hans Holbein")}, the
+ employee's name has been changed, but both e1 and e2 still refer to
+ the same instance of \c EmployeeData, so there is only one employee
+ with ID 1001.
+
+ In the member function documentation, \e{d pointer} always refers
+ to the internal pointer to the shared data object.
+
+ \sa QSharedData, QExplicitlySharedDataPointer, QScopedPointer, QSharedPointer
*/
/*! \fn T& QSharedDataPointer::operator*()
- Provides access to the shared data object's members.
- This function calls detach().
+ Provides access to the shared data object's members.
+ This function calls detach().
*/
/*! \fn const T& QSharedDataPointer::operator*() const
- Provides const access to the shared data object's members.
- This function does \e not call detach().
+ Provides const access to the shared data object's members.
+ This function does \e not call detach().
*/
/*! \fn T* QSharedDataPointer::operator->()
- Provides access to the shared data object's members.
- This function calls detach().
+ Provides access to the shared data object's members.
+ This function calls detach().
*/
/*! \fn const T* QSharedDataPointer::operator->() const
- Provides const access to the shared data object's members.
- This function does \e not call detach().
+ Provides const access to the shared data object's members.
+ This function does \e not call detach().
*/
/*! \fn QSharedDataPointer::operator T*()
- Returns a pointer to the shared data object.
- This function calls detach().
+ Returns a pointer to the shared data object.
+ This function calls detach().
- \sa data(), constData()
+ \sa data(), constData()
*/
/*! \fn QSharedDataPointer::operator const T*() const
- Returns a pointer to the shared data object.
- This function does \e not call detach().
+ Returns a pointer to the shared data object.
+ This function does \e not call detach().
*/
/*! \fn T* QSharedDataPointer::data()
- Returns a pointer to the shared data object.
- This function calls detach().
+ Returns a pointer to the shared data object.
+ This function calls detach().
- \sa constData()
+ \sa constData()
*/
/*! \fn const T* QSharedDataPointer::data() const
- Returns a pointer to the shared data object.
- This function does \e not call detach().
+ Returns a pointer to the shared data object.
+ This function does \e not call detach().
*/
/*! \fn const T* QSharedDataPointer::constData() const
- Returns a const pointer to the shared data object.
- This function does \e not call detach().
+ Returns a const pointer to the shared data object.
+ This function does \e not call detach().
- \sa data()
+ \sa data()
*/
+/*! \fn void QSharedDataPointer::swap(QSharedDataPointer &other)
+ Swap this instance's shared data pointer with the shared
+ data pointer in \a other.
+ */
+
/*! \fn bool QSharedDataPointer::operator==(const QSharedDataPointer<T>& other) const
- Returns true if \a other and \e this have the same \e{d pointer}.
- This function does \e not call detach().
+ Returns true if \a other and \e this have the same \e{d pointer}.
+ This function does \e not call detach().
*/
/*! \fn bool QSharedDataPointer::operator!=(const QSharedDataPointer<T>& other) const
- Returns true if \a other and \e this do \e not have the same
- \e{d pointer}. This function does \e not call detach().
+ Returns true if \a other and \e this do \e not have the same
+ \e{d pointer}. This function does \e not call detach().
*/
/*! \fn QSharedDataPointer::QSharedDataPointer()
- Constructs a QSharedDataPointer initialized with a null \e{d pointer}.
+ Constructs a QSharedDataPointer initialized with a null \e{d pointer}.
*/
/*! \fn QSharedDataPointer::~QSharedDataPointer()
- Decrements the reference count of the shared data object.
- If the reference count becomes 0, the shared data object
- is deleted. \e This is then destroyed.
+ Decrements the reference count of the shared data object.
+ If the reference count becomes 0, the shared data object
+ is deleted. \e This is then destroyed.
*/
/*! \fn QSharedDataPointer::QSharedDataPointer(T* sharedData)
- Constructs a QSharedDataPointer with \e{d pointer} set to
- \a sharedData and increments \a{sharedData}'s reference count.
+ Constructs a QSharedDataPointer with \e{d pointer} set to
+ \a sharedData and increments \a{sharedData}'s reference count.
*/
/*! \fn QSharedDataPointer::QSharedDataPointer(const QSharedDataPointer<T>& other)
- Sets the \e{d pointer} of \e this to the \e{d pointer} in
- \a other and increments the reference count of the shared
- data object.
+ Sets the \e{d pointer} of \e this to the \e{d pointer} in
+ \a other and increments the reference count of the shared
+ data object.
*/
/*! \fn QSharedDataPointer<T>& QSharedDataPointer::operator=(const QSharedDataPointer<T>& other)
- Sets the \e{d pointer} of \e this to the \e{d pointer} of
- \a other and increments the reference count of the shared
- data object. The reference count of the old shared data
- object of \e this is decremented. If the reference count
- of the old shared data object becomes 0, the old shared
- data object is deleted.
+ Sets the \e{d pointer} of \e this to the \e{d pointer} of
+ \a other and increments the reference count of the shared
+ data object. The reference count of the old shared data
+ object of \e this is decremented. If the reference count
+ of the old shared data object becomes 0, the old shared
+ data object is deleted.
*/
/*! \fn QSharedDataPointer& QSharedDataPointer::operator=(T* sharedData)
- Sets the \e{d pointer} og \e this to \a sharedData and increments
- \a{sharedData}'s reference count. The reference count of the old
- shared data object of \e this is decremented. If the reference
- count of the old shared data object becomes 0, the old shared data
- object is deleted.
+ Sets the \e{d pointer} og \e this to \a sharedData and increments
+ \a{sharedData}'s reference count. The reference count of the old
+ shared data object of \e this is decremented. If the reference
+ count of the old shared data object becomes 0, the old shared data
+ object is deleted.
*/
/*! \fn bool QSharedDataPointer::operator!() const
- Returns true if the \e{d pointer} of \e this is null.
+ Returns true if the \e{d pointer} of \e this is null.
*/
/*! \fn void QSharedDataPointer::detach()
- If the shared data object's reference count is greater than 1, this
- function creates a deep copy of the shared data object and sets the
- \e{d pointer} of \e this to the copy.
-
- This function is called automatically by non-const member
- functions of QSharedDataPointer if \e{copy on write} is
- required. You don't need to call it yourself.
+ If the shared data object's reference count is greater than 1, this
+ function creates a deep copy of the shared data object and sets the
+ \e{d pointer} of \e this to the copy.
+
+ This function is called automatically by non-const member
+ functions of QSharedDataPointer if \e{copy on write} is
+ required. You don't need to call it yourself.
*/
/*! \fn T *QSharedDataPointer::clone()
\since 4.5
- Creates and returns a deep copy of the current data. This function
- is called by detach() when the reference count is greater than 1 in
- order to create the new copy. This function uses the \e {operator
- new} and calls the copy constructor of the type T.
+ Creates and returns a deep copy of the current data. This function
+ is called by detach() when the reference count is greater than 1 in
+ order to create the new copy. This function uses the \e {operator
+ new} and calls the copy constructor of the type T.
- This function is provided so that you may support "virtual copy
- constructors" for your own types. In order to so, you should declare
- a template-specialization of this function for your own type, like
- the example below:
+ This function is provided so that you may support "virtual copy
+ constructors" for your own types. In order to so, you should declare
+ a template-specialization of this function for your own type, like
+ the example below:
- \code
+ \code
template<>
EmployeeData *QSharedDataPointer<EmployeeData>::clone()
{
return d->clone();
}
- \endcode
+ \endcode
- In the example above, the template specialization for the clone()
- function calls the \e {EmployeeData::clone()} virtual function. A
- class derived from EmployeeData could override that function and
- return the proper polymorphic type.
+ In the example above, the template specialization for the clone()
+ function calls the \e {EmployeeData::clone()} virtual function. A
+ class derived from EmployeeData could override that function and
+ return the proper polymorphic type.
*/
/*!
- \class QExplicitlySharedDataPointer
- \brief The QExplicitlySharedDataPointer class represents a pointer to an explicitly shared object.
- \since 4.4
- \reentrant
- \ingroup misc
- \mainclass
-
- QExplicitlySharedDataPointer\<T\> makes writing your own explicitly
- shared classes easy. QExplicitlySharedDataPointer implements
- \l {thread-safe} reference counting, ensuring that adding
- QExplicitlySharedDataPointers to your \l {reentrant} classes won't
- make them non-reentrant.
-
- Except for one big difference, QExplicitlySharedDataPointer is just
- like QSharedDataPointer. The big difference is that member functions
- of QExplicitlySharedDataPointer \e{do not} do the automatic
- \e{copy on write} operation (detach()) that non-const members of
- QSharedDataPointer do before allowing the shared data object to be
- modified. There is a detach() function available, but if you really
- want to detach(), you have to call it yourself. This means that
- QExplicitlySharedDataPointers behave like regular C++ pointers,
- except that by doing reference counting and not deleting the shared
- data object until the reference count is 0, they avoid the dangling
- pointer problem.
-
- It is instructive to compare QExplicitlySharedDataPointer with
- QSharedDataPointer by way of an example. Consider the \l {Employee
- example} in QSharedDataPointer, modified to use explicit sharing as
- explained in the discussion \l {Implicit vs Explicit Sharing}.
-
- Note that if you use this class but find you are calling detach() a
- lot, you probably should be using QSharedDataPointer instead.
-
- In the member function documentation, \e{d pointer} always refers
- to the internal pointer to the shared data object.
-
- \sa QSharedData, QSharedDataPointer
+ \class QExplicitlySharedDataPointer
+ \brief The QExplicitlySharedDataPointer class represents a pointer to an explicitly shared object.
+ \since 4.4
+ \reentrant
+
+ QExplicitlySharedDataPointer\<T\> makes writing your own explicitly
+ shared classes easy. QExplicitlySharedDataPointer implements
+ \l {thread-safe} reference counting, ensuring that adding
+ QExplicitlySharedDataPointers to your \l {reentrant} classes won't
+ make them non-reentrant.
+
+ Except for one big difference, QExplicitlySharedDataPointer is just
+ like QSharedDataPointer. The big difference is that member functions
+ of QExplicitlySharedDataPointer \e{do not} do the automatic
+ \e{copy on write} operation (detach()) that non-const members of
+ QSharedDataPointer do before allowing the shared data object to be
+ modified. There is a detach() function available, but if you really
+ want to detach(), you have to call it yourself. This means that
+ QExplicitlySharedDataPointers behave like regular C++ pointers,
+ except that by doing reference counting and not deleting the shared
+ data object until the reference count is 0, they avoid the dangling
+ pointer problem.
+
+ It is instructive to compare QExplicitlySharedDataPointer with
+ QSharedDataPointer by way of an example. Consider the \l {Employee
+ example} in QSharedDataPointer, modified to use explicit sharing as
+ explained in the discussion \l {Implicit vs Explicit Sharing}.
+
+ Note that if you use this class but find you are calling detach() a
+ lot, you probably should be using QSharedDataPointer instead.
+
+ In the member function documentation, \e{d pointer} always refers
+ to the internal pointer to the shared data object.
+
+ \sa QSharedData, QSharedDataPointer
*/
/*! \fn T& QExplicitlySharedDataPointer::operator*() const
- Provides access to the shared data object's members.
+ Provides access to the shared data object's members.
*/
/*! \fn T* QExplicitlySharedDataPointer::operator->()
- Provides access to the shared data object's members.
+ Provides access to the shared data object's members.
*/
/*! \fn const T* QExplicitlySharedDataPointer::operator->() const
- Provides const access to the shared data object's members.
+ Provides const access to the shared data object's members.
*/
/*! \fn T* QExplicitlySharedDataPointer::data() const
- Returns a pointer to the shared data object.
+ Returns a pointer to the shared data object.
*/
/*! \fn const T* QExplicitlySharedDataPointer::constData() const
- Returns a const pointer to the shared data object.
+ Returns a const pointer to the shared data object.
- \sa data()
+ \sa data()
*/
+/*! \fn void QExplicitlySharedDataPointer::swap(QExplicitlySharedDataPointer &other)
+ Swap this instance's explicitly shared data pointer with
+ the explicitly shared data pointer in \a other.
+ */
+
/*! \fn bool QExplicitlySharedDataPointer::operator==(const QExplicitlySharedDataPointer<T>& other) const
- Returns true if \a other and \e this have the same \e{d pointer}.
+ Returns true if \a other and \e this have the same \e{d pointer}.
*/
/*! \fn bool QExplicitlySharedDataPointer::operator==(const T* ptr) const
- Returns true if the \e{d pointer} of \e this is \a ptr.
+ Returns true if the \e{d pointer} of \e this is \a ptr.
*/
/*! \fn bool QExplicitlySharedDataPointer::operator!=(const QExplicitlySharedDataPointer<T>& other) const
- Returns true if \a other and \e this do \e not have the same
- \e{d pointer}.
+ Returns true if \a other and \e this do \e not have the same
+ \e{d pointer}.
*/
/*! \fn bool QExplicitlySharedDataPointer::operator!=(const T* ptr) const
- Returns true if the \e{d pointer} of \e this is \e not \a ptr.
+ Returns true if the \e{d pointer} of \e this is \e not \a ptr.
*/
/*! \fn QExplicitlySharedDataPointer::QExplicitlySharedDataPointer()
- Constructs a QExplicitlySharedDataPointer initialized with a null
- \e{d pointer}.
+ Constructs a QExplicitlySharedDataPointer initialized with a null
+ \e{d pointer}.
*/
/*! \fn QExplicitlySharedDataPointer::~QExplicitlySharedDataPointer()
- Decrements the reference count of the shared data object.
- If the reference count becomes 0, the shared data object
- is deleted. \e This is then destroyed.
+ Decrements the reference count of the shared data object.
+ If the reference count becomes 0, the shared data object
+ is deleted. \e This is then destroyed.
*/
/*! \fn QExplicitlySharedDataPointer::QExplicitlySharedDataPointer(T* sharedData)
- Constructs a QExplicitlySharedDataPointer with \e{d pointer}
- set to \a sharedData and increments \a{sharedData}'s reference
- count.
+ Constructs a QExplicitlySharedDataPointer with \e{d pointer}
+ set to \a sharedData and increments \a{sharedData}'s reference
+ count.
*/
/*! \fn QExplicitlySharedDataPointer::QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<T>& other)
- This standard copy constructor sets the \e {d pointer} of \e this to
- the \e {d pointer} in \a other and increments the reference count of
- the shared data object.
+ This standard copy constructor sets the \e {d pointer} of \e this to
+ the \e {d pointer} in \a other and increments the reference count of
+ the shared data object.
*/
/*! \fn QExplicitlySharedDataPointer::QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<X>& other)
- This copy constructor is different in that it allows \a other to be
- a different type of explicitly shared data pointer but one that has
- a compatible shared data object. It performs a static cast of the
- \e{d pointer} in \a other and sets the \e {d pointer} of \e this to
- the converted \e{d pointer}. It increments the reference count of
- the shared data object.
- */
+ This copy constructor is different in that it allows \a other to be
+ a different type of explicitly shared data pointer but one that has
+ a compatible shared data object. It performs a static cast of the
+ \e{d pointer} in \a other and sets the \e {d pointer} of \e this to
+ the converted \e{d pointer}. It increments the reference count of
+ the shared data object.
+*/
/*! \fn QExplicitlySharedDataPointer<T>& QExplicitlySharedDataPointer::operator=(const QExplicitlySharedDataPointer<T>& other)
- Sets the \e{d pointer} of \e this to the \e{d pointer} of
- \a other and increments the reference count of the shared
- data object. The reference count of the old shared data
- object of \e this is decremented. If the reference count
- of the old shared data object becomes 0, the old shared
- data object is deleted.
+ Sets the \e{d pointer} of \e this to the \e{d pointer} of
+ \a other and increments the reference count of the shared
+ data object. The reference count of the old shared data
+ object of \e this is decremented. If the reference count
+ of the old shared data object becomes 0, the old shared
+ data object is deleted.
*/
/*! \fn QExplicitlySharedDataPointer& QExplicitlySharedDataPointer::operator=(T* sharedData)
- Sets the \e{d pointer} of \e this to \a sharedData and
- increments \a{sharedData}'s reference count. The reference
- count of the old shared data object of \e this is decremented.
- If the reference count of the old shared data object becomes
- 0, the old shared data object is deleted.
+ Sets the \e{d pointer} of \e this to \a sharedData and
+ increments \a{sharedData}'s reference count. The reference
+ count of the old shared data object of \e this is decremented.
+ If the reference count of the old shared data object becomes
+ 0, the old shared data object is deleted.
*/
/*! \fn void QExplicitlySharedDataPointer::reset()
- Resets \e this to be null. i.e., this function sets the
- \e{d pointer} of \e this to 0, but first it decrements
- the reference count of the shared data object and deletes
- the shared data object if the reference count became 0.
+ Resets \e this to be null. i.e., this function sets the
+ \e{d pointer} of \e this to 0, but first it decrements
+ the reference count of the shared data object and deletes
+ the shared data object if the reference count became 0.
*/
/*! \fn QExplicitlySharedDataPointer::operator bool () const
- Returns true if the \e{d pointer} of \e this is \e not null.
+ Returns true if the \e{d pointer} of \e this is \e not null.
*/
/*! \fn bool QExplicitlySharedDataPointer::operator!() const
- Returns true if the \e{d pointer} of \e this is null.
+ Returns true if the \e{d pointer} of \e this is null.
*/
/*! \fn void QExplicitlySharedDataPointer::detach()
- If the shared data object's reference count is greater than 1, this
- function creates a deep copy of the shared data object and sets the
- \e{d pointer} of \e this to the copy.
+ If the shared data object's reference count is greater than 1, this
+ function creates a deep copy of the shared data object and sets the
+ \e{d pointer} of \e this to the copy.
- Because QExplicitlySharedDataPointer does not do the automatic
- \e{copy on write} operations that members of QSharedDataPointer do,
- detach() is \e not called automatically anywhere in the member
- functions of this class. If you find that you are calling detach()
- everywhere in your code, consider using QSharedDataPointer instead.
+ Because QExplicitlySharedDataPointer does not do the automatic
+ \e{copy on write} operations that members of QSharedDataPointer do,
+ detach() is \e not called automatically anywhere in the member
+ functions of this class. If you find that you are calling detach()
+ everywhere in your code, consider using QSharedDataPointer instead.
*/
/*! \fn T *QExplicitlySharedDataPointer::clone()
\since 4.5
- Creates and returns a deep copy of the current data. This function
- is called by detach() when the reference count is greater than 1 in
- order to create the new copy. This function uses the \e {operator
- new} and calls the copy constructor of the type T.
+ Creates and returns a deep copy of the current data. This function
+ is called by detach() when the reference count is greater than 1 in
+ order to create the new copy. This function uses the \e {operator
+ new} and calls the copy constructor of the type T.
- See QSharedDataPointer::clone() for an explanation of how to use it.
+ See QSharedDataPointer::clone() for an explanation of how to use it.
*/
/*!
- \typedef QExplicitlySharedDataPointer::Type
+ \typedef QExplicitlySharedDataPointer::Type
- This is the type of the shared data object. The \e{d pointer}
- points to an object of this type.
- */
+ This is the type of the shared data object. The \e{d pointer}
+ points to an object of this type.
+*/
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qshareddata.h b/src/corelib/tools/qshareddata.h
index 019ddd9bba..003d187767 100644
--- a/src/corelib/tools/qshareddata.h
+++ b/src/corelib/tools/qshareddata.h
@@ -69,6 +69,9 @@ private:
template <class T> class QSharedDataPointer
{
public:
+ typedef T Type;
+ typedef T *pointer;
+
inline void detach() { if (d && d->ref != 1) detach_helper(); }
inline T &operator*() { detach(); return *d; }
inline const T &operator*() const { return *d; }
@@ -111,6 +114,9 @@ public:
inline bool operator!() const { return !d; }
+ inline void swap(QSharedDataPointer &other)
+ { qSwap(d, other.d); }
+
protected:
T *clone();
@@ -124,6 +130,7 @@ template <class T> class QExplicitlySharedDataPointer
{
public:
typedef T Type;
+ typedef T *pointer;
inline T &operator*() const { return *d; }
inline T *operator->() { return d; }
@@ -186,6 +193,9 @@ public:
inline bool operator!() const { return !d; }
+ inline void swap(QExplicitlySharedDataPointer &other)
+ { qSwap(d, other.d); }
+
protected:
T *clone();
@@ -235,6 +245,14 @@ template <class T>
Q_INLINE_TEMPLATE QExplicitlySharedDataPointer<T>::QExplicitlySharedDataPointer(T *adata) : d(adata)
{ if (d) d->ref.ref(); }
+template <class T>
+Q_INLINE_TEMPLATE void qSwap(QSharedDataPointer<T> &p1, QSharedDataPointer<T> &p2)
+{ p1.swap(p2); }
+
+template <class T>
+Q_INLINE_TEMPLATE void qSwap(QExplicitlySharedDataPointer<T> &p1, QExplicitlySharedDataPointer<T> &p2)
+{ p1.swap(p2); }
+
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/corelib/tools/qsharedpointer.cpp b/src/corelib/tools/qsharedpointer.cpp
index 8cf7ad7923..78117100c8 100644
--- a/src/corelib/tools/qsharedpointer.cpp
+++ b/src/corelib/tools/qsharedpointer.cpp
@@ -50,7 +50,6 @@
\since 4.5
\reentrant
- \ingroup misc
The QSharedPointer is an automatic, shared pointer in C++. It
behaves exactly like a normal pointer for normal purposes,
@@ -98,17 +97,264 @@
access made to the data being guarded: if it's a non-const access,
it creates a copy atomically for the operation to complete.
- QExplicitlySharedDataPointer behaves like QSharedDataPointer,
- except that it only detaches if
- QExplicitlySharedDataPointer::detach() is explicitly called.
-
- Finally, QPointer holds a pointer to a QObject-derived object, but
- it does so weakly. QPointer is similar, in that behaviour, to
- QWeakPointer: it does not allow you to prevent the object from
- being destroyed. All you can do is query whether it has been
- destroyed or not.
-
- \sa QSharedDataPointer, QWeakPointer
+ QExplicitlySharedDataPointer is a variant of QSharedDataPointer, except
+ that it only detaches if QExplicitlySharedDataPointer::detach() is
+ explicitly called (hence the name).
+
+ QScopedPointer simply holds a pointer to a heap allocated object and
+ deletes it in its destructor. This class is useful when an object needs to
+ be heap allocated and deleted, but no more. QScopedPointer is lightweight,
+ it makes no use of additional structure or reference counting.
+
+ Finally, QPointer holds a pointer to a QObject-derived object, but it
+ does so weakly. QPointer can be replaced by QWeakPointer in almost all
+ cases, since they have the same functionality. See
+ \l{QWeakPointer#tracking-qobject} for more information.
+
+ \section1 Optional pointer tracking
+
+ A feature of QSharedPointer that can be enabled at compile-time for
+ debugging purposes is a pointer tracking mechanism. When enabled,
+ QSharedPointer registers in a global set all the pointers that it tracks.
+ This allows one to catch mistakes like assigning the same pointer to two
+ QSharedPointer objects.
+
+ This function is enabled by defining the \tt{QT_SHAREDPOINTER_TRACK_POINTERS}
+ macro before including the QSharedPointer header.
+
+ It is safe to use this feature even with code compiled without the
+ feature. QSharedPointer will ensure that the pointer is removed from the
+ tracker even from code compiled without pointer tracking.
+
+ Note, however, that the pointer tracking feature has limitations on
+ multiple- or virtual-inheritance (that is, in cases where two different
+ pointer addresses can refer to the same object). In that case, if a
+ pointer is cast to a different type and its value changes,
+ QSharedPointer's pointer tracking mechanism mail fail to detect that the
+ object being tracked is the same.
+
+ \omit
+ \secton1 QSharedPointer internals
+
+ QSharedPointer is in reality implemented by two ancestor classes:
+ QtSharedPointer::Basic and QtSharedPointer::ExternalRefCount. The reason
+ for having that split is now mostly legacy: in the beginning,
+ QSharedPointer was meant to support both internal reference counting and
+ external reference counting.
+
+ QtSharedPointer::Basic implements the basic functionality that is shared
+ between internal- and external-reference counting. That is, it's mostly
+ the accessor functions into QSharedPointer. Those are all inherited by
+ QSharedPointer, which adds another level of shared functionality (the
+ constructors and assignment operators). The Basic class has one member
+ variable, which is the actual pointer being tracked.
+
+ QtSharedPointer::ExternalRefCount implements the actual reference
+ counting and introduces the d-pointer for QSharedPointer. That d-pointer
+ itself is shared with with other QSharedPointer objects as well as
+ QWeakPointer.
+
+ The reason for keeping the pointer value itself outside the d-pointer is
+ because of multiple inheritance needs. If you have two QSharedPointer
+ objects of different pointer types, but pointing to the same object in
+ memory, it could happen that the pointer values are different. The \tt
+ differentPointers autotest exemplifies this problem. The same thing could
+ happen in the case of virtual inheritance: a pointer of class matching
+ the virtual base has different address compared to the pointer of the
+ complete object. See the \tt virtualBaseDifferentPointers autotest for
+ this problem.
+
+ The d pointer is of type QtSharedPointer::ExternalRefCountData for simple
+ QSharedPointer objects, but could be of a derived type in some cases. It
+ is basically a reference-counted reference-counter.
+
+ \section2 d-pointer
+ \section3 QtSharedPointer::ExternalRefCountData
+
+ This class is basically a reference-counted reference-counter. It has two
+ members: \tt strongref and \tt weakref. The strong reference counter is
+ controlling the lifetime of the object tracked by QSharedPointer. a
+ positive value indicates that the object is alive. It's also the number
+ of QSharedObject instances that are attached to this Data.
+
+ When the strong reference count decreases to zero, the object is deleted
+ (see below for information on custom deleters). The strong reference
+ count can also exceptionally be -1, indicating that there are no
+ QSharedPointers attached to an object, which is tracked too. The only
+ case where this is possible is that of
+ \l{QWeakPointer#tracking-qobject}{QWeakPointers tracking a QObject}.
+
+ The weak reference count controls the lifetime of the d-pointer itself.
+ It can be thought of as an internal/intrusive reference count for
+ ExternalRefCountData itself. This count is equal to the number of
+ QSharedPointers and QWeakPointers that are tracking this object. (In case
+ the object tracked derives from QObject, this number is increased by 1,
+ since QObjectPrivate tracks it too).
+
+ ExternalRefCountData is a virtual class: it has a virtual destructor and
+ a virtual destroy() function. The destroy() function is supposed to
+ delete the object being tracked and return true if it does so. Otherwise,
+ it returns false to indicate that the caller must simply call delete.
+ This allows the normal use-case of QSharedPointer without custom deleters
+ to use only one 12- or 16-byte (depending on whether it's a 32- or 64-bit
+ architecture) external descriptor structure, without paying the price for
+ the custom deleter that it isn't using.
+
+ \section3 QtSharedPointer::ExternalRefCountDataWithDestroyFn
+
+ This class is not used directly, per se. It only exists to enable the two
+ classes that derive from it. It adds one member variable, which is a
+ pointer to a function (which returns void and takes an
+ ExternalRefCountData* as a parameter). It also overrides the destroy()
+ function: it calls that function pointer with \tt this as parameter, and
+ returns true.
+
+ That means when ExternalRefCountDataWithDestroyFn is used, the \tt
+ destroyer field must be set to a valid function that \b will delete the
+ object tracked.
+
+ This class also adds an operator delete function to ensure that simply
+ calls the global operator delete. That should be the behaviour in all
+ compilers already, but to be on the safe side, this class ensures that no
+ funny business happens.
+
+ On a 32-bit architecture, this class is 16 bytes in size, whereas it's 24
+ bytes on 64-bit. (On Itanium where function pointers contain the global
+ pointer, it can be 32 bytes).
+
+ \section3 QtSharedPointer::ExternalRefCountWithCustomDeleter
+
+ This class derives from ExternalRefCountDataWithDestroyFn and is a
+ template class. As template parameters, it has the type of the pointer
+ being tracked (\tt T) and a \tt Deleter, which is anything. It adds two
+ fields to its parent class, matching those template parameters: a member
+ of type \tt Deleter and a member of type \tt T*.
+
+ The purpose of this class is to store the pointer to be deleted and the
+ deleter code along with the d-pointer. This allows the last strong
+ reference to call any arbitrary function that disposes of the object. For
+ example, this allows calling QObject::deleteLater() on a given object.
+ The pointer to the object is kept here to avoid the extra cost of keeping
+ the deleter in the generic case.
+
+ This class is never instantiated directly: the constructors and
+ destructor are private. Only the create() function may be called to
+ return an object of this type. See below for construction details.
+
+ The size of this class depends on the size of \tt Deleter. If it's an
+ empty functor (i.e., no members), ABIs generally assign it the size of 1.
+ But given that it's followed by a pointer, up to 3 or 7 padding bytes may
+ be inserted: in that case, the size of this class is 16+4+4 = 24 bytes on
+ 32-bit architectures, or 24+8+8 = 40 bytes on 64-bit architectures (48
+ bytes on Itanium with global pointers stored). If \tt Deleter is a
+ function pointer, the size should be the same as the empty structure
+ case, except for Itanium where it may be 56 bytes due to another global
+ pointer. If \tt Deleter is a pointer to a member function (PMF), the size
+ will be even bigger and will depend on the ABI. For architectures using
+ the Itanium C++ ABI, a PMF is twice the size of a normal pointer, or 24
+ bytes on Itanium itself. In that case, the size of this structure will be
+ 16+8+4 = 28 bytes on 32-bit architectures, 24+16+8 = 48 bytes on 64-bit,
+ and 32+24+8 = 64 bytes on Itanium.
+
+ (Values for Itanium consider an LP64 architecture; for ILP32, pointers
+ are 32-bit in length, function pointers are 64-bit and PMF are 96-bit, so
+ the sizes are slightly less)
+
+ \section3 QtSharedPointer::ExternalRefCountWithContiguousData
+
+ This class also derives from ExternalRefCountDataWithDestroyFn and it is
+ also a template class. The template parameter is the type \tt T of the
+ class which QSharedPointer tracks. It adds only one member to its parent,
+ which is of type \tt T (the actual type, not a pointer to it).
+
+ The purpose of this class is to lay the \tt T object out next to the
+ reference counts, saving one memory allocation per shared pointer. This
+ is particularly interesting for small \tt T or for the cases when there
+ are few if any QWeakPointer tracking the object. This class exists to
+ implement the QSharedPointer::create() call.
+
+ Like ExternalRefCountWithCustomDeleter, this class is never instantiated
+ directly. This class also provides a create() member that returns the
+ pointer, and hides its constructors and destructor. (With C++0x, we'd
+ delete them).
+
+ The size of this class depends on the size of \tt T.
+
+ \section3 Instantiating ExternalRefCountWithCustomDeleter and ExternalRefCountWithContiguousData
+
+ Like explained above, these classes have private constructors. Moreover,
+ they are not defined anywhere, so trying to call \tt{new ClassType} would
+ result in a compilation or linker error. Instead, these classes must be
+ constructed via their create() methods.
+
+ Instead of instantiating the class by the normal way, the create() method
+ calls \tt{operator new} directly with the size of the class, then calls
+ the parent class's constructor only (ExternalRefCountDataWithDestroyFn).
+ This ensures that the inherited members are initialised properly, as well
+ as the virtual table pointer, which must point to
+ ExternalRefCountDataWithDestroyFn's virtual table. That way, we also
+ ensure that the virtual destructor being called is
+ ExternalRefCountDataWithDestroyFn's.
+
+ After initialising the base class, the
+ ExternalRefCountWithCustomDeleter::create() function initialises the new
+ members directly, by using the placement \tt{operator new}. In the case
+ of the ExternalRefCountWithContiguousData::create() function, the address
+ to the still-uninitialised \tt T member is saved for the callee to use.
+ The member is only initialised in QSharedPointer::create(), so that we
+ avoid having many variants of the internal functions according to the
+ arguments in use for calling the constructor.
+
+ When initialising the parent class, the create() functions pass the
+ address of the static deleter() member function. That is, when the
+ virtual destroy() is called by QSharedPointer, the deleter() functions
+ are called instead. These functiosn static_cast the ExternalRefCountData*
+ parameter to their own type and execute their deletion: for the
+ ExternalRefCountWithCustomDeleter::deleter() case, it runs the user's
+ custom deleter, then destroys the deleter; for
+ ExternalRefCountWithContiguousData::deleter, it simply calls the \tt T
+ destructor directly.
+
+ By not calling the constructor of the derived classes, we avoid
+ instantiating their virtual tables. Since these classes are
+ template-based, there would be one virtual table per \tt T and \tt
+ Deleter type. (This is what Qt 4.5 did)
+
+ Instead, only one non-inline function is required per template, which is
+ the deleter() static member. All the other functions can be inlined.
+ What's more, the address of deleter() is calculated only in code, which
+ can be resolved at link-time if the linker can determine that the
+ function lies in the current application or library module (since these
+ classes are not exported, that is the case for Windows or for builds with
+ \tt{-fvisibility=hidden}).
+
+ In contrast, a virtual table would require at least 3 relocations to be
+ resolved at module load-time, per module where these classes are used.
+ (In the Itanium C++ ABI, there would be more relocations, due to the
+ RTTI)
+
+ \section3 Modifications due to pointer-tracking
+
+ To ensure that pointers created with pointer-tracking enabled get
+ un-tracked when destroyed, even if destroyed by code compiled without the
+ feature, QSharedPointer modifies slightly the instructions of the
+ previous sections.
+
+ When ExternalRefCountWithCustomDeleter or
+ ExternalRefCountWithContiguousData are used, their create() functions
+ will set the ExternalRefCountDataWithDestroyFn::destroyer function
+ pointer to safetyCheckDeleter() instead. These static member functions
+ simply call internalSafetyCheckRemove2() before passing control to the
+ normal deleter() function.
+
+ If neither custom deleter nor QSharedPointer::create() are used, then
+ QSharedPointer uses a custom deleter of its own: the normalDeleter()
+ function, which simply calls \tt delete. By using a custom deleter, the
+ safetyCheckDeleter() procedure described above kicks in.
+
+ \endomit
+
+ \sa QSharedDataPointer, QWeakPointer, QScopedPointer
*/
/*!
@@ -116,21 +362,96 @@
\brief The QWeakPointer class holds a weak reference to a shared pointer
\since 4.5
\reentrant
- \ingroup misc
The QWeakPointer is an automatic weak reference to a
pointer in C++. It cannot be used to dereference the pointer
directly, but it can be used to verify if the pointer has been
deleted or not in another context.
- QWeakPointer objects can only be created by assignment
- from a QSharedPointer.
-
- To access the pointer that QWeakPointer is tracking, you
- must first create a QSharedPointer object and verify if the pointer
- is null or not.
-
- \sa QSharedPointer
+ QWeakPointer objects can only be created by assignment from a
+ QSharedPointer. The exception is pointers derived from QObject: in that
+ case, QWeakPointer serves as a replacement to QPointer.
+
+ It's important to note that QWeakPointer provides no automatic casting
+ operators to prevent mistakes from happening. Even though QWeakPointer
+ tracks a pointer, it should not be considered a pointer itself, since it
+ doesn't guarantee that the pointed object remains valid.
+
+ Therefore, to access the pointer that QWeakPointer is tracking, you must
+ first promote it to QSharedPointer and verify if the resulting object is
+ null or not. QSharedPointer guarantees that the object isn't deleted, so
+ if you obtain a non-null object, you may use the pointer. See
+ QWeakPointer::toStrongRef() for more an example.
+
+ QWeakPointer also provides the QWeakPointer::data() method that returns
+ the tracked pointer without ensuring that it remains valid. This function
+ is provided if you can guarantee by external means that the object will
+ not get deleted (or if you only need the pointer value) and the cost of
+ creating a QSharedPointer using toStrongRef() is too high.
+
+ That function can also be used to obtain the tracked pointer for
+ QWeakPointers that cannot be promoted to QSharedPointer, such as those
+ created directly from a QObject pointer (not via QSharedPointer).
+
+ \section1 Tracking QObject
+
+ QWeakPointer can be used to track deletion classes derives from QObject,
+ even if they are not managed by QSharedPointer. When used in that role,
+ QWeakPointer replaces the older QPointer in all use-cases. QWeakPointer
+ is also more efficient than QPointer, so it should be preferred in all
+ new code.
+
+ To do that, QWeakPointer provides a special constructor that is only
+ available if the template parameter \tt T is either QObject or a class
+ deriving from it. Trying to use that constructor if \tt T does not derive
+ from QObject will result in compilation errors.
+
+ To obtain the QObject being tracked by QWeakPointer, you must use the
+ QWeakPointer::data() function, but only if you can guarantee that the
+ object cannot get deleted by another context. It should be noted that
+ QPointer had the same constraint, so use of QWeakPointer forces you to
+ consider whether the pointer is still valid.
+
+ QObject-derived classes can only be deleted in the thread they have
+ affinity to (which is the thread they were created in or moved to, using
+ QObject::moveToThread()). In special, QWidget-derived classes cannot be
+ created in non-GUI threads nor moved there. Therefore, guaranteeing that
+ the tracked QObject has affinity to the current thread is enough to also
+ guarantee that it won't be deleted asynchronously.
+
+ Note that QWeakPointer's size and data layout do not match QPointer, so
+ it cannot replace that class in a binary-compatible manner.
+
+ Care must also be taken with QWeakPointers created directly from QObject
+ pointers when dealing with code that was compiled with Qt versions prior
+ to 4.6. Those versions may not track the reference counters correctly, so
+ QWeakPointers created from QObject should never be passed to code that
+ hasn't been recompiled.
+
+ \omit
+ \secton1 QWeakPointer internals
+
+ QWeakPointer shares most of its internal functionality with
+ \l{QSharedPointer#qsharedpointer-internals}{QSharedPointer}, so see that
+ class's internal documentation for more information.
+
+ QWeakPointer requires an external reference counter in order to operate.
+ Therefore, it is incompatible by design with \l QSharedData-derived
+ classes.
+
+ It has a special QObject constructor, which works by calling
+ QtSharedPointer::ExternalRefCountData::getAndRef, which retrieves the
+ d-pointer from QObjectPrivate. If one isn't set yet, that function
+ creates the d-pointer and atomically sets it.
+
+ If getAndRef needs to create a d-pointer, it sets the strongref to -1,
+ indicating that the QObject is not shared: QWeakPointer is used only to
+ determine whether the QObject has been deleted. In that case, it cannot
+ be upgraded to QSharedPointer (see the previous section).
+
+ \endomit
+
+ \sa QSharedPointer, QScopedPointer
*/
/*!
@@ -210,6 +531,8 @@
If \tt T is a derived type of the template parameter of this
class, QSharedPointer will perform an automatic cast. Otherwise,
you will get a compiler error.
+
+ \sa QWeakPointer::toStrongRef()
*/
/*!
@@ -340,10 +663,30 @@
*/
/*!
+ \fn QSharedPointer<X> QSharedPointer::objectCast() const
+ \since 4.6
+
+ Performs a \l qobject_cast() from this pointer's type to \tt X and
+ returns a QSharedPointer that shares the reference. If this
+ function is used to up-cast, then QSharedPointer will perform a \tt
+ qobject_cast, which means that if the object being pointed by this
+ QSharedPointer is not of type \tt X, the returned object will be
+ null.
+
+ Note: the template type \c X must have the same const and volatile
+ qualifiers as the template of this object, or the cast will
+ fail. Use constCast() if you need to drop those qualifiers.
+
+ \sa qSharedPointerObjectCast()
+*/
+
+/*!
\fn QWeakPointer<T> QSharedPointer::toWeakRef() const
Returns a weak reference object that shares the pointer referenced
by this object.
+
+ \sa QWeakPointer::QWeakPointer()
*/
/*!
@@ -390,6 +733,35 @@
*/
/*!
+ \fn QWeakPointer::QWeakPointer(const QObject *obj)
+ \since 4.6
+
+ Creates a QWeakPointer that holds a weak reference directly to the
+ QObject \a obj. This constructor is only available if the template type
+ \tt T is QObject or derives from it (otherwise a compilation error will
+ result).
+
+ You can use this constructor with any QObject, even if they were not
+ created with \l QSharedPointer.
+
+ Note that QWeakPointers created this way on arbitrary QObjects usually
+ cannot be promoted to QSharedPointer.
+
+ \sa QSharedPointer, QWeakPointer#tracking-qobject
+*/
+
+/*!
+ \fn QWeakPointer &QWeakPointer::operator=(const QObject *obj)
+ \since 4.6
+
+ Makes this QWeakPointer hold a weak reference to directly to the QObject
+ \a obj. This function is only available if the template type \tt T is
+ QObject or derives from it.
+
+ \sa QWeakPointer#tracking-qobject
+*/
+
+/*!
\fn QWeakPointer &QWeakPointer::operator=(const QWeakPointer<T> &other)
Makes this object share \a other's pointer. The current pointer
@@ -460,10 +832,78 @@
*/
/*!
+ \fn T *QWeakPointer::data() const
+ \since 4.6
+
+ Returns the value of the pointer being tracked by this QWeakPointer,
+ \b without ensuring that it cannot get deleted. To have that guarantee,
+ use toStrongRef(), which returns a QSharedPointer object. If this
+ function can determine that the pointer has already been deleted, it
+ returns 0.
+
+ It is ok to obtain the value of the pointer and using that value itself,
+ like for example in debugging statements:
+
+ \code
+ qDebug("Tracking %p", weakref.data());
+ \endcode
+
+ However, dereferencing the pointer is only allowed if you can guarantee
+ by external means that the pointer does not get deleted. For example,
+ if you can be certain that no other thread can delete it, nor the
+ functions that you may call.
+
+ If that is the case, then the following code is valid:
+
+ \code
+ // this pointer cannot be used in another thread
+ // so other threads cannot delete it
+ QWeakPointer<int> weakref = obtainReference();
+
+ Object *obj = weakref.data();
+ if (obj) {
+ // if the pointer wasn't deleted yet, we know it can't get
+ // deleted by our own code here nor the functions we call
+ otherFunction(obj);
+ }
+ \endcode
+
+ Use this function with care.
+
+ \sa isNull(), toStrongRef()
+*/
+
+/*!
\fn QSharedPointer<T> QWeakPointer::toStrongRef() const
Promotes this weak reference to a strong one and returns a
- QSharedPointer object holding that reference.
+ QSharedPointer object holding that reference. When promoting to
+ QSharedPointer, this function verifies if the object has been deleted
+ already or not. If it hasn't, this function increases the reference
+ count to the shared object, thus ensuring that it will not get
+ deleted.
+
+ Since this function can fail to obtain a valid strong reference to the
+ shared object, you should always verify if the conversion succeeded,
+ by calling QSharedPointer::isNull() on the returned object.
+
+ For example, the following code promotes a QWeakPointer that was held
+ to a strong reference and, if it succeeded, it prints the value of the
+ integer that was held:
+
+ \code
+ QWeakPointer<int> weakref;
+
+ // ...
+
+ QSharedPointer<int> strong = weakref.toStrongRef();
+ if (strong)
+ qDebug() << "The value is:" << *strong;
+ else
+ qDebug() << "The value has already been deleted";
+ \endcode
+
+ \sa QSharedPointer::QSharedPointer()
*/
/*!
@@ -718,6 +1158,47 @@
*/
/*!
+ \fn QSharedPointer<X> qSharedPointerObjectCast(const QSharedPointer<T> &other)
+ \relates QSharedPointer
+ \since 4.6
+
+ Returns a shared pointer to the pointer held by \a other, using a
+ \l qobject_cast() to type \tt X to obtain an internal pointer of the
+ appropriate type. If the \tt qobject_cast fails, the object
+ returned will be null.
+
+ Note that \tt X must have the same cv-qualifiers (\tt const and
+ \tt volatile) that \tt T has, or the code will fail to
+ compile. Use qSharedPointerConstCast to cast away the constness.
+
+ \sa QSharedPointer::objectCast(), qSharedPointerCast(), qSharedPointerConstCast()
+*/
+
+/*!
+ \fn QSharedPointer<X> qSharedPointerObjectCast(const QWeakPointer<T> &other)
+ \relates QSharedPointer
+ \relates QWeakPointer
+ \since 4.6
+
+ Returns a shared pointer to the pointer held by \a other, using a
+ \l qobject_cast() to type \tt X to obtain an internal pointer of the
+ appropriate type. If the \tt qobject_cast fails, the object
+ returned will be null.
+
+ The \a other object is converted first to a strong reference. If
+ that conversion fails (because the object it's pointing to has
+ already been deleted), this function also returns a null
+ QSharedPointer.
+
+ Note that \tt X must have the same cv-qualifiers (\tt const and
+ \tt volatile) that \tt T has, or the code will fail to
+ compile. Use qSharedPointerConstCast to cast away the constness.
+
+ \sa QWeakPointer::toStrongRef(), qSharedPointerCast(), qSharedPointerConstCast()
+*/
+
+
+/*!
\fn QWeakPointer<X> qWeakPointerCast(const QWeakPointer<T> &other)
\relates QWeakPointer
@@ -733,6 +1214,63 @@
#include <qset.h>
#include <qmutex.h>
+#if !defined(QT_NO_QOBJECT)
+#include "private/qobject_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \internal
+ This function is called for a just-created QObject \a obj, to enable
+ the use of QSharedPointer and QWeakPointer.
+
+ When QSharedPointer is active in a QObject, the object must not be deleted
+ directly: the lifetime is managed by the QSharedPointer object. In that case,
+ the deleteLater() and parent-child relationship in QObject only decrease
+ the strong reference count, instead of deleting the object.
+*/
+void QtSharedPointer::ExternalRefCountData::setQObjectShared(const QObject *obj, bool)
+{
+ Q_ASSERT(obj);
+ QObjectPrivate *d = QObjectPrivate::get(const_cast<QObject *>(obj));
+
+ if (d->sharedRefcount)
+ qFatal("QSharedPointer: pointer %p already has reference counting", obj);
+ d->sharedRefcount = this;
+
+ // QObject decreases the refcount too, so increase it up
+ weakref.ref();
+}
+
+QtSharedPointer::ExternalRefCountData *QtSharedPointer::ExternalRefCountData::getAndRef(const QObject *obj)
+{
+ Q_ASSERT(obj);
+ QObjectPrivate *d = QObjectPrivate::get(const_cast<QObject *>(obj));
+ Q_ASSERT_X(!d->wasDeleted, "QWeakPointer", "Detected QWeakPointer creation in a QObject being deleted");
+
+ ExternalRefCountData *that = d->sharedRefcount;
+ if (that) {
+ that->weakref.ref();
+ return that;
+ }
+
+ // we can create the refcount data because it doesn't exist
+ ExternalRefCountData *x = new ExternalRefCountData(Qt::Uninitialized);
+ x->strongref = -1;
+ x->weakref = 2; // the QWeakPointer that called us plus the QObject itself
+ if (!d->sharedRefcount.testAndSetRelease(0, x)) {
+ delete x;
+ d->sharedRefcount->weakref.ref();
+ }
+ return d->sharedRefcount;
+}
+
+QT_END_NAMESPACE
+
+#endif
+
+
+
#if !defined(QT_NO_MEMBER_TEMPLATES)
//# define QT_SHARED_POINTER_BACKTRACE_SUPPORT
@@ -744,29 +1282,21 @@
# endif
# endif
-# if !defined(BACKTRACE_SUPPORTED)
-// Dummy implementation of the functions.
-// Using QHashDummyValue also means that the QHash below is actually a QSet
-typedef QT_PREPEND_NAMESPACE(QHashDummyValue) Backtrace;
-
-static inline Backtrace saveBacktrace() { return Backtrace(); }
-static inline void printBacktrace(Backtrace) { }
-
-# else
+# if defined(BACKTRACE_SUPPORTED)
# include <sys/types.h>
# include <execinfo.h>
# include <stdio.h>
# include <unistd.h>
# include <sys/wait.h>
-typedef QT_PREPEND_NAMESPACE(QByteArray) Backtrace;
+QT_BEGIN_NAMESPACE
-static inline Backtrace saveBacktrace() __attribute__((always_inline));
-static inline Backtrace saveBacktrace()
+static inline QByteArray saveBacktrace() __attribute__((always_inline));
+static inline QByteArray saveBacktrace()
{
static const int maxFrames = 32;
- Backtrace stacktrace;
+ QByteArray stacktrace;
stacktrace.resize(sizeof(void*) * maxFrames);
int stack_size = backtrace((void**)stacktrace.data(), maxFrames);
stacktrace.resize(sizeof(void*) * stack_size);
@@ -774,7 +1304,7 @@ static inline Backtrace saveBacktrace()
return stacktrace;
}
-static void printBacktrace(Backtrace stacktrace)
+static void printBacktrace(QByteArray stacktrace)
{
void *const *stack = (void *const *)stacktrace.constData();
int stack_size = stacktrace.size() / sizeof(void*);
@@ -821,29 +1351,58 @@ static void printBacktrace(Backtrace stacktrace)
waitpid(child, 0, 0);
}
}
+
+QT_END_NAMESPACE
+
# endif // BACKTRACE_SUPPORTED
namespace {
QT_USE_NAMESPACE
+ struct Data {
+ const volatile void *pointer;
+# ifdef BACKTRACE_SUPPORTED
+ QByteArray backtrace;
+# endif
+ };
+
class KnownPointers
{
public:
QMutex mutex;
- QHash<void *, Backtrace> values;
+ QHash<const void *, Data> dPointers;
+ QHash<const volatile void *, const void *> dataPointers;
};
}
-//Q_GLOBAL_STATIC(KnownPointers, knownPointers)
+Q_GLOBAL_STATIC(KnownPointers, knownPointers)
QT_BEGIN_NAMESPACE
+namespace QtSharedPointer {
+ Q_CORE_EXPORT void internalSafetyCheckAdd(const volatile void *);
+ Q_CORE_EXPORT void internalSafetyCheckRemove(const volatile void *);
+ Q_AUTOTEST_EXPORT void internalSafetyCheckCleanCheck();
+}
+
/*!
\internal
*/
void QtSharedPointer::internalSafetyCheckAdd(const volatile void *)
{
- // functionality is broken
- // fix requires Qt 4.6
+ // Qt 4.5 compatibility
+ // this function is broken by design, so it was replaced with internalSafetyCheckAdd2
+ //
+ // it's broken because we tracked the pointers added and
+ // removed from QSharedPointer, converted to void*.
+ // That is, this is supposed to track the "top-of-object" pointer in
+ // case of multiple inheritance.
+ //
+ // However, it doesn't work well in some compilers:
+ // if you create an object with a class of type A and the last reference
+ // is dropped of type B, then the value passed to internalSafetyCheckRemove could
+ // be different than was added. That would leave dangling addresses.
+ //
+ // So instead, we track the pointer by the d-pointer instead.
}
/*!
@@ -851,6 +1410,90 @@ void QtSharedPointer::internalSafetyCheckAdd(const volatile void *)
*/
void QtSharedPointer::internalSafetyCheckRemove(const volatile void *)
{
+ // Qt 4.5 compatibility
+ // see comments above
+}
+
+/*!
+ \internal
+*/
+void QtSharedPointer::internalSafetyCheckAdd2(const void *d_ptr, const volatile void *ptr)
+{
+ // see comments above for the rationale for this function
+ KnownPointers *const kp = knownPointers();
+ if (!kp)
+ return; // end-game: the application is being destroyed already
+
+ QMutexLocker lock(&kp->mutex);
+ Q_ASSERT(!kp->dPointers.contains(d_ptr));
+
+ //qDebug("Adding d=%p value=%p", d_ptr, ptr);
+
+ const void *other_d_ptr = kp->dataPointers.value(ptr, 0);
+ if (other_d_ptr) {
+# ifdef BACKTRACE_SUPPORTED
+ printBacktrace(knownPointers()->dPointers.value(other_d_ptr).backtrace);
+# endif
+ qFatal("QSharedPointer: internal self-check failed: pointer %p was already tracked "
+ "by another QSharedPointer object %p", ptr, other_d_ptr);
+ }
+
+ Data data;
+ data.pointer = ptr;
+# ifdef BACKTRACE_SUPPORTED
+ data.backtrace = saveBacktrace();
+# endif
+
+ kp->dPointers.insert(d_ptr, data);
+ kp->dataPointers.insert(ptr, d_ptr);
+ Q_ASSERT(kp->dPointers.size() == kp->dataPointers.size());
+}
+
+/*!
+ \internal
+*/
+void QtSharedPointer::internalSafetyCheckRemove2(const void *d_ptr)
+{
+ KnownPointers *const kp = knownPointers();
+ if (!kp)
+ return; // end-game: the application is being destroyed already
+
+ QMutexLocker lock(&kp->mutex);
+
+ QHash<const void *, Data>::iterator it = kp->dPointers.find(d_ptr);
+ if (it == kp->dPointers.end()) {
+ qFatal("QSharedPointer: internal self-check inconsistency: pointer %p was not tracked. "
+ "To use QT_SHAREDPOINTER_TRACK_POINTERS, you have to enable it throughout "
+ "in your code.", d_ptr);
+ }
+
+ QHash<const volatile void *, const void *>::iterator it2 = kp->dataPointers.find(it->pointer);
+ Q_ASSERT(it2 != kp->dataPointers.end());
+
+ //qDebug("Removing d=%p value=%p", d_ptr, it->pointer);
+
+ // remove entries
+ kp->dataPointers.erase(it2);
+ kp->dPointers.erase(it);
+ Q_ASSERT(kp->dPointers.size() == kp->dataPointers.size());
+}
+
+/*!
+ \internal
+ Called by the QSharedPointer autotest
+*/
+void QtSharedPointer::internalSafetyCheckCleanCheck()
+{
+# ifdef QT_BUILD_INTERNAL
+ KnownPointers *const kp = knownPointers();
+ Q_ASSERT_X(kp, "internalSafetyCheckSelfCheck()", "Called after global statics deletion!");
+
+ if (kp->dPointers.size() != kp->dataPointers.size())
+ qFatal("Internal consistency error: the number of pointers is not equal!");
+
+ if (!kp->dPointers.isEmpty())
+ qFatal("Pointer cleaning failed: %d entries remaining", kp->dPointers.size());
+# endif
}
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qsharedpointer.h b/src/corelib/tools/qsharedpointer.h
index 98d2c9e7a6..ac3032cde9 100644
--- a/src/corelib/tools/qsharedpointer.h
+++ b/src/corelib/tools/qsharedpointer.h
@@ -93,6 +93,7 @@ public:
template <class X> QSharedPointer<X> staticCast() const;
template <class X> QSharedPointer<X> dynamicCast() const;
template <class X> QSharedPointer<X> constCast() const;
+ template <class X> QSharedPointer<X> objectCast() const;
};
template <class T>
@@ -114,6 +115,10 @@ public:
QWeakPointer<T> operator=(const QWeakPointer<T> &other);
QWeakPointer<T> operator=(const QSharedPointer<T> &other);
+ QWeakPointer(const QObject *other);
+ QWeakPointer<T> operator=(const QObject *other);
+
+ T *data() const;
void clear();
QSharedPointer<T> toStrongRef() const;
@@ -136,6 +141,8 @@ template <class X, class T> QSharedPointer<X> qSharedPointerDynamicCast(const QS
template <class X, class T> QSharedPointer<X> qSharedPointerDynamicCast(const QWeakPointer<T> &src);
template <class X, class T> QSharedPointer<X> qSharedPointerConstCast(const QSharedPointer<T> &src);
template <class X, class T> QSharedPointer<X> qSharedPointerConstCast(const QWeakPointer<T> &src);
+template <class X, class T> QSharedPointer<X> qSharedPointerObjectCast(const QSharedPointer<T> &src);
+template <class X, class T> QSharedPointer<X> qSharedPointerObjectCast(const QWeakPointer<T> &src);
template <class X, class T> QWeakPointer<X> qWeakPointerCast(const QWeakPointer<T> &src);
diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h
index 8dbccb1e48..a43fd9cc60 100644
--- a/src/corelib/tools/qsharedpointer_impl.h
+++ b/src/corelib/tools/qsharedpointer_impl.h
@@ -48,7 +48,9 @@
#pragma qt_sync_stop_processing
#endif
+#include <new>
#include <QtCore/qatomic.h>
+#include <QtCore/qobject.h> // for qobject_cast
QT_BEGIN_HEADER
@@ -83,17 +85,20 @@ QSharedPointer<X> qSharedPointerDynamicCast(const QSharedPointer<T> &ptr);
template <class X, class T>
QSharedPointer<X> qSharedPointerConstCast(const QSharedPointer<T> &ptr);
+#ifndef QT_NO_QOBJECT
+template <class X, class T>
+QSharedPointer<X> qSharedPointerObjectCast(const QSharedPointer<T> &ptr);
+#endif
+
namespace QtSharedPointer {
template <class T> class InternalRefCount;
template <class T> class ExternalRefCount;
- template <class X, class T> QSharedPointer<X> qStrongRefFromWeakHelper(const QWeakPointer<T> &, X*);
- template <class X, class T> QSharedPointer<X> qSharedPointerCastHelper(const QSharedPointer<T> &src, X *);
- template <class X, class T> QSharedPointer<X> qSharedPointerConstCastHelper(const QSharedPointer<T> &src, X *);
+ template <class X, class Y> QSharedPointer<X> copyAndSetPointer(X * ptr, const QSharedPointer<Y> &src);
// used in debug mode to verify the reuse of pointers
- Q_CORE_EXPORT void internalSafetyCheckAdd(const volatile void *);
- Q_CORE_EXPORT void internalSafetyCheckRemove(const volatile void *);
+ Q_CORE_EXPORT void internalSafetyCheckAdd2(const void *, const volatile void *);
+ Q_CORE_EXPORT void internalSafetyCheckRemove2(const void *);
template <class T, typename Klass, typename RetVal>
inline void executeDeleter(T *t, RetVal (Klass:: *memberDeleter)())
@@ -101,50 +106,54 @@ namespace QtSharedPointer {
template <class T, typename Deleter>
inline void executeDeleter(T *t, Deleter d)
{ d(t); }
-
- //
- // Depending on its template parameter, QSharedPointer derives from either
- // QtSharedPointer::InternalRefCount or from QtSharedPointer::ExternalRefCount.
- // Both of these classes derive from QtSharedPointer::Basic, which provides common
- // operations,
- //
+ template <class T> inline void normalDeleter(T *t) { delete t; }
+
+ // this uses partial template specialization
+ // the only compilers that didn't support this were MSVC 6.0 and 2002
+ template <class T> struct RemovePointer;
+ template <class T> struct RemovePointer<T *> { typedef T Type; };
+ template <class T> struct RemovePointer<QSharedPointer<T> > { typedef T Type; };
+ template <class T> struct RemovePointer<QWeakPointer<T> > { typedef T Type; };
+
+ // This class provides the basic functionality of a pointer wrapper.
+ // Its existence is mostly legacy, since originally QSharedPointer
+ // could also be used for internally-refcounted objects.
template <class T>
class Basic
{
+#ifndef Q_CC_NOKIAX86
typedef T *Basic:: *RestrictedBool;
+#endif
public:
typedef T Type;
+ typedef T element_type;
+ typedef T value_type;
+ typedef value_type *pointer;
+ typedef const value_type *const_pointer;
+ typedef value_type &reference;
+ typedef const value_type &const_reference;
+ typedef ptrdiff_t difference_type;
inline T *data() const { return value; }
inline bool isNull() const { return !data(); }
+#ifndef Q_CC_NOKIAX86
inline operator RestrictedBool() const { return isNull() ? 0 : &Basic::value; }
+#else
+ inline operator bool() const { return isNull() ? 0 : &Basic::value; }
+#endif
inline bool operator !() const { return isNull(); }
inline T &operator*() const { return *data(); }
inline T *operator->() const { return data(); }
protected:
- inline Basic() : value(0 * sizeof(T)) { }
+ inline Basic(T *ptr = 0) : value(ptr) { }
+ inline Basic(Qt::Initialization) { }
// ~Basic();
- inline void verifyReconstruction(const T *ptr)
- {
- Q_ASSERT_X(!ptr || value != ptr, "QSharedPointer",
- "QSharedPointer violation: you cannot create two QSharedPointer objects "
- "from the same pointer");
-
- // make use of the "ptr" variable in the no-op statement below
- // since this function is in a public header, we don't
- // want warnings on "unused variables" to show up everywhere
- ptr = 0;
- }
-
inline void internalConstruct(T *ptr)
{
value = ptr;
}
- inline void internalDestroy()
- {
- }
#if defined(Q_NO_TEMPLATE_FRIENDS)
public:
@@ -155,64 +164,220 @@ namespace QtSharedPointer {
Type *value;
};
+ // This class is the d-pointer of QSharedPointer and QWeakPointer.
+ //
+ // It is a reference-counted reference counter. "strongref" is the inner
+ // reference counter, and it tracks the lifetime of the pointer itself.
+ // "weakref" is the outer reference counter and it tracks the lifetime of
+ // the ExternalRefCountData object.
struct ExternalRefCountData
{
- QAtomicInt weakref;
- QAtomicInt strongref;
+ QBasicAtomicInt weakref;
+ QBasicAtomicInt strongref;
- inline ExternalRefCountData() : weakref(1), strongref(1) { }
- virtual inline ~ExternalRefCountData() { Q_ASSERT(!weakref); Q_ASSERT(!strongref); }
+ inline ExternalRefCountData()
+ {
+ strongref = 1;
+ weakref = 1;
+ }
+ inline ExternalRefCountData(Qt::Initialization) { }
+ virtual inline ~ExternalRefCountData() { Q_ASSERT(!weakref); Q_ASSERT(strongref <= 0); }
+ // overridden by derived classes
+ // returns false to indicate caller should delete the pointer
+ // returns true in case it has already done so
virtual inline bool destroy() { return false; }
+
+#ifndef QT_NO_QOBJECT
+ Q_CORE_EXPORT static ExternalRefCountData *getAndRef(const QObject *);
+ Q_CORE_EXPORT void setQObjectShared(const QObject *, bool enable);
+#endif
+ inline void setQObjectShared(...) { }
};
+ // sizeof(ExternalRefCount) = 12 (32-bit) / 16 (64-bit)
- template <class T, typename Deleter>
- struct ExternalRefCountWithSpecializedDeleter: public ExternalRefCountData
+ // This class extends ExternalRefCountData with a pointer
+ // to a function, which is called by the destroy() function.
+ struct ExternalRefCountWithDestroyFn: public ExternalRefCountData
{
- T *ptr;
- Deleter deleter;
+ typedef void (*DestroyerFn)(ExternalRefCountData *);
+ DestroyerFn destroyer;
- inline ExternalRefCountWithSpecializedDeleter(T *p, Deleter d)
- : ptr(p), deleter(d)
+ inline ExternalRefCountWithDestroyFn(DestroyerFn d)
+ : destroyer(d)
{ }
- inline bool destroy() { executeDeleter(ptr, deleter); return true; }
+
+ inline bool destroy() { destroyer(this); return true; }
+ inline void operator delete(void *ptr) { ::operator delete(ptr); }
+ };
+ // sizeof(ExternalRefCountWithDestroyFn) = 16 (32-bit) / 24 (64-bit)
+
+ // This class extends ExternalRefCountWithDestroyFn and implements
+ // the static function that deletes the object. The pointer and the
+ // custom deleter are kept in the "extra" member.
+ template <class T, typename Deleter>
+ struct ExternalRefCountWithCustomDeleter: public ExternalRefCountWithDestroyFn
+ {
+ typedef ExternalRefCountWithCustomDeleter Self;
+ typedef ExternalRefCountWithDestroyFn BaseClass;
+
+ struct CustomDeleter
+ {
+ Deleter deleter;
+ T *ptr;
+
+ inline CustomDeleter(T *p, Deleter d) : deleter(d), ptr(p) {}
+ };
+ CustomDeleter extra;
+ // sizeof(CustomDeleter) = sizeof(Deleter) + sizeof(void*)
+ // for Deleter = function pointer: 8 (32-bit) / 16 (64-bit)
+ // for Deleter = PMF: 12 (32-bit) / 24 (64-bit) (GCC)
+
+ static inline void deleter(ExternalRefCountData *self)
+ {
+ Self *realself = static_cast<Self *>(self);
+ executeDeleter(realself->extra.ptr, realself->extra.deleter);
+
+ // delete the deleter too
+ realself->extra.~CustomDeleter();
+ }
+ static void safetyCheckDeleter(ExternalRefCountData *self)
+ {
+ internalSafetyCheckRemove2(self);
+ deleter(self);
+ }
+
+ static inline Self *create(T *ptr, Deleter userDeleter)
+ {
+# ifdef QT_SHAREDPOINTER_TRACK_POINTERS
+ DestroyerFn destroy = &safetyCheckDeleter;
+# else
+ DestroyerFn destroy = &deleter;
+# endif
+ Self *d = static_cast<Self *>(::operator new(sizeof(Self)));
+
+ // initialize the two sub-objects
+ new (&d->extra) CustomDeleter(ptr, userDeleter);
+ new (d) BaseClass(destroy); // can't throw
+
+ return d;
+ }
+ private:
+ // prevent construction and the emission of virtual symbols
+ ExternalRefCountWithCustomDeleter();
+ ~ExternalRefCountWithCustomDeleter();
};
+ // This class extends ExternalRefCountWithDestroyFn and adds a "T"
+ // member. That way, when the create() function is called, we allocate
+ // memory for both QSharedPointer's d-pointer and the actual object being
+ // tracked.
+ template <class T>
+ struct ExternalRefCountWithContiguousData: public ExternalRefCountWithDestroyFn
+ {
+ typedef ExternalRefCountWithDestroyFn Parent;
+ T data;
+
+ static void deleter(ExternalRefCountData *self)
+ {
+ ExternalRefCountWithContiguousData *that =
+ static_cast<ExternalRefCountWithContiguousData *>(self);
+ that->data.~T();
+ }
+ static void safetyCheckDeleter(ExternalRefCountData *self)
+ {
+ internalSafetyCheckRemove2(self);
+ deleter(self);
+ }
+
+ static inline ExternalRefCountData *create(T **ptr)
+ {
+# ifdef QT_SHAREDPOINTER_TRACK_POINTERS
+ DestroyerFn destroy = &safetyCheckDeleter;
+# else
+ DestroyerFn destroy = &deleter;
+# endif
+ ExternalRefCountWithContiguousData *d =
+ static_cast<ExternalRefCountWithContiguousData *>(::operator new(sizeof(ExternalRefCountWithContiguousData)));
+
+ // initialize the d-pointer sub-object
+ // leave d->data uninitialized
+ new (d) Parent(destroy); // can't throw
+
+ *ptr = &d->data;
+ return d;
+ }
+
+ private:
+ // prevent construction and the emission of virtual symbols
+ ExternalRefCountWithContiguousData();
+ ~ExternalRefCountWithContiguousData();
+ };
+
+ // This is the main body of QSharedPointer. It implements the
+ // external reference counting functionality.
template <class T>
class ExternalRefCount: public Basic<T>
{
- typedef ExternalRefCountData Data;
- typedef void (*DeleterFunction)(T *);
protected:
+ typedef ExternalRefCountData Data;
+
inline void ref() const { d->weakref.ref(); d->strongref.ref(); }
inline bool deref()
{
- if (!d->strongref.deref())
- this->internalDestroy();
+ if (!d->strongref.deref()) {
+ internalDestroy();
+ }
return d->weakref.deref();
}
inline void internalConstruct(T *ptr)
{
- Basic<T>::internalConstruct(ptr);
- Q_ASSERT(!d);
+#ifdef QT_SHAREDPOINTER_TRACK_POINTERS
+ internalConstruct<void (*)(T *)>(ptr, normalDeleter);
+#else
if (ptr)
d = new Data;
+ else
+ d = 0;
+ internalFinishConstruction(ptr);
+#endif
}
template <typename Deleter>
inline void internalConstruct(T *ptr, Deleter deleter)
{
- Basic<T>::internalConstruct(ptr);
- Q_ASSERT(!d);
if (ptr)
- d = new ExternalRefCountWithSpecializedDeleter<T, Deleter>(ptr, deleter);
+ d = ExternalRefCountWithCustomDeleter<T, Deleter>::create(ptr, deleter);
+ else
+ d = 0;
+ internalFinishConstruction(ptr);
+ }
+
+ inline void internalCreate()
+ {
+ T *ptr;
+ d = ExternalRefCountWithContiguousData<T>::create(&ptr);
+ Basic<T>::internalConstruct(ptr);
+ }
+
+ inline void internalFinishConstruction(T *ptr)
+ {
+ Basic<T>::internalConstruct(ptr);
+ if (ptr) d->setQObjectShared(ptr, true);
+#ifdef QT_SHAREDPOINTER_TRACK_POINTERS
+ if (ptr) internalSafetyCheckAdd2(d, ptr);
+#endif
}
inline ExternalRefCount() : d(0) { }
- inline ~ExternalRefCount() { if (d && !deref()) delete d; }
+ inline ExternalRefCount(Qt::Initialization i) : Basic<T>(i) { }
inline ExternalRefCount(const ExternalRefCount<T> &other) : Basic<T>(other), d(other.d)
{ if (d) ref(); }
+ template <class X>
+ inline ExternalRefCount(const ExternalRefCount<X> &other) : Basic<T>(other.value), d(other.d)
+ { if (d) ref(); }
+ inline ~ExternalRefCount() { if (d && !deref()) delete d; }
template <class X>
inline void internalCopy(const ExternalRefCount<X> &other)
@@ -222,32 +387,41 @@ namespace QtSharedPointer {
inline void internalDestroy()
{
- Basic<T>::internalDestroy();
if (!d->destroy())
delete this->value;
}
- private:
+ inline void internalSwap(ExternalRefCount &other)
+ {
+ qSwap(d, other.d);
+ qSwap(this->value, other.value);
+ }
+
#if defined(Q_NO_TEMPLATE_FRIENDS)
public:
#else
template <class X> friend class ExternalRefCount;
template <class X> friend class QWeakPointer;
- template <class X, class Y> friend QSharedPointer<X> qSharedPointerCastHelper(const QSharedPointer<Y> &src, X *);
- template <class X, class Y> friend QSharedPointer<X> qSharedPointerDynamicCastHelper(const QSharedPointer<Y> &src, X *);
- template <class X, class Y> friend QSharedPointer<X> qSharedPointerConstCastHelper(const QSharedPointer<Y> &src, X *);
- template <class X, class Y> friend QSharedPointer<X> QtSharedPointer::qStrongRefFromWeakHelper(const QWeakPointer<Y> &src, X *);
+ template <class X, class Y> friend QSharedPointer<X> copyAndSetPointer(X * ptr, const QSharedPointer<Y> &src);
#endif
inline void internalSet(Data *o, T *actual)
{
- if (d == o) return;
- if (o && !o->strongref)
- o = 0;
if (o) {
- verifyReconstruction(actual);
- o->weakref.ref();
- o->strongref.ref();
+ // increase the strongref, but never up from zero
+ // or less (-1 is used by QWeakPointer on untracked QObject)
+ register int tmp = o->strongref;
+ while (tmp > 0) {
+ // try to increment from "tmp" to "tmp + 1"
+ if (o->strongref.testAndSetRelaxed(tmp, tmp + 1))
+ break; // succeeded
+ tmp = o->strongref; // failed, try again
+ }
+
+ if (tmp > 0)
+ o->weakref.ref();
+ else
+ o = 0;
}
if (d && !deref())
delete d;
@@ -255,9 +429,6 @@ namespace QtSharedPointer {
this->value = d && d->strongref ? actual : 0;
}
-#if defined(QT_BUILD_INTERNAL)
- public:
-#endif
Data *d;
private:
@@ -273,41 +444,41 @@ public:
inline QSharedPointer() { }
// inline ~QSharedPointer() { }
- inline explicit QSharedPointer(T *ptr) { internalConstruct(ptr); }
+ inline explicit QSharedPointer(T *ptr) : BaseClass(Qt::Uninitialized)
+ { BaseClass::internalConstruct(ptr); }
template <typename Deleter>
- inline QSharedPointer(T *ptr, Deleter d) { internalConstruct(ptr, d); }
+ inline QSharedPointer(T *ptr, Deleter d) { BaseClass::internalConstruct(ptr, d); }
inline QSharedPointer(const QSharedPointer<T> &other) : BaseClass(other) { }
inline QSharedPointer<T> &operator=(const QSharedPointer<T> &other)
{
- internalCopy(other);
+ BaseClass::internalCopy(other);
return *this;
}
- inline QSharedPointer(const QWeakPointer<T> &other)
- { *this = QtSharedPointer::qStrongRefFromWeakHelper(other, static_cast<T*>(0)); }
- inline QSharedPointer<T> &operator=(const QWeakPointer<T> &other)
- { *this = QtSharedPointer::qStrongRefFromWeakHelper(other, static_cast<T*>(0)); return *this; }
-
template <class X>
- inline QSharedPointer(const QSharedPointer<X> &other) { *this = other; }
+ inline QSharedPointer(const QSharedPointer<X> &other) : BaseClass(other)
+ { }
template <class X>
inline QSharedPointer<T> &operator=(const QSharedPointer<X> &other)
{
QSHAREDPOINTER_VERIFY_AUTO_CAST(T, X); // if you get an error in this line, the cast is invalid
- internalCopy(other);
+ BaseClass::internalCopy(other);
return *this;
}
template <class X>
- inline QSharedPointer(const QWeakPointer<X> &other)
- { *this = QtSharedPointer::qStrongRefFromWeakHelper(other, static_cast<T *>(0)); }
+ inline QSharedPointer(const QWeakPointer<X> &other) : BaseClass(Qt::Uninitialized)
+ { this->d = 0; *this = other; }
template <class X>
inline QSharedPointer<T> &operator=(const QWeakPointer<X> &other)
- { *this = qStrongRefFromWeakHelper(other, static_cast<T *>(0)); return *this; }
+ { BaseClass::internalSet(other.d, other.value); return *this; }
+
+ inline void swap(QSharedPointer &other)
+ { internalSwap(other); }
template <class X>
QSharedPointer<X> staticCast() const
@@ -327,24 +498,73 @@ public:
return qSharedPointerConstCast<X, T>(*this);
}
+#ifndef QT_NO_QOBJECT
+ template <class X>
+ QSharedPointer<X> objectCast() const
+ {
+ return qSharedPointerObjectCast<X, T>(*this);
+ }
+#endif
+
inline void clear() { *this = QSharedPointer<T>(); }
QWeakPointer<T> toWeakRef() const;
+
+protected:
+ inline explicit QSharedPointer(Qt::Initialization i) : BaseClass(i) {}
+
+public:
+ static inline QSharedPointer<T> create()
+ {
+ QSharedPointer<T> result(Qt::Uninitialized);
+ result.internalCreate();
+
+ // now initialize the data
+ new (result.data()) T();
+ result.internalFinishConstruction(result.data());
+ return result;
+ }
};
template <class T>
class QWeakPointer
{
+#ifndef Q_CC_NOKIAX86
typedef T *QWeakPointer:: *RestrictedBool;
+#endif
typedef QtSharedPointer::ExternalRefCountData Data;
public:
+ typedef T element_type;
+ typedef T value_type;
+ typedef value_type *pointer;
+ typedef const value_type *const_pointer;
+ typedef value_type &reference;
+ typedef const value_type &const_reference;
+ typedef ptrdiff_t difference_type;
+
inline bool isNull() const { return d == 0 || d->strongref == 0 || value == 0; }
+#ifndef Q_CC_NOKIAX86
inline operator RestrictedBool() const { return isNull() ? 0 : &QWeakPointer::value; }
+#else
+ inline operator bool() const { return isNull() ? 0 : &QWeakPointer::value; }
+#endif
inline bool operator !() const { return isNull(); }
+ inline T *data() const { return d == 0 || d->strongref == 0 ? 0 : value; }
inline QWeakPointer() : d(0), value(0) { }
inline ~QWeakPointer() { if (d && !d->weakref.deref()) delete d; }
+
+#ifndef QT_NO_QOBJECT
+ // special constructor that is enabled only if X derives from QObject
+ template <class X>
+ inline QWeakPointer(X *ptr) : d(ptr ? d->getAndRef(ptr) : 0), value(ptr)
+ { }
+#endif
+ template <class X>
+ inline QWeakPointer &operator=(X *ptr)
+ { return *this = QWeakPointer(ptr); }
+
inline QWeakPointer(const QWeakPointer<T> &o) : d(o.d), value(o.value)
{ if (d) d->weakref.ref(); }
inline QWeakPointer<T> &operator=(const QWeakPointer<T> &o)
@@ -396,7 +616,7 @@ public:
template <class X>
inline bool operator==(const QSharedPointer<X> &o) const
- { return d == o.d && value == static_cast<const T *>(o.data()); }
+ { return d == o.d; }
template <class X>
inline bool operator!=(const QSharedPointer<X> &o) const
@@ -406,12 +626,16 @@ public:
inline QSharedPointer<T> toStrongRef() const { return QSharedPointer<T>(*this); }
+#if defined(QWEAKPOINTER_ENABLE_ARROW)
+ inline T *operator->() const { return data(); }
+#endif
+
private:
#if defined(Q_NO_TEMPLATE_FRIENDS)
public:
#else
- template <class X, class Y> friend QSharedPointer<X> QtSharedPointer::qStrongRefFromWeakHelper(const QWeakPointer<Y> &src, X *);
+ template <class X> friend class QSharedPointer;
#endif
inline void internalSet(Data *o, T *actual)
@@ -473,60 +697,31 @@ bool operator!=(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2)
return ptr2 != ptr1;
}
+template <class T, class X>
+Q_INLINE_TEMPLATE typename T::difference_type operator-(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
+{
+ return ptr1.data() - ptr2.data();
+}
+
template <class T>
Q_INLINE_TEMPLATE QWeakPointer<T> QSharedPointer<T>::toWeakRef() const
{
return QWeakPointer<T>(*this);
}
+template <class T>
+inline void qSwap(QSharedPointer<T> &p1, QSharedPointer<T> &p2)
+{
+ p1.swap(p2);
+}
+
namespace QtSharedPointer {
// helper functions:
template <class X, class T>
- Q_INLINE_TEMPLATE X *qVerifyStaticCast(T *src, X *)
- {
- return static_cast<X *>(src); // if you get an error in this line, the cast is invalid
- }
- template <class X, class T>
- Q_INLINE_TEMPLATE X *qVerifyDynamicCast(T *src, X *)
- {
- return dynamic_cast<X *>(src); // if you get an error in this line, the cast is invalid
- }
- template <class X, class T>
- Q_INLINE_TEMPLATE X *qVerifyConstCast(T *src, X *)
- {
- return const_cast<X *>(src); // if you get an error in this line, the cast is invalid
- }
-
- template <class X, class T>
- Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerCastHelper(const QSharedPointer<T> &src, X *)
- {
- QSharedPointer<X> result;
- register T *ptr = src.data();
- result.internalSet(src.d, static_cast<X *>(ptr));
- return result;
- }
- template <class X, class T>
- Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerDynamicCastHelper(const QSharedPointer<T> &src, X *)
- {
- QSharedPointer<X> result;
- register T *ptr = src.data();
- result.internalSet(src.d, dynamic_cast<X *>(ptr));
- return result;
- }
- template <class X, class T>
- Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerConstCastHelper(const QSharedPointer<T> &src, X *)
- {
- QSharedPointer<X> result;
- register T *ptr = src.data();
- result.internalSet(src.d, const_cast<X *>(ptr));
- return result;
- }
- template <class X, class T>
- Q_INLINE_TEMPLATE QSharedPointer<X> qStrongRefFromWeakHelper
- (const QT_PREPEND_NAMESPACE(QWeakPointer<T>) &src, X *)
+ Q_INLINE_TEMPLATE QSharedPointer<X> copyAndSetPointer(X *ptr, const QSharedPointer<T> &src)
{
QSharedPointer<X> result;
- result.internalSet(src.d, src.value);
+ result.internalSet(src.d, ptr);
return result;
}
}
@@ -535,9 +730,8 @@ namespace QtSharedPointer {
template <class X, class T>
Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerCast(const QSharedPointer<T> &src)
{
- X *x = 0;
- QtSharedPointer::qVerifyStaticCast(src.data(), x);
- return QtSharedPointer::qSharedPointerCastHelper(src, x);
+ register X *ptr = static_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
+ return QtSharedPointer::copyAndSetPointer(ptr, src);
}
template <class X, class T>
Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerCast(const QWeakPointer<T> &src)
@@ -548,8 +742,8 @@ Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerCast(const QWeakPointer<T> &sr
template <class X, class T>
Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerDynamicCast(const QSharedPointer<T> &src)
{
- X *x = 0;
- return QtSharedPointer::qSharedPointerDynamicCastHelper(src, x);
+ register X *ptr = dynamic_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
+ return QtSharedPointer::copyAndSetPointer(ptr, src);
}
template <class X, class T>
Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerDynamicCast(const QWeakPointer<T> &src)
@@ -560,14 +754,13 @@ Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerDynamicCast(const QWeakPointer
template <class X, class T>
Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerConstCast(const QSharedPointer<T> &src)
{
- X *x = 0;
- return QtSharedPointer::qSharedPointerConstCastHelper(src, x);
+ register X *ptr = const_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
+ return QtSharedPointer::copyAndSetPointer(ptr, src);
}
template <class X, class T>
Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerConstCast(const QWeakPointer<T> &src)
{
- X *x = 0;
- return QtSharedPointer::qSharedPointerConstCastHelper(src, x);
+ return qSharedPointerConstCast<X, T>(src.toStrongRef());
}
template <class X, class T>
@@ -577,6 +770,34 @@ QWeakPointer<X> qWeakPointerCast(const QSharedPointer<T> &src)
return qSharedPointerCast<X, T>(src).toWeakRef();
}
+#ifndef QT_NO_QOBJECT
+template <class X, class T>
+Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerObjectCast(const QSharedPointer<T> &src)
+{
+ register X *ptr = qobject_cast<X *>(src.data());
+ return QtSharedPointer::copyAndSetPointer(ptr, src);
+}
+template <class X, class T>
+Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerObjectCast(const QWeakPointer<T> &src)
+{
+ return qSharedPointerObjectCast<X>(src.toStrongRef());
+}
+
+template <class X, class T>
+inline QSharedPointer<typename QtSharedPointer::RemovePointer<X>::Type>
+qobject_cast(const QSharedPointer<T> &src)
+{
+ return qSharedPointerObjectCast<typename QtSharedPointer::RemovePointer<X>::Type, T>(src);
+}
+template <class X, class T>
+inline QSharedPointer<typename QtSharedPointer::RemovePointer<X>::Type>
+qobject_cast(const QWeakPointer<T> &src)
+{
+ return qSharedPointerObjectCast<typename QtSharedPointer::RemovePointer<X>::Type, T>(src);
+}
+
+#endif
+
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/corelib/tools/qsize.cpp b/src/corelib/tools/qsize.cpp
index 0323fe0e37..dcbcbfcf20 100644
--- a/src/corelib/tools/qsize.cpp
+++ b/src/corelib/tools/qsize.cpp
@@ -47,7 +47,7 @@ QT_BEGIN_NAMESPACE
/*!
\class QSize
- \ingroup multimedia
+ \ingroup painting
\brief The QSize class defines the size of a two-dimensional
object using integer point precision.
@@ -432,7 +432,7 @@ QDebug operator<<(QDebug dbg, const QSize &s) {
\brief The QSizeF class defines the size of a two-dimensional object
using floating point precision.
- \ingroup multimedia
+ \ingroup painting
A size is specified by a width() and a height(). It can be set in
the constructor and changed using the setWidth(), setHeight(), or
diff --git a/src/corelib/tools/qsize.h b/src/corelib/tools/qsize.h
index e89f93cec2..53bdd9a7ac 100644
--- a/src/corelib/tools/qsize.h
+++ b/src/corelib/tools/qsize.h
@@ -98,8 +98,10 @@ Q_DECLARE_TYPEINFO(QSize, Q_MOVABLE_TYPE);
QSize stream functions
*****************************************************************************/
+#ifndef QT_NO_DATASTREAM
Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QSize &);
Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QSize &);
+#endif
/*****************************************************************************
@@ -171,14 +173,14 @@ inline const QSize operator*(qreal c, const QSize &s)
inline QSize &QSize::operator/=(qreal c)
{
- Q_ASSERT(!qFuzzyCompare(c + 1, 1));
+ Q_ASSERT(!qFuzzyIsNull(c));
wd = qRound(wd/c); ht = qRound(ht/c);
return *this;
}
inline const QSize operator/(const QSize &s, qreal c)
{
- Q_ASSERT(!qFuzzyCompare(c + 1, 1));
+ Q_ASSERT(!qFuzzyIsNull(c));
return QSize(qRound(s.wd/c), qRound(s.ht/c));
}
@@ -249,8 +251,10 @@ Q_DECLARE_TYPEINFO(QSizeF, Q_MOVABLE_TYPE);
QSizeF stream functions
*****************************************************************************/
+#ifndef QT_NO_DATASTREAM
Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QSizeF &);
Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QSizeF &);
+#endif
/*****************************************************************************
@@ -327,14 +331,14 @@ inline const QSizeF operator*(qreal c, const QSizeF &s)
inline QSizeF &QSizeF::operator/=(qreal c)
{
- Q_ASSERT(!qFuzzyCompare(c + 1, 1));
+ Q_ASSERT(!qFuzzyIsNull(c));
wd = wd/c; ht = ht/c;
return *this;
}
inline const QSizeF operator/(const QSizeF &s, qreal c)
{
- Q_ASSERT(!qFuzzyCompare(c + 1, 1));
+ Q_ASSERT(!qFuzzyIsNull(c));
return QSizeF(s.wd/c, s.ht/c);
}
diff --git a/src/corelib/tools/qstack.cpp b/src/corelib/tools/qstack.cpp
index b7609c962a..29630dbd55 100644
--- a/src/corelib/tools/qstack.cpp
+++ b/src/corelib/tools/qstack.cpp
@@ -45,7 +45,7 @@
\ingroup tools
\ingroup shared
- \mainclass
+
\reentrant
QStack\<T\> is one of Qt's generic \l{container classes}. It implements
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index 2515fc47a7..56caa724a5 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ -45,6 +45,7 @@
#ifndef QT_NO_TEXTCODEC
#include <qtextcodec.h>
#endif
+#include <private/qutfcodec_p.h>
#include <qdatastream.h>
#include <qlist.h>
#include "qlocale.h"
@@ -195,6 +196,68 @@ static int ucstrnicmp(const ushort *a, const ushort *b, int l)
return ucstricmp(a, a + l, b, b + l);
}
+static bool qMemEquals(const quint16 *a, const quint16 *b, int length)
+{
+ // Benchmarking indicates that doing memcmp is much slower than
+ // executing the comparison ourselves.
+ // To make it even faster, we do a 32-bit comparison, comparing
+ // twice the amount of data as a normal word-by-word comparison.
+ //
+ // Benchmarking results on a 2.33 GHz Core2 Duo, with a 64-QChar
+ // block of data, with 4194304 iterations (per iteration):
+ // operation usec cpu ticks
+ // memcmp 330 710
+ // 16-bit 79 167-171
+ // 32-bit aligned 49 105-109
+ //
+ // Testing also indicates that unaligned 32-bit loads are as
+ // performant as 32-bit aligned.
+ if (a == b || !length)
+ return true;
+
+ register union {
+ const quint16 *w;
+ const quint32 *d;
+ quintptr value;
+ } sa, sb;
+ sa.w = a;
+ sb.w = b;
+
+ // check alignment
+ if ((sa.value & 2) == (sb.value & 2)) {
+ // both addresses have the same alignment
+ if (sa.value & 2) {
+ // both addresses are not aligned to 4-bytes boundaries
+ // compare the first character
+ if (*sa.w != *sb.w)
+ return false;
+ --length;
+ ++sa.w;
+ ++sb.w;
+
+ // now both addresses are 4-bytes aligned
+ }
+
+ // both addresses are 4-bytes aligned
+ // do a fast 32-bit comparison
+ register const quint32 *e = sa.d + (length >> 1);
+ for ( ; sa.d != e; ++sa.d, ++sb.d) {
+ if (*sa.d != *sb.d)
+ return false;
+ }
+
+ // do we have a tail?
+ return (length & 1) ? *sa.w == *sb.w : true;
+ } else {
+ // one of the addresses isn't 4-byte aligned but the other is
+ register const quint16 *e = sa.w + length;
+ for ( ; sa.w != e; ++sa.w, ++sb.w) {
+ if (*sa.w != *sb.w)
+ return false;
+ }
+ }
+ return true;
+}
/*!
\internal
@@ -296,7 +359,7 @@ const QString::Null QString::null = { };
\internal
- \ingroup text
+ \ingroup string-processing
When you get an object of type QCharRef, if you can assign to it,
the assignment will apply to the character in the string from
@@ -318,8 +381,8 @@ const QString::Null QString::null = { };
\ingroup tools
\ingroup shared
- \ingroup text
- \mainclass
+ \ingroup string-processing
+
QString stores a string of 16-bit \l{QChar}s, where each QChar
corresponds one Unicode 4.0 character. (Unicode characters
@@ -601,6 +664,74 @@ const QString::Null QString::null = { };
formats, the \e precision represents the maximum number of
significant digits (trailing zeroes are omitted).
+ \section1 More Efficient String Construction
+
+ Using the QString \c{'+'} operator, it is easy to construct a
+ complex string from multiple substrings. You will often write code
+ like this:
+
+ \snippet doc/src/snippets/qstring/stringbuilder.cpp 0
+
+ There is nothing wrong with either of these string constructions,
+ but there are a few hidden inefficiencies. Beginning with Qt 4.6,
+ you can eliminate them.
+
+ First, multiple uses of the \c{'+'} operator usually means
+ multiple memory allocations. When concatenating \e{n} substrings,
+ where \e{n > 2}, there can be as many as \e{n - 1} calls to the
+ memory allocator.
+
+ Second, QLatin1String does not store its length internally but
+ calls qstrlen() when it needs to know its length.
+
+ In 4.6, an internal template class \c{QStringBuilder} has been
+ added along with a few helper functions. This class is marked
+ internal and does not appear in the documentation, because you
+ aren't meant to instantiate it in your code. Its use will be
+ automatic, as described below. The class is found in
+ \c {src/corelib/tools/qstringbuilder.cpp} if you want to have a
+ look at it.
+
+ \c{QStringBuilder} uses expression templates and reimplements the
+ \c{'%'} operator so that when you use \c{'%'} for string
+ concatenation instead of \c{'+'}, multiple substring
+ concatenations will be postponed until the final result is about
+ to be assigned to a QString. At this point, the amount of memory
+ required for the final result is known. The memory allocator is
+ then called \e{once} to get the required space, and the substrings
+ are copied into it one by one.
+
+ \c{QLatin1Literal} is a second internal class that can replace
+ QLatin1String, which can't be changed for compatibility reasons.
+ \c{QLatin1Literal} stores its length, thereby saving time when
+ \c{QStringBuilder} computes the amount of memory required for the
+ final string.
+
+ Additional efficiency is gained by inlining and reduced reference
+ counting (the QString created from a \c{QStringBuilder} typically
+ has a ref count of 1, whereas QString::append() needs an extra
+ test).
+
+ There are three ways you can access this improved method of string
+ construction. The straightforward way is to include
+ \c{QStringBuilder} wherever you want to use it, and use the
+ \c{'%'} operator instead of \c{'+'} when concatenating strings:
+
+ \snippet doc/src/snippets/qstring/stringbuilder.cpp 5
+
+ A more global approach is to include this define:
+
+ \snippet doc/src/snippets/qstring/stringbuilder.cpp 3
+
+ and use \c{'%'} instead of \c{'+'} for string concatenation
+ everywhere. The third approach, which is the most convenient but
+ not entirely source compatible, is to include two defines:
+
+ \snippet doc/src/snippets/qstring/stringbuilder.cpp 4
+
+ and the \c{'+'} will automatically be performed as the
+ \c{QStringBuilder} \c{'%'} everywhere.
+
\sa fromRawData(), QChar, QLatin1String, QByteArray, QStringRef
*/
@@ -834,7 +965,8 @@ int QString::toWCharArray(wchar_t *array) const
Constructs a string initialized with the first \a size characters
of the QChar array \a unicode.
- QString makes a deep copy of the string data.
+ QString makes a deep copy of the string data. The unicode data is copied as
+ is and the Byte Order Mark is preserved if present.
*/
QString::QString(const QChar *unicode, int size)
{
@@ -846,6 +978,7 @@ QString::QString(const QChar *unicode, int size)
d->ref.ref();
} else {
d = (Data*) qMalloc(sizeof(Data)+size*sizeof(QChar));
+ Q_CHECK_PTR(d);
d->ref = 1;
d->alloc = d->size = size;
d->clean = d->asciiCache = d->simpletext = d->righttoleft = d->capacity = 0;
@@ -869,6 +1002,7 @@ QString::QString(int size, QChar ch)
d->ref.ref();
} else {
d = (Data*) qMalloc(sizeof(Data)+size*sizeof(QChar));
+ Q_CHECK_PTR(d);
d->ref = 1;
d->alloc = d->size = size;
d->clean = d->asciiCache = d->simpletext = d->righttoleft = d->capacity = 0;
@@ -882,6 +1016,23 @@ QString::QString(int size, QChar ch)
}
}
+/*! \fn QString::QString(int size, Qt::Initialization)
+ \internal
+
+ Constructs a string of the given \a size without initializing the
+ characters. This is only used in \c QStringBuilder::toString().
+*/
+QString::QString(int size, Qt::Initialization)
+{
+ d = (Data*) qMalloc(sizeof(Data)+size*sizeof(QChar));
+ Q_CHECK_PTR(d);
+ d->ref = 1;
+ d->alloc = d->size = size;
+ d->clean = d->asciiCache = d->simpletext = d->righttoleft = d->capacity = 0;
+ d->data = d->array;
+ d->array[size] = '\0';
+}
+
/*! \fn QString::QString(const QLatin1String &str)
Constructs a copy of the Latin-1 string \a str.
@@ -894,7 +1045,9 @@ QString::QString(int size, QChar ch)
*/
QString::QString(QChar ch)
{
- d = (Data *)qMalloc(sizeof(Data) + sizeof(QChar));
+ void *buf = qMalloc(sizeof(Data) + sizeof(QChar));
+ Q_CHECK_PTR(buf);
+ d = reinterpret_cast<Data *>(buf);
d->ref = 1;
d->alloc = d->size = 1;
d->clean = d->asciiCache = d->simpletext = d->righttoleft = d->capacity = 0;
@@ -1064,8 +1217,7 @@ void QString::realloc(int alloc)
{
if (d->ref != 1 || d->data != d->array) {
Data *x = static_cast<Data *>(qMalloc(sizeof(Data) + alloc * sizeof(QChar)));
- if (!x)
- return;
+ Q_CHECK_PTR(x);
x->size = qMin(alloc, d->size);
::memcpy(x->array, d->data, x->size * sizeof(QChar));
x->array[x->size] = 0;
@@ -1087,12 +1239,9 @@ void QString::realloc(int alloc)
asciiCache->remove(d);
}
#endif
- Data *x = static_cast<Data *>(qRealloc(d, sizeof(Data) + alloc * sizeof(QChar)));
- if (!x)
- return;
- x->alloc = alloc;
- x->data = x->array;
- d = x;
+ d = static_cast<Data *>(q_check_ptr(qRealloc(d, sizeof(Data) + alloc * sizeof(QChar))));
+ d->alloc = alloc;
+ d->data = d->array;
}
}
@@ -1246,6 +1395,7 @@ QString& QString::insert(int i, const QChar *unicode, int size)
if (s >= d->data && s < d->data + d->alloc) {
// Part of me - take a copy
ushort *tmp = static_cast<ushort *>(qMalloc(size * sizeof(QChar)));
+ Q_CHECK_PTR(tmp);
memcpy(tmp, s, size * sizeof(QChar));
insert(i, reinterpret_cast<const QChar *>(tmp), size);
qFree(tmp);
@@ -1600,51 +1750,69 @@ QString &QString::replace(const QString &before, const QString &after, Qt::CaseS
*/
void QString::replace_helper(uint *indices, int nIndices, int blen, const QChar *after, int alen)
{
- if (blen == alen) {
- detach();
- for (int i = 0; i < nIndices; ++i)
- memcpy(d->data + indices[i], after, alen * sizeof(QChar));
- } else if (alen < blen) {
+ // copy *after in case it lies inside our own d->data area
+ // (which we could possibly invalidate via a realloc or corrupt via memcpy operations.)
+ QChar *afterBuffer = const_cast<QChar *>(after);
+ if (after >= reinterpret_cast<QChar *>(d->data) && after < reinterpret_cast<QChar *>(d->data) + d->size) {
+ afterBuffer = static_cast<QChar *>(qMalloc(alen*sizeof(QChar)));
+ Q_CHECK_PTR(afterBuffer);
+ ::memcpy(afterBuffer, after, alen*sizeof(QChar));
+ }
+
+ QT_TRY {
detach();
- uint to = indices[0];
- if (alen)
- memcpy(d->data+to, after, alen*sizeof(QChar));
- to += alen;
- uint movestart = indices[0] + blen;
- for (int i = 1; i < nIndices; ++i) {
- int msize = indices[i] - movestart;
- if (msize > 0) {
- memmove(d->data + to, d->data + movestart, msize * sizeof(QChar));
- to += msize;
+ if (blen == alen) {
+ // replace in place
+ for (int i = 0; i < nIndices; ++i)
+ memcpy(d->data + indices[i], afterBuffer, alen * sizeof(QChar));
+ } else if (alen < blen) {
+ // replace from front
+ uint to = indices[0];
+ if (alen)
+ memcpy(d->data+to, after, alen*sizeof(QChar));
+ to += alen;
+ uint movestart = indices[0] + blen;
+ for (int i = 1; i < nIndices; ++i) {
+ int msize = indices[i] - movestart;
+ if (msize > 0) {
+ memmove(d->data + to, d->data + movestart, msize * sizeof(QChar));
+ to += msize;
+ }
+ if (alen) {
+ memcpy(d->data + to, afterBuffer, alen*sizeof(QChar));
+ to += alen;
+ }
+ movestart = indices[i] + blen;
}
- if (alen) {
- memcpy(d->data + to, after, alen*sizeof(QChar));
- to += alen;
+ int msize = d->size - movestart;
+ if (msize > 0)
+ memmove(d->data + to, d->data + movestart, msize * sizeof(QChar));
+ resize(d->size - nIndices*(blen-alen));
+ } else {
+ // replace from back
+ int adjust = nIndices*(alen-blen);
+ int newLen = d->size + adjust;
+ int moveend = d->size;
+ resize(newLen);
+
+ while (nIndices) {
+ --nIndices;
+ int movestart = indices[nIndices] + blen;
+ int insertstart = indices[nIndices] + nIndices*(alen-blen);
+ int moveto = insertstart + alen;
+ memmove(d->data + moveto, d->data + movestart,
+ (moveend - movestart)*sizeof(QChar));
+ memcpy(d->data + insertstart, afterBuffer, alen*sizeof(QChar));
+ moveend = movestart-blen;
}
- movestart = indices[i] + blen;
- }
- int msize = d->size - movestart;
- if (msize > 0)
- memmove(d->data + to, d->data + movestart, msize * sizeof(QChar));
- resize(d->size - nIndices*(blen-alen));
- } else {
- // we have a table of replacement positions, use them for fast replacing
- int adjust = nIndices*(alen-blen);
- int newLen = d->size + adjust;
- int moveend = d->size;
- resize(newLen);
-
- while (nIndices) {
- --nIndices;
- int movestart = indices[nIndices] + blen;
- int insertstart = indices[nIndices] + nIndices*(alen-blen);
- int moveto = insertstart + alen;
- memmove(d->data + moveto, d->data + movestart,
- (moveend - movestart)*sizeof(QChar));
- memcpy(d->data + insertstart, after, alen*sizeof(QChar));
- moveend = movestart-blen;
}
+ } QT_CATCH(const std::bad_alloc &) {
+ if (afterBuffer != after)
+ qFree(afterBuffer);
+ QT_RETHROW;
}
+ if (afterBuffer != after)
+ qFree(afterBuffer);
}
/*!
@@ -1672,21 +1840,7 @@ QString &QString::replace(const QChar *before, int blen,
if (alen == 0 && blen == 0)
return *this;
- // protect against before or after being part of this
- const QChar *a = after;
- const QChar *b = before;
- if (after >= (const QChar *)d->data && after < (const QChar *)d->data + d->size) {
- QChar *copy = (QChar *)malloc(alen*sizeof(QChar));
- memcpy(copy, after, alen*sizeof(QChar));
- a = copy;
- }
- if (before >= (const QChar *)d->data && before < (const QChar *)d->data + d->size) {
- QChar *copy = (QChar *)malloc(blen*sizeof(QChar));
- memcpy(copy, before, blen*sizeof(QChar));
- b = copy;
- }
-
- QStringMatcher matcher(b, blen, cs);
+ QStringMatcher matcher(before, blen, cs);
int index = 0;
while (1) {
@@ -1705,7 +1859,7 @@ QString &QString::replace(const QChar *before, int blen,
if (!pos)
break;
- replace_helper(indices, pos, blen, a, alen);
+ replace_helper(indices, pos, blen, after, alen);
if (index == -1)
break;
@@ -1713,11 +1867,6 @@ QString &QString::replace(const QChar *before, int blen,
index += pos*(alen-blen);
}
- if (a != after)
- ::free((QChar *)a);
- if (b != before)
- ::free((QChar *)b);
-
return *this;
}
@@ -1908,8 +2057,10 @@ QString &QString::replace(QChar c, const QLatin1String &after, Qt::CaseSensitivi
*/
bool QString::operator==(const QString &other) const
{
- return (size() == other.size()) &&
- (memcmp((char*)unicode(),(char*)other.unicode(), size()*sizeof(QChar))==0);
+ if (d->size != other.d->size)
+ return false;
+
+ return qMemEquals(d->data, other.d->data, d->size);
}
/*!
@@ -3136,7 +3287,7 @@ bool QString::startsWith(const QString& s, Qt::CaseSensitivity cs) const
if (s.d->size > d->size)
return false;
if (cs == Qt::CaseSensitive) {
- return memcmp((char*)d->data, (char*)s.d->data, s.d->size*sizeof(QChar)) == 0;
+ return qMemEquals(d->data, s.d->data, s.d->size);
} else {
uint last = 0;
uint olast = 0;
@@ -3207,7 +3358,7 @@ bool QString::endsWith(const QString& s, Qt::CaseSensitivity cs) const
if (pos < 0)
return false;
if (cs == Qt::CaseSensitive) {
- return memcmp((char*)&d->data[pos], (char*)s.d->data, s.d->size*sizeof(QChar)) == 0;
+ return qMemEquals(d->data + pos, s.d->data, s.d->size);
} else {
uint last = 0;
uint olast = 0;
@@ -3332,7 +3483,7 @@ QByteArray QString::toAscii() const
return toLatin1();
}
-#ifndef Q_WS_MAC
+#if !defined(Q_WS_MAC) && defined(Q_OS_UNIX)
static QByteArray toLocal8Bit_helper(const QChar *data, int length)
{
#ifndef QT_NO_TEXTCODEC
@@ -3450,6 +3601,7 @@ QString::Data *QString::fromLatin1_helper(const char *str, int size)
if (size < 0)
size = qstrlen(str);
d = static_cast<Data *>(qMalloc(sizeof(Data) + size * sizeof(QChar)));
+ Q_CHECK_PTR(d);
d->ref = 1;
d->alloc = d->size = size;
d->clean = d->asciiCache = d->simpletext = d->righttoleft = d->capacity = 0;
@@ -3457,7 +3609,7 @@ QString::Data *QString::fromLatin1_helper(const char *str, int size)
ushort *i = d->data;
d->array[size] = '\0';
while (size--)
- *i++ = (uchar)*str++;
+ *i++ = (uchar)*str++;
}
return d;
}
@@ -3566,13 +3718,13 @@ QByteArray qt_winQString2MB(const QChar *ch, int uclen)
BOOL used_def;
QByteArray mb(4096, 0);
int len;
- while (!(len=WideCharToMultiByte(CP_ACP, 0, (const WCHAR*)ch, uclen,
+ while (!(len=WideCharToMultiByte(CP_ACP, 0, (const wchar_t*)ch, uclen,
mb.data(), mb.size()-1, 0, &used_def)))
{
int r = GetLastError();
if (r == ERROR_INSUFFICIENT_BUFFER) {
mb.resize(1+WideCharToMultiByte(CP_ACP, 0,
- (const WCHAR*)ch, uclen,
+ (const wchar_t*)ch, uclen,
0, 0, 0, &used_def));
// and try again...
} else {
@@ -3593,9 +3745,9 @@ QString qt_winMB2QString(const char *mb, int mblen)
if (!mb || !mblen)
return QString();
const int wclen_auto = 4096;
- WCHAR wc_auto[wclen_auto];
+ wchar_t wc_auto[wclen_auto];
int wclen = wclen_auto;
- WCHAR *wc = wc_auto;
+ wchar_t *wc = wc_auto;
int len;
while (!(len=MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
mb, mblen, wc, wclen)))
@@ -3608,7 +3760,7 @@ QString qt_winMB2QString(const char *mb, int mblen)
} else {
wclen = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
mb, mblen, 0, 0);
- wc = new WCHAR[wclen];
+ wc = new wchar_t[wclen];
// and try again...
}
} else {
@@ -3651,11 +3803,6 @@ QString QString::fromLocal8Bit(const char *str, int size)
return QString();
if (size == 0 || (!*str && size < 0))
return QLatin1String("");
-#if defined(Q_OS_WIN32)
- if(QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based) {
- return qt_winMB2QString(str, size);
- }
-#endif
#if !defined(QT_NO_TEXTCODEC)
if (size < 0)
size = qstrlen(str);
@@ -3700,75 +3847,7 @@ QString QString::fromUtf8(const char *str, int size)
if (size < 0)
size = qstrlen(str);
- QString result;
- result.resize(size); // worst case
- ushort *qch = result.d->data;
- uint uc = 0;
- uint min_uc = 0;
- int need = 0;
- int error = -1;
- uchar ch;
- int i = 0;
-
- // skip utf8-encoded byte order mark
- if (size >= 3
- && (uchar)str[0] == 0xef && (uchar)str[1] == 0xbb && (uchar)str[2] == 0xbf)
- i += 3;
-
- for (; i < size; ++i) {
- ch = str[i];
- if (need) {
- if ((ch&0xc0) == 0x80) {
- uc = (uc << 6) | (ch & 0x3f);
- need--;
- if (!need) {
- if (uc > 0xffffU && uc < 0x110000U) {
- // surrogate pair
- *qch++ = QChar::highSurrogate(uc);
- uc = QChar::lowSurrogate(uc);
- } else if ((uc < min_uc) || (uc >= 0xd800 && uc <= 0xdfff) || (uc >= 0xfffe)) {
- // overlong seqence, UTF16 surrogate or BOM
- uc = QChar::ReplacementCharacter;
- }
- *qch++ = uc;
- }
- } else {
- i = error;
- need = 0;
- *qch++ = QChar::ReplacementCharacter;
- }
- } else {
- if (ch < 128) {
- *qch++ = ch;
- } else if ((ch & 0xe0) == 0xc0) {
- uc = ch & 0x1f;
- need = 1;
- error = i;
- min_uc = 0x80;
- } else if ((ch & 0xf0) == 0xe0) {
- uc = ch & 0x0f;
- need = 2;
- error = i;
- min_uc = 0x800;
- } else if ((ch&0xf8) == 0xf0) {
- uc = ch & 0x07;
- need = 3;
- error = i;
- min_uc = 0x10000;
- } else {
- // Error
- *qch++ = QChar::ReplacementCharacter;
- }
- }
- }
- if (need) {
- // we have some invalid characters remaining we need to add to the string
- for (int i = error; i < size; ++i)
- *qch++ = QChar::ReplacementCharacter;
- }
-
- result.truncate(qch - result.d->data);
- return result;
+ return QUtf8::convertToUnicode(str, size, 0);
}
/*!
@@ -3791,7 +3870,7 @@ QString QString::fromUtf16(const ushort *unicode, int size)
while (unicode[size] != 0)
++size;
}
- return QString((const QChar *)unicode, size);
+ return QUtf16::convertToUnicode((const char *)unicode, size*2, 0);
}
@@ -3815,21 +3894,7 @@ QString QString::fromUcs4(const uint *unicode, int size)
while (unicode[size] != 0)
++size;
}
-
- QString s;
- s.resize(size*2); // worst case
- ushort *uc = s.d->data;
- for (int i = 0; i < size; ++i) {
- uint u = unicode[i];
- if (u > 0xffff) {
- // decompose into a surrogate pair
- *uc++ = QChar::highSurrogate(u);
- u = QChar::lowSurrogate(u);
- }
- *uc++ = u;
- }
- s.resize(uc - s.d->data);
- return s;
+ return QUtf32::convertToUnicode((const char *)unicode, size*4, 0);
}
/*!
@@ -3880,8 +3945,7 @@ QString QString::simplified() const
{
if (d->size == 0)
return *this;
- QString result;
- result.resize(d->size);
+ QString result(d->size, Qt::Uninitialized);
const QChar *from = (const QChar*) d->data;
const QChar *fromend = (const QChar*) from+d->size;
int outc=0;
@@ -4552,16 +4616,7 @@ int QString::localeAwareCompare_helper(const QChar *data1, int length1,
return ucstrcmp(data1, length1, data2, length2);
#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
- int res;
- QT_WA({
- const TCHAR* s1 = (TCHAR*)data1;
- const TCHAR* s2 = (TCHAR*)data2;
- res = CompareStringW(GetUserDefaultLCID(), 0, s1, length1, s2, length2);
- } , {
- QByteArray s1 = toLocal8Bit_helper(data1, length1);
- QByteArray s2 = toLocal8Bit_helper(data2, length2);
- res = CompareStringA(GetUserDefaultLCID(), 0, s1.data(), s1.length(), s2.data(), s2.length());
- });
+ int res = CompareString(GetUserDefaultLCID(), 0, (wchar_t*)data1, length1, (wchar_t*)data2, length2);
switch (res) {
case CSTR_LESS_THAN:
@@ -4733,8 +4788,7 @@ QString QString::toLower() const
c = QChar::surrogateToUcs4(*(p - 1), c);
const QUnicodeTables::Properties *prop = qGetProp(c);
if (prop->lowerCaseDiff || prop->lowerCaseSpecial) {
- QString s;
- s.resize(d->size);
+ QString s(d->size, Qt::Uninitialized);
memcpy(s.d->data, d->data, (p - d->data)*sizeof(ushort));
ushort *pp = s.d->data + (p - d->data);
while (p < e) {
@@ -4825,8 +4879,7 @@ QString QString::toUpper() const
c = QChar::surrogateToUcs4(*(p - 1), c);
const QUnicodeTables::Properties *prop = qGetProp(c);
if (prop->upperCaseDiff || prop->upperCaseSpecial) {
- QString s;
- s.resize(d->size);
+ QString s(d->size, Qt::Uninitialized);
memcpy(s.d->data, d->data, (p - d->data)*sizeof(ushort));
ushort *pp = s.d->data + (p - d->data);
while (p < e) {
@@ -5977,6 +6030,7 @@ QString QString::repeated(int times) const
return result;
}
+void qt_string_normalize(QString *data, QString::NormalizationForm mode, QChar::UnicodeVersion version, int from);
/*!
\overload
\fn QString QString::normalized(NormalizationForm mode, QChar::UnicodeVersion version) const
@@ -5986,42 +6040,48 @@ QString QString::repeated(int times) const
*/
QString QString::normalized(QString::NormalizationForm mode, QChar::UnicodeVersion version) const
{
+ QString copy = *this;
+ qt_string_normalize(&copy, mode, version, 0);
+ return copy;
+}
+
+void qt_string_normalize(QString *data, QString::NormalizationForm mode, QChar::UnicodeVersion version, int from)
+{
bool simple = true;
- for (int i = 0; i < d->size; ++i) {
- if (d->data[i] >= 0x80) {
+ const QChar *p = data->constData();
+ int len = data->length();
+ for (int i = from; i < len; ++i) {
+ if (p[i].unicode() >= 0x80) {
simple = false;
break;
}
}
if (simple)
- return *this;
+ return;
- QString s = *this;
+ QString &s = *data;
if (version != CURRENT_VERSION) {
for (int i = 0; i < NumNormalizationCorrections; ++i) {
const NormalizationCorrection &n = uc_normalization_corrections[i];
if (n.version > version) {
+ int pos = from;
if (n.ucs4 > 0xffff) {
ushort ucs4High = QChar::highSurrogate(n.ucs4);
ushort ucs4Low = QChar::lowSurrogate(n.ucs4);
ushort oldHigh = QChar::highSurrogate(n.old_mapping);
ushort oldLow = QChar::lowSurrogate(n.old_mapping);
- int pos = 0;
- while (pos < s.d->size - 1) {
- if (s.d->data[pos] == ucs4High && s.d->data[pos + 1] == ucs4Low) {
- s.detach();
- s.d->data[pos] = oldHigh;
- s.d->data[pos + 1] = oldLow;
+ while (pos < s.length() - 1) {
+ if (s.at(pos).unicode() == ucs4High && s.at(pos + 1).unicode() == ucs4Low) {
+ s[pos] = oldHigh;
+ s[pos + 1] = oldLow;
++pos;
}
++pos;
}
} else {
- int pos = 0;
- while (pos < s.d->size) {
- if (s.d->data[pos] == n.ucs4) {
- s.detach();
- s.d->data[pos] = n.old_mapping;
+ while (pos < s.length()) {
+ if (s.at(pos).unicode() == n.ucs4) {
+ s[pos] = n.old_mapping;
}
++pos;
}
@@ -6029,15 +6089,14 @@ QString QString::normalized(QString::NormalizationForm mode, QChar::UnicodeVersi
}
}
}
- s = decomposeHelper(s, mode < QString::NormalizationForm_KD, version);
+ decomposeHelper(data, mode < QString::NormalizationForm_KD, version, from);
- s = canonicalOrderHelper(s, version);
+ canonicalOrderHelper(data, version, from);
if (mode == QString::NormalizationForm_D || mode == QString::NormalizationForm_KD)
- return s;
-
- return composeHelper(s);
+ return;
+ composeHelper(data, from);
}
@@ -6123,8 +6182,7 @@ static QString replaceArgEscapes(const QString &s, const ArgEscapeData &d, int f
+ d.locale_occurrences
*qMax(abs_field_width, larg.length());
- QString result;
- result.resize(result_len);
+ QString result(result_len, Qt::Uninitialized);
QChar *result_buff = (QChar*) result.unicode();
QChar *rc = result_buff;
@@ -6423,7 +6481,7 @@ QString QString::arg(qlonglong a, int fieldWidth, int base, const QChar &fillCha
ArgEscapeData d = findArgEscapes(*this);
if (d.occurrences == 0) {
- qWarning("QString::arg: Argument missing: %s, %lld", toLocal8Bit().data(), a);
+ qWarning() << "QString::arg: Argument missing:" << *this << ',' << a;
return *this;
}
@@ -6466,7 +6524,7 @@ QString QString::arg(qulonglong a, int fieldWidth, int base, const QChar &fillCh
ArgEscapeData d = findArgEscapes(*this);
if (d.occurrences == 0) {
- qWarning("QString::arg: Argument missing: %s, %llu", toLocal8Bit().data(), a);
+ qWarning() << "QString::arg: Argument missing:" << *this << ',' << a;
return *this;
}
@@ -6867,6 +6925,7 @@ void QString::updateProperties() const
QString QString::fromRawData(const QChar *unicode, int size)
{
Data *x = static_cast<Data *>(qMalloc(sizeof(Data)));
+ Q_CHECK_PTR(x);
if (unicode) {
x->data = (ushort *)unicode;
} else {
@@ -6883,7 +6942,7 @@ QString QString::fromRawData(const QChar *unicode, int size)
/*! \class QLatin1String
\brief The QLatin1String class provides a thin wrapper around an ASCII/Latin-1 encoded string literal.
- \ingroup text
+ \ingroup string-processing
\reentrant
Many of QString's member functions are overloaded to accept
@@ -7505,7 +7564,7 @@ QDataStream &operator>>(QDataStream &in, QString &str)
\brief The QStringRef class provides a thin wrapper around QString substrings.
\reentrant
\ingroup tools
- \ingroup text
+ \ingroup string-processing
QStringRef provides a read-only subset of the QString API.
@@ -7692,7 +7751,8 @@ QString QStringRef::toString() const {
*/
bool operator==(const QStringRef &s1,const QStringRef &s2)
{ return (s1.size() == s2.size() &&
- (memcmp((char*)s1.unicode(), (char*)s2.unicode(), s1.size()*sizeof(QChar))==0)); }
+ qMemEquals((const ushort *)s1.unicode(), (const ushort *)s2.unicode(), s1.size()));
+}
/*! \relates QStringRef
@@ -7701,7 +7761,8 @@ bool operator==(const QStringRef &s1,const QStringRef &s2)
*/
bool operator==(const QString &s1,const QStringRef &s2)
{ return (s1.size() == s2.size() &&
- (memcmp((char*)s1.unicode(), (char*)s2.unicode(), s1.size()*sizeof(QChar))==0)); }
+ qMemEquals((const ushort *)s1.unicode(), (const ushort *)s2.unicode(), s1.size()));
+}
/*! \relates QStringRef
diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h
index 303f79bb08..ce70707b83 100644
--- a/src/corelib/tools/qstring.h
+++ b/src/corelib/tools/qstring.h
@@ -579,6 +579,8 @@ public:
bool isSimpleText() const { if (!d->clean) updateProperties(); return d->simpletext; }
bool isRightToLeft() const { if (!d->clean) updateProperties(); return d->righttoleft; }
+ QString(int size, Qt::Initialization);
+
private:
#if defined(QT_NO_CAST_FROM_ASCII) && !defined(Q_NO_DECLARED_NOT_DEFINED)
QString &operator+=(const char *s);
@@ -1001,13 +1003,15 @@ inline int QByteArray::findRev(const QString &s, int from) const
# endif // QT3_SUPPORT
#endif // QT_NO_CAST_TO_ASCII
+#ifndef QT_USE_FAST_OPERATOR_PLUS
+# ifndef QT_USE_FAST_CONCATENATION
inline const QString operator+(const QString &s1, const QString &s2)
{ QString t(s1); t += s2; return t; }
inline const QString operator+(const QString &s1, QChar s2)
{ QString t(s1); t += s2; return t; }
inline const QString operator+(QChar s1, const QString &s2)
{ QString t(s1); t += s2; return t; }
-#ifndef QT_NO_CAST_FROM_ASCII
+# ifndef QT_NO_CAST_FROM_ASCII
inline QT_ASCII_CAST_WARN const QString operator+(const QString &s1, const char *s2)
{ QString t(s1); t += QString::fromAscii(s2); return t; }
inline QT_ASCII_CAST_WARN const QString operator+(const char *s1, const QString &s2)
@@ -1020,7 +1024,9 @@ inline QT_ASCII_CAST_WARN const QString operator+(const QByteArray &ba, const QS
{ QString t = QString::fromAscii(ba.constData(), qstrnlen(ba.constData(), ba.size())); t += s; return t; }
inline QT_ASCII_CAST_WARN const QString operator+(const QString &s, const QByteArray &ba)
{ QString t(s); t += QString::fromAscii(ba.constData(), qstrnlen(ba.constData(), ba.size())); return t; }
-#endif
+# endif // QT_NO_CAST_FROM_ASCII
+# endif // QT_USE_FAST_CONCATENATION
+#endif // QT_USE_FAST_OPERATOR_PLUS
#ifndef QT_NO_STL
inline std::string QString::toStdString() const
@@ -1231,4 +1237,8 @@ QT_END_NAMESPACE
QT_END_HEADER
+#ifdef QT_USE_FAST_CONCATENATION
+#include <QtCore/qstringbuilder.h>
+#endif
+
#endif // QSTRING_H
diff --git a/src/corelib/tools/qstringbuilder.cpp b/src/corelib/tools/qstringbuilder.cpp
new file mode 100644
index 0000000000..04fbb93540
--- /dev/null
+++ b/src/corelib/tools/qstringbuilder.cpp
@@ -0,0 +1,145 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qstringbuilder.h"
+
+/*!
+ \class QLatin1Literal
+ \internal
+ \reentrant
+ \since 4.6
+
+ \brief The QLatin1Literal class provides a thin wrapper around string
+ literals used in source code.
+
+ \ingroup tools
+ \ingroup shared
+ \ingroup string-processing
+
+
+ Unlike \c QLatin1String, a \c QLatin1Literal can retrieve its size
+ without iterating over the literal.
+
+ The main use of \c QLatin1Literal is in conjunction with \c QStringBuilder
+ to reduce the number of reallocations needed to build up a string from
+ smaller chunks.
+
+ \sa QStringBuilder, QLatin1String, QString, QStringRef
+*/
+
+/*! \fn int QLatin1Literal::size() const
+
+ Returns the number of characters in the literal \e{excluding} the trailing
+ NULL char.
+*/
+
+/*! \fn QLatin1Literal::QLatin1Literal(const char str)
+
+ Constructs a new literal from the string \a str.
+*/
+
+/*! \fn const char *QLatin1Literal::data() const
+
+ Returns a pointer to the first character of the string literal.
+ The string literal is terminated by a NUL character.
+*/
+
+/*!
+ \class QStringBuilder
+ \internal
+ \reentrant
+ \since 4.6
+
+ \brief The QStringBuilder class is a template class that provides a facility to build up QStrings from smaller chunks.
+
+ \ingroup tools
+ \ingroup shared
+ \ingroup string-processing
+
+
+ To build a QString by multiple concatenations, QString::operator+()
+ is typically used. This causes \e{n - 1} reallocations when building
+ a string from \e{n} chunks.
+
+ QStringBuilder uses expression templates to collect the individual
+ chunks, compute the total size, allocate the required amount of
+ memory for the final QString object, and copy the chunks into the
+ allocated memory.
+
+ The QStringBuilder class is not to be used explicitly in user
+ code. Instances of the class are created as return values of the
+ operator%() function, acting on objects of type QString,
+ QLatin1String, QLatin1Literal, QStringRef, QChar, QCharRef,
+ QLatin1Char, and \c char.
+
+ Concatenating strings with operator%() generally yields better
+ performance then using \c QString::operator+() on the same chunks
+ if there are three or more of them, and performs equally well in other
+ cases.
+
+ \sa QLatin1Literal, QString
+*/
+
+/*! \fn QStringBuilder::QStringBuilder(const A &a, const B &b)
+ Constructs a QStringBuilder from \a a and \a b.
+ */
+
+/* \fn QStringBuilder::operator%(const A &a, const B &b)
+
+ Returns a \c QStringBuilder object that is converted to a QString object
+ when assigned to a variable of QString type or passed to a function that
+ takes a QString parameter.
+
+ This function is usable with arguments of type \c QString,
+ \c QLatin1String, \c QLatin1Literal, \c QStringRef,
+ \c QChar, \c QCharRef, \c QLatin1Char, and \c char.
+*/
+
+/*! \fn QByteArray QStringBuilder::toLatin1() const
+ Returns a Latin-1 representation of the string as a QByteArray. The
+ returned byte array is undefined if the string contains non-Latin1
+ characters.
+ */
+
+/*! \fn QStringBuilder::operator QString() const
+
+ Converts the \c QLatin1Literal into a \c QString object.
+*/
diff --git a/src/corelib/tools/qstringbuilder.h b/src/corelib/tools/qstringbuilder.h
new file mode 100644
index 0000000000..9be57c5991
--- /dev/null
+++ b/src/corelib/tools/qstringbuilder.h
@@ -0,0 +1,260 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSTRINGBUILDER_H
+#define QSTRINGBUILDER_H
+
+#include <QtCore/qstring.h>
+
+#if defined(Q_CC_GNU) && !defined(Q_CC_INTEL)
+# if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ == 0)
+# include <QtCore/qmap.h>
+# endif
+#endif
+
+#include <string.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+// ### Qt 5: merge with QLatin1String
+class QLatin1Literal
+{
+public:
+ int size() const { return m_size; }
+ const char *data() const { return m_data; }
+
+ template <int N>
+ QLatin1Literal(const char (&str)[N])
+ : m_size(N - 1), m_data(str) {}
+
+private:
+ const int m_size;
+ const char *m_data;
+};
+
+
+template <typename T> struct QConcatenable {};
+
+template <typename A, typename B>
+class QStringBuilder
+{
+public:
+ QStringBuilder(const A &a_, const B &b_) : a(a_), b(b_) {}
+
+ operator QString() const
+ {
+ QString s(QConcatenable< QStringBuilder<A, B> >::size(*this),
+ Qt::Uninitialized);
+
+ QChar *d = s.data();
+ QConcatenable< QStringBuilder<A, B> >::appendTo(*this, d);
+ return s;
+ }
+ QByteArray toLatin1() const { return QString(*this).toLatin1(); }
+
+ const A &a;
+ const B &b;
+};
+
+
+template <> struct QConcatenable<char>
+{
+ typedef char type;
+ static int size(const char) { return 1; }
+ static inline void appendTo(const char c, QChar *&out)
+ {
+ *out++ = QLatin1Char(c);
+ }
+};
+
+template <> struct QConcatenable<QLatin1Char>
+{
+ typedef QLatin1Char type;
+ static int size(const QLatin1Char) { return 1; }
+ static inline void appendTo(const QLatin1Char c, QChar *&out)
+ {
+ *out++ = c;
+ }
+};
+
+template <> struct QConcatenable<QChar>
+{
+ typedef QChar type;
+ static int size(const QChar) { return 1; }
+ static inline void appendTo(const QChar c, QChar *&out)
+ {
+ *out++ = c;
+ }
+};
+
+template <> struct QConcatenable<QCharRef>
+{
+ typedef QCharRef type;
+ static int size(const QCharRef &) { return 1; }
+ static inline void appendTo(const QCharRef &c, QChar *&out)
+ {
+ *out++ = QChar(c);
+ }
+};
+
+template <> struct QConcatenable<QLatin1String>
+{
+ typedef QLatin1String type;
+ static int size(const QLatin1String &a) { return qstrlen(a.latin1()); }
+ static inline void appendTo(const QLatin1String &a, QChar *&out)
+ {
+ for (const char *s = a.latin1(); *s; )
+ *out++ = QLatin1Char(*s++);
+ }
+
+};
+
+template <> struct QConcatenable<QLatin1Literal>
+{
+ typedef QLatin1Literal type;
+ static int size(const QLatin1Literal &a) { return a.size(); }
+ static inline void appendTo(const QLatin1Literal &a, QChar *&out)
+ {
+ for (const char *s = a.data(); *s; )
+ *out++ = QLatin1Char(*s++);
+ }
+};
+
+template <> struct QConcatenable<QString>
+{
+ typedef QString type;
+ static int size(const QString &a) { return a.size(); }
+ static inline void appendTo(const QString &a, QChar *&out)
+ {
+ const int n = a.size();
+ memcpy(out, reinterpret_cast<const char*>(a.constData()), sizeof(QChar) * n);
+ out += n;
+ }
+};
+
+template <> struct QConcatenable<QStringRef>
+{
+ typedef QStringRef type;
+ static int size(const QStringRef &a) { return a.size(); }
+ static inline void appendTo(QStringRef a, QChar *&out)
+ {
+ const int n = a.size();
+ memcpy(out, reinterpret_cast<const char*>(a.constData()), sizeof(QChar) * n);
+ out += n;
+ }
+};
+
+#ifndef QT_NO_CAST_FROM_ASCII
+template <int N> struct QConcatenable<char[N]>
+{
+ typedef char type[N];
+ static int size(const char[N]) { return N - 1; }
+ static inline void appendTo(const char a[N], QChar *&out)
+ {
+ for (int i = 0; i < N - 1; ++i)
+ *out++ = QLatin1Char(a[i]);
+ }
+};
+
+template <> struct QConcatenable<const char *>
+{
+ typedef char const *type;
+ static int size(const char *a) { return qstrlen(a); }
+ static inline void appendTo(const char *a, QChar *&out)
+ {
+ while (*a)
+ *out++ = QLatin1Char(*a++);
+ }
+};
+
+template <> struct QConcatenable<QByteArray>
+{
+ typedef QByteArray type;
+ static int size(const QByteArray &ba) { return qstrnlen(ba.constData(), ba.size()); }
+ static inline void appendTo(const QByteArray &ba, QChar *&out)
+ {
+ const char *data = ba.constData();
+ while (*data)
+ *out++ = QLatin1Char(*data++);
+ }
+};
+#endif
+
+template <typename A, typename B>
+struct QConcatenable< QStringBuilder<A, B> >
+{
+ typedef QStringBuilder<A, B> type;
+ static int size(const type &p)
+ {
+ return QConcatenable<A>::size(p.a) + QConcatenable<B>::size(p.b);
+ }
+ static inline void appendTo(const QStringBuilder<A, B> &p, QChar *&out)
+ {
+ QConcatenable<A>::appendTo(p.a, out);
+ QConcatenable<B>::appendTo(p.b, out);
+ }
+};
+
+template <typename A, typename B>
+QStringBuilder<typename QConcatenable<A>::type, typename QConcatenable<B>::type>
+operator%(const A &a, const B &b)
+{
+ return QStringBuilder<A, B>(a, b);
+}
+
+#ifdef QT_USE_FAST_OPERATOR_PLUS
+template <typename A, typename B>
+QStringBuilder<typename QConcatenable<A>::type, typename QConcatenable<B>::type>
+operator+(const A &a, const B &b)
+{
+ return QStringBuilder<A, B>(a, b);
+}
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSTRINGBUILDER_H
diff --git a/src/corelib/tools/qstringlist.cpp b/src/corelib/tools/qstringlist.cpp
index 1430235e18..20c9bcec5d 100644
--- a/src/corelib/tools/qstringlist.cpp
+++ b/src/corelib/tools/qstringlist.cpp
@@ -41,6 +41,7 @@
#include <qstringlist.h>
#include <qset.h>
+#include <qstringmatcher.h>
QT_BEGIN_NAMESPACE
@@ -76,8 +77,8 @@ QT_BEGIN_NAMESPACE
\ingroup tools
\ingroup shared
- \ingroup text
- \mainclass
+ \ingroup string-processing
+
\reentrant
QStringList inherits from QList<QString>. Like QList, QStringList is
diff --git a/src/corelib/tools/qstringlist.h b/src/corelib/tools/qstringlist.h
index 49da145827..a0033fd2ea 100644
--- a/src/corelib/tools/qstringlist.h
+++ b/src/corelib/tools/qstringlist.h
@@ -47,7 +47,6 @@
#include <QtCore/qlist.h>
#include <QtCore/qregexp.h>
#include <QtCore/qstring.h>
-#include <QtCore/qstringmatcher.h>
#ifdef QT_INCLUDE_COMPAT
#include <Qt3Support/q3valuelist.h>
#endif
diff --git a/src/corelib/tools/qstringmatcher.cpp b/src/corelib/tools/qstringmatcher.cpp
index 38bcc67565..3e0edd0581 100644
--- a/src/corelib/tools/qstringmatcher.cpp
+++ b/src/corelib/tools/qstringmatcher.cpp
@@ -129,7 +129,7 @@ static inline int bm_find(const ushort *uc, uint l, int index, const ushort *puc
can be quickly matched in a Unicode string.
\ingroup tools
- \ingroup text
+ \ingroup string-processing
This class is useful when you have a sequence of \l{QChar}s that
you want to repeatedly match against some strings (perhaps in a
diff --git a/src/corelib/tools/qstringmatcher.h b/src/corelib/tools/qstringmatcher.h
index 7927996ede..cf01d07263 100644
--- a/src/corelib/tools/qstringmatcher.h
+++ b/src/corelib/tools/qstringmatcher.h
@@ -81,13 +81,14 @@ private:
// explicitely allow anonymous unions for RVCT to prevent compiler warnings
#pragma anon_unions
#endif
+ struct Data {
+ uchar q_skiptable[256];
+ const QChar *uc;
+ int len;
+ };
union {
uint q_data[256];
- struct {
- uchar q_skiptable[256];
- const QChar *uc;
- int len;
- } p;
+ Data p;
};
};
diff --git a/src/corelib/tools/qtextboundaryfinder.cpp b/src/corelib/tools/qtextboundaryfinder.cpp
index 3e156a6814..1b6b8602a4 100644
--- a/src/corelib/tools/qtextboundaryfinder.cpp
+++ b/src/corelib/tools/qtextboundaryfinder.cpp
@@ -38,11 +38,11 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-#include "private/qharfbuzz_p.h"
#include <QtCore/qtextboundaryfinder.h>
#include <QtCore/qvarlengtharray.h>
#include <private/qunicodetables_p.h>
#include <qdebug.h>
+#include "private/qharfbuzz_p.h"
QT_BEGIN_NAMESPACE
@@ -107,7 +107,7 @@ static void init(QTextBoundaryFinder::BoundaryType type, const QChar *chars, int
\since 4.4
\ingroup tools
\ingroup shared
- \ingroup text
+ \ingroup string-processing
\reentrant
QTextBoundaryFinder allows to find Unicode text boundaries in a
@@ -176,6 +176,7 @@ QTextBoundaryFinder::QTextBoundaryFinder(const QTextBoundaryFinder &other)
, freePrivate(true)
{
d = (QTextBoundaryFinderPrivate *) malloc(length*sizeof(HB_CharAttributes));
+ Q_CHECK_PTR(d);
memcpy(d, other.d, length*sizeof(HB_CharAttributes));
}
@@ -193,8 +194,11 @@ QTextBoundaryFinder &QTextBoundaryFinder::operator=(const QTextBoundaryFinder &o
length = other.length;
pos = other.pos;
freePrivate = true;
-
- d = (QTextBoundaryFinderPrivate *) realloc(d, length*sizeof(HB_CharAttributes));
+
+ QTextBoundaryFinderPrivate *newD = (QTextBoundaryFinderPrivate *)
+ realloc(d, length*sizeof(HB_CharAttributes));
+ Q_CHECK_PTR(newD);
+ d = newD;
memcpy(d, other.d, length*sizeof(HB_CharAttributes));
return *this;
@@ -221,6 +225,7 @@ QTextBoundaryFinder::QTextBoundaryFinder(BoundaryType type, const QString &strin
, freePrivate(true)
{
d = (QTextBoundaryFinderPrivate *) malloc(length*sizeof(HB_CharAttributes));
+ Q_CHECK_PTR(d);
init(t, chars, length, d->attributes);
}
@@ -248,6 +253,7 @@ QTextBoundaryFinder::QTextBoundaryFinder(BoundaryType type, const QChar *chars,
freePrivate = false;
} else {
d = (QTextBoundaryFinderPrivate *) malloc(length*sizeof(HB_CharAttributes));
+ Q_CHECK_PTR(d);
freePrivate = true;
}
init(t, chars, length, d->attributes);
diff --git a/src/corelib/tools/qtimeline.cpp b/src/corelib/tools/qtimeline.cpp
index 7b0d102676..052c45626a 100644
--- a/src/corelib/tools/qtimeline.cpp
+++ b/src/corelib/tools/qtimeline.cpp
@@ -48,20 +48,6 @@
QT_BEGIN_NAMESPACE
-static const qreal pi = qreal(3.14159265359);
-static const qreal halfPi = pi / qreal(2.0);
-
-
-static inline qreal qt_sinProgress(qreal value)
-{
- return qSin((value * pi) - halfPi) / 2 + qreal(0.5);
-}
-
-static inline qreal qt_smoothBeginEndMixFactor(qreal value)
-{
- return qMin(qMax(1 - value * 2 + qreal(0.3), qreal(0.0)), qreal(1.0));
-}
-
class QTimeLinePrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QTimeLine)
@@ -70,7 +56,7 @@ public:
: startTime(0), duration(1000), startFrame(0), endFrame(0),
updateInterval(1000 / 25),
totalLoopCount(1), currentLoopCount(0), currentTime(0), timerId(0),
- direction(QTimeLine::Forward), curveShape(QTimeLine::EaseInOutCurve),
+ direction(QTimeLine::Forward), easingCurve(QEasingCurve::InOutSine),
state(QTimeLine::NotRunning)
{ }
@@ -83,12 +69,11 @@ public:
int currentLoopCount;
int currentTime;
- int elapsedTime;
int timerId;
QTime timer;
QTimeLine::Direction direction;
- QTimeLine::CurveShape curveShape;
+ QEasingCurve easingCurve;
QTimeLine::State state;
inline void setState(QTimeLine::State newState)
{
@@ -180,7 +165,7 @@ void QTimeLinePrivate::setCurrentTime(int msecs)
\class QTimeLine
\brief The QTimeLine class provides a timeline for controlling animations.
\since 4.2
- \ingroup multimedia
+ \ingroup animation
It's most commonly used to animate a GUI control by calling a slot
periodically. You can construct a timeline by passing its duration in
@@ -226,7 +211,7 @@ void QTimeLinePrivate::setCurrentTime(int msecs)
applies an interpolation algorithm to generate these value. You can choose
from a set of predefined timeline algorithms by calling
setCurveShape().
-
+
Note that by default, QTimeLine uses the EaseInOut curve shape,
which provides a value that grows slowly, then grows steadily, and
finally grows slowly. For a custom timeline, you can reimplement
@@ -523,12 +508,70 @@ void QTimeLine::setUpdateInterval(int interval)
QTimeLine::CurveShape QTimeLine::curveShape() const
{
Q_D(const QTimeLine);
- return d->curveShape;
+ switch (d->easingCurve.type()) {
+ default:
+ case QEasingCurve::InOutSine:
+ return EaseInOutCurve;
+ case QEasingCurve::InCurve:
+ return EaseInCurve;
+ case QEasingCurve::OutCurve:
+ return EaseOutCurve;
+ case QEasingCurve::Linear:
+ return LinearCurve;
+ case QEasingCurve::SineCurve:
+ return SineCurve;
+ case QEasingCurve::CosineCurve:
+ return CosineCurve;
+ }
+ return EaseInOutCurve;
}
+
void QTimeLine::setCurveShape(CurveShape shape)
{
+ switch (shape) {
+ default:
+ case EaseInOutCurve:
+ setEasingCurve(QEasingCurve(QEasingCurve::InOutSine));
+ break;
+ case EaseInCurve:
+ setEasingCurve(QEasingCurve(QEasingCurve::InCurve));
+ break;
+ case EaseOutCurve:
+ setEasingCurve(QEasingCurve(QEasingCurve::OutCurve));
+ break;
+ case LinearCurve:
+ setEasingCurve(QEasingCurve(QEasingCurve::Linear));
+ break;
+ case SineCurve:
+ setEasingCurve(QEasingCurve(QEasingCurve::SineCurve));
+ break;
+ case CosineCurve:
+ setEasingCurve(QEasingCurve(QEasingCurve::CosineCurve));
+ break;
+ }
+}
+
+/*!
+ \property QTimeLine::easingCurve
+
+ \since 4.6
+
+ Specifies the easing curve that the timeline will use.
+ If both easing curve and curveShape are set, the last set property will
+ override the previous one. (If valueForTime() is reimplemented it will
+ override both)
+*/
+
+QEasingCurve QTimeLine::easingCurve() const
+{
+ Q_D(const QTimeLine);
+ return d->easingCurve;
+}
+
+void QTimeLine::setEasingCurve(const QEasingCurve& curve)
+{
Q_D(QTimeLine);
- d->curveShape = shape;
+ d->easingCurve = curve;
}
/*!
@@ -608,42 +651,8 @@ qreal QTimeLine::valueForTime(int msec) const
Q_D(const QTimeLine);
msec = qMin(qMax(msec, 0), d->duration);
- // Simple linear interpolation
qreal value = msec / qreal(d->duration);
-
- switch (d->curveShape) {
- case EaseInOutCurve:
- value = qt_sinProgress(value);
- break;
- // SmoothBegin blends Smooth and Linear Interpolation.
- // Progress 0 - 0.3 : Smooth only
- // Progress 0.3 - ~ 0.5 : Mix of Smooth and Linear
- // Progress ~ 0.5 - 1 : Linear only
- case EaseInCurve: {
- const qreal sinProgress = qt_sinProgress(value);
- const qreal linearProgress = value;
- const qreal mix = qt_smoothBeginEndMixFactor(value);
- value = sinProgress * mix + linearProgress * (1 - mix);
- break;
- }
- case EaseOutCurve: {
- const qreal sinProgress = qt_sinProgress(value);
- const qreal linearProgress = value;
- const qreal mix = qt_smoothBeginEndMixFactor(1 - value);
- value = sinProgress * mix + linearProgress * (1 - mix);
- break;
- }
- case SineCurve:
- value = (qSin(((msec * pi * 2) / d->duration) - pi/2) + 1) / 2;
- break;
- case CosineCurve:
- value = (qCos(((msec * pi * 2) / d->duration) - pi/2) + 1) / 2;
- break;
- default:
- break;
- }
-
- return value;
+ return d->easingCurve.valueForProgress(value);
}
/*!
@@ -653,6 +662,7 @@ qreal QTimeLine::valueForTime(int msec) const
second). You can change the update interval by calling
setUpdateInterval().
+ The timeline will start from position 0, or the end if going backward.
If you want to resume a stopped timeline without restarting, you can call
resume() instead.
@@ -665,10 +675,8 @@ void QTimeLine::start()
qWarning("QTimeLine::start: already running");
return;
}
- int curTime = d->currentTime;
- if (curTime == d->duration && d->direction == Forward)
- curTime = 0;
- else if (curTime == 0 && d->direction == Backward)
+ int curTime = 0;
+ if (d->direction == Backward)
curTime = d->duration;
d->timerId = startTimer(d->updateInterval);
d->startTime = curTime;
@@ -684,7 +692,7 @@ void QTimeLine::start()
frame and value at regular intervals.
In contrast to start(), this function does not restart the timeline before
- is resumes.
+ it resumes.
\sa start(), updateInterval(), frameChanged(), valueChanged()
*/
diff --git a/src/corelib/tools/qtimeline.h b/src/corelib/tools/qtimeline.h
index 37e072dcd3..d89b09a93a 100644
--- a/src/corelib/tools/qtimeline.h
+++ b/src/corelib/tools/qtimeline.h
@@ -42,6 +42,7 @@
#ifndef QTIMELINE_H
#define QTIMELINE_H
+#include <QtCore/qeasingcurve.h>
#include <QtCore/qobject.h>
QT_BEGIN_HEADER
@@ -60,6 +61,7 @@ class Q_CORE_EXPORT QTimeLine : public QObject
Q_PROPERTY(Direction direction READ direction WRITE setDirection)
Q_PROPERTY(int loopCount READ loopCount WRITE setLoopCount)
Q_PROPERTY(CurveShape curveShape READ curveShape WRITE setCurveShape)
+ Q_PROPERTY(QEasingCurve easingCurve READ easingCurve WRITE setEasingCurve)
public:
enum State {
NotRunning,
@@ -105,6 +107,9 @@ public:
CurveShape curveShape() const;
void setCurveShape(CurveShape shape);
+ QEasingCurve easingCurve() const;
+ void setEasingCurve(const QEasingCurve &curve);
+
int currentTime() const;
int currentFrame() const;
qreal currentValue() const;
diff --git a/src/corelib/tools/qunicodetables_p.h b/src/corelib/tools/qunicodetables_p.h
index ed28afbedd..e08e541899 100644
--- a/src/corelib/tools/qunicodetables_p.h
+++ b/src/corelib/tools/qunicodetables_p.h
@@ -178,7 +178,7 @@ namespace QUnicodeTables {
}
Q_CORE_EXPORT int QT_FASTCALL script(uint ucs4);
- Q_CORE_EXPORT_INLINE int QT_FASTCALL script(const QChar &ch) {
+ inline int script(const QChar &ch) {
return script(ch.unicode());
}
diff --git a/src/corelib/tools/qvarlengtharray.h b/src/corelib/tools/qvarlengtharray.h
index f27091337e..f7284a8598 100644
--- a/src/corelib/tools/qvarlengtharray.h
+++ b/src/corelib/tools/qvarlengtharray.h
@@ -52,6 +52,9 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Core)
+template<class T, int Prealloc>
+class QPodList;
+
// Prealloc = 256 by default, specified in qcontainerfwd.h
template<class T, int Prealloc>
class QVarLengthArray
@@ -122,6 +125,7 @@ public:
inline const T * constData() const { return ptr; }
private:
+ friend class QPodList<T, Prealloc>;
void realloc(int size, int alloc);
int a;
@@ -140,6 +144,7 @@ Q_INLINE_TEMPLATE QVarLengthArray<T, Prealloc>::QVarLengthArray(int asize)
: s(asize) {
if (s > Prealloc) {
ptr = reinterpret_cast<T *>(qMalloc(s * sizeof(T)));
+ Q_CHECK_PTR(ptr);
a = s;
} else {
ptr = reinterpret_cast<T *>(array);
@@ -161,25 +166,24 @@ Q_INLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::reserve(int asize)
{ if (asize > a) realloc(s, asize); }
template <class T, int Prealloc>
-Q_OUTOFLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::append(const T *abuf, int asize)
+Q_OUTOFLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::append(const T *abuf, int increment)
{
Q_ASSERT(abuf);
- if (asize <= 0)
+ if (increment <= 0)
return;
- const int idx = s;
- const int news = s + asize;
- if (news >= a)
- realloc(s, qMax(s<<1, news));
- s = news;
+ const int asize = s + increment;
+
+ if (asize >= a)
+ realloc(s, qMax(s*2, asize));
if (QTypeInfo<T>::isComplex) {
- T *i = ptr + idx;
- T *j = i + asize;
- while (i < j)
- new (i++) T(*abuf++);
+ // call constructor for new objects (which can throw)
+ while (s < asize)
+ new (ptr+(s++)) T(*abuf++);
} else {
- qMemCopy(&ptr[idx], abuf, asize * sizeof(T));
+ qMemCopy(&ptr[s], abuf, increment * sizeof(T));
+ s = asize;
}
}
@@ -189,46 +193,60 @@ Q_OUTOFLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::realloc(int asize, int a
Q_ASSERT(aalloc >= asize);
T *oldPtr = ptr;
int osize = s;
- s = asize;
+ // s = asize;
if (aalloc != a) {
ptr = reinterpret_cast<T *>(qMalloc(aalloc * sizeof(T)));
+ Q_CHECK_PTR(ptr);
if (ptr) {
+ s = 0;
a = aalloc;
if (QTypeInfo<T>::isStatic) {
- T *i = ptr + osize;
- T *j = oldPtr + osize;
- while (i != ptr) {
- new (--i) T(*--j);
- j->~T();
+ QT_TRY {
+ // copy all the old elements
+ const int copySize = qMin(asize, osize);
+ while (s < copySize) {
+ new (ptr+s) T(*(oldPtr+s));
+ (oldPtr+s)->~T();
+ s++;
+ }
+ } QT_CATCH(...) {
+ // clean up all the old objects and then free the old ptr
+ int sClean = s;
+ while (sClean < osize)
+ (oldPtr+(sClean++))->~T();
+ if (oldPtr != reinterpret_cast<T *>(array) && oldPtr != ptr)
+ qFree(oldPtr);
+ QT_RETHROW;
}
} else {
- qMemCopy(ptr, oldPtr, osize * sizeof(T));
+ qMemCopy(ptr, oldPtr, qMin(asize, osize) * sizeof(T));
+ s = asize;
}
} else {
ptr = oldPtr;
- s = 0;
- asize = 0;
+ return;
}
}
if (QTypeInfo<T>::isComplex) {
- if (asize < osize) {
- T *i = oldPtr + osize;
- T *j = oldPtr + asize;
- while (i-- != j)
- i->~T();
- } else {
- T *i = ptr + asize;
- T *j = ptr + osize;
- while (i != j)
- new (--i) T;
- }
+ while (osize > asize)
+ (oldPtr+(--osize))->~T();
+ if( oldPtr == ptr )
+ s = osize;
}
if (oldPtr != reinterpret_cast<T *>(array) && oldPtr != ptr)
qFree(oldPtr);
+
+ if (QTypeInfo<T>::isComplex) {
+ // call default constructor for new objects (which can throw)
+ while (s < asize)
+ new (ptr+(s++)) T;
+ } else {
+ s = asize;
+ }
}
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qvarlengtharray.qdoc b/src/corelib/tools/qvarlengtharray.qdoc
new file mode 100644
index 0000000000..e56e6f50b3
--- /dev/null
+++ b/src/corelib/tools/qvarlengtharray.qdoc
@@ -0,0 +1,274 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QVarLengthArray
+ \brief The QVarLengthArray class provides a low-level variable-length array.
+
+ \ingroup tools
+ \reentrant
+
+ The C++ language doesn't support variable-length arrays on the stack.
+ For example, the following code won't compile:
+
+ \snippet doc/src/snippets/code/doc_src_qvarlengtharray.qdoc 0
+
+ The alternative is to allocate the array on the heap (with
+ \c{new}):
+
+ \snippet doc/src/snippets/code/doc_src_qvarlengtharray.qdoc 1
+
+ However, if myfunc() is called very frequently from the
+ application's inner loop, heap allocation can be a major source
+ of slowdown.
+
+ QVarLengthArray is an attempt to work around this gap in the C++
+ language. It allocates a certain number of elements on the stack,
+ and if you resize the array to a larger size, it automatically
+ uses the heap instead. Stack allocation has the advantage that
+ it is much faster than heap allocation.
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qvarlengtharray.qdoc 2
+
+ In the example above, QVarLengthArray will preallocate 1024
+ elements on the stack and use them unless \c{n + 1} is greater
+ than 1024. If you omit the second template argument,
+ QVarLengthArray's default of 256 is used.
+
+ QVarLengthArray's value type must be an \l{assignable data type}.
+ This covers most data types that are commonly used, but the
+ compiler won't let you, for example, store a QWidget as a value;
+ instead, store a QWidget *.
+
+ QVarLengthArray, like QVector, provides a resizable array data
+ structure. The main differences between the two classes are:
+
+ \list
+ \o QVarLengthArray's API is much more low-level. It provides no
+ iterators and lacks much of QVector's functionality.
+
+ \o QVarLengthArray doesn't initialize the memory if the value is
+ a basic type. (QVector always does.)
+
+ \o QVector uses \l{implicit sharing} as a memory optimization.
+ QVarLengthArray doesn't provide that feature; however, it
+ usually produces slightly better performance due to reduced
+ overhead, especially in tight loops.
+ \endlist
+
+ In summary, QVarLengthArray is a low-level optimization class
+ that only makes sense in very specific cases. It is used a few
+ places inside Qt and was added to Qt's public API for the
+ convenience of advanced users.
+
+ \sa QVector, QList, QLinkedList
+*/
+
+/*! \fn QVarLengthArray::QVarLengthArray(int size)
+
+ Constructs an array with an initial size of \a size elements.
+
+ If the value type is a primitive type (e.g., char, int, float) or
+ a pointer type (e.g., QWidget *), the elements are not
+ initialized. For other types, the elements are initialized with a
+ \l{default-constructed value}.
+*/
+
+/*! \fn QVarLengthArray::~QVarLengthArray()
+
+ Destroys the array.
+*/
+
+/*! \fn int QVarLengthArray::size() const
+
+ Returns the number of elements in the array.
+
+ \sa isEmpty(), resize()
+*/
+
+/*! \fn int QVarLengthArray::count() const
+
+ Same as size().
+
+ \sa isEmpty(), resize()
+*/
+
+/*! \fn bool QVarLengthArray::isEmpty() const
+
+ Returns true if the array has size 0; otherwise returns false.
+
+ \sa size(), resize()
+*/
+
+/*! \fn void QVarLengthArray::clear()
+
+ Removes all the elements from the array.
+
+ Same as resize(0).
+*/
+
+/*! \fn void QVarLengthArray::resize(int size)
+
+ Sets the size of the array to \a size. If \a size is greater than
+ the current size, elements are added to the end. If \a size is
+ less than the current size, elements are removed from the end.
+
+ If the value type is a primitive type (e.g., char, int, float) or
+ a pointer type (e.g., QWidget *), new elements are not
+ initialized. For other types, the elements are initialized with a
+ \l{default-constructed value}.
+
+ \sa size()
+*/
+
+/*! \fn int QVarLengthArray::capacity() const
+
+ Returns the maximum number of elements that can be stored in the
+ array without forcing a reallocation.
+
+ The sole purpose of this function is to provide a means of fine
+ tuning QVarLengthArray's memory usage. In general, you will rarely ever
+ need to call this function. If you want to know how many items are
+ in the array, call size().
+
+ \sa reserve()
+*/
+
+/*! \fn void QVarLengthArray::reserve(int size)
+
+ Attempts to allocate memory for at least \a size elements. If you
+ know in advance how large the array can get, you can call this
+ function and if you call resize() often, you are likely to get
+ better performance. If \a size is an underestimate, the worst
+ that will happen is that the QVarLengthArray will be a bit
+ slower.
+
+ The sole purpose of this function is to provide a means of fine
+ tuning QVarLengthArray's memory usage. In general, you will
+ rarely ever need to call this function. If you want to change the
+ size of the array, call resize().
+
+ \sa capacity()
+*/
+
+/*! \fn T &QVarLengthArray::operator[](int i)
+
+ Returns a reference to the item at index position \a i.
+
+ \a i must be a valid index position in the array (i.e., 0 <= \a i
+ < size()).
+
+ \sa data()
+*/
+
+/*! \fn const T &QVarLengthArray::operator[](int i) const
+
+ \overload
+*/
+
+
+/*!
+ \fn void QVarLengthArray::append(const T &t)
+
+ Appends item \a t to the array, extending the array if necessary.
+
+ \sa removeLast()
+*/
+
+
+/*!
+ \fn inline void QVarLengthArray::removeLast()
+ \since 4.5
+
+ Decreases the size of the array by one. The allocated size is not changed.
+
+ \sa append()
+*/
+
+/*!
+ \fn void QVarLengthArray::append(const T *buf, int size)
+
+ Appends \a size amount of items referenced by \a buf to this array.
+*/
+
+
+/*! \fn T *QVarLengthArray::data()
+
+ Returns a pointer to the data stored in the array. The pointer can
+ be used to access and modify the items in the array.
+
+ Example:
+ \snippet doc/src/snippets/code/doc_src_qvarlengtharray.qdoc 3
+
+ The pointer remains valid as long as the array isn't reallocated.
+
+ This function is mostly useful to pass an array to a function
+ that accepts a plain C++ array.
+
+ \sa constData(), operator[]()
+*/
+
+/*! \fn const T *QVarLengthArray::data() const
+
+ \overload
+*/
+
+/*! \fn const T *QVarLengthArray::constData() const
+
+ Returns a const pointer to the data stored in the array. The
+ pointer can be used to access the items in the array. The
+ pointer remains valid as long as the array isn't reallocated.
+
+ This function is mostly useful to pass an array to a function
+ that accepts a plain C++ array.
+
+ \sa data(), operator[]()
+*/
+
+/*! \fn QVarLengthArray<T, Prealloc> &QVarLengthArray::operator=(const QVarLengthArray<T, Prealloc> &other)
+ Assigns \a other to this array and returns a reference to this array.
+ */
+
+/*! \fn QVarLengthArray::QVarLengthArray(const QVarLengthArray<T, Prealloc> &other)
+ Constructs a copy of \a other.
+ */
+
diff --git a/src/corelib/tools/qvector.cpp b/src/corelib/tools/qvector.cpp
index 6ca5526b0e..b365fd0cc0 100644
--- a/src/corelib/tools/qvector.cpp
+++ b/src/corelib/tools/qvector.cpp
@@ -50,6 +50,7 @@ QVectorData QVectorData::shared_null = { Q_BASIC_ATOMIC_INITIALIZER(1), 0, 0, tr
QVectorData *QVectorData::malloc(int sizeofTypedData, int size, int sizeofT, QVectorData *init)
{
QVectorData* p = (QVectorData *)qMalloc(sizeofTypedData + (size - 1) * sizeofT);
+ Q_CHECK_PTR(p);
::memcpy(p, init, sizeofTypedData + (qMin(size, init->alloc) - 1) * sizeofT);
return p;
}
@@ -67,7 +68,7 @@ int QVectorData::grow(int sizeofTypedData, int size, int sizeofT, bool excessive
\ingroup tools
\ingroup shared
- \mainclass
+
\reentrant
QVector\<T\> is one of Qt's generic \l{container classes}. It
diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h
index a3beff89ae..56707c741f 100644
--- a/src/corelib/tools/qvector.h
+++ b/src/corelib/tools/qvector.h
@@ -77,24 +77,15 @@ struct Q_CORE_EXPORT QVectorData
static QVectorData shared_null;
// ### Qt 5: rename to 'allocate()'. The current name causes problems for
// some debugges when the QVector is member of a class within an unnamed namespace.
+ // ### Qt 5: can be removed completely. (Ralf)
static QVectorData *malloc(int sizeofTypedData, int size, int sizeofT, QVectorData *init);
static int grow(int sizeofTypedData, int size, int sizeofT, bool excessive);
};
template <typename T>
-struct QVectorTypedData
-{
- QBasicAtomicInt ref;
- int alloc;
- int size;
-#if defined(QT_ARCH_SPARC) && defined(Q_CC_GNU) && defined(__LP64__) && defined(QT_BOOTSTRAPPED)
- // workaround for bug in gcc 3.4.2
- uint sharable;
- uint capacity;
-#else
- uint sharable : 1;
- uint capacity : 1;
-#endif
+struct QVectorTypedData : private QVectorData
+{ // private inheritance as we must not access QVectorData member thought QVectorTypedData
+ // as this would break strict aliasing rules. (in the case of shared_null)
T array[1];
};
@@ -104,14 +95,21 @@ template <typename T>
class QVector
{
typedef QVectorTypedData<T> Data;
- union { QVectorData *p; QVectorTypedData<T> *d; };
+ union {
+ QVectorData *d;
+#if defined(Q_CC_SUN) && (__SUNPRO_CC <= 0x550)
+ QVectorTypedData<T> *p;
+#else
+ Data *p;
+#endif
+ };
public:
- inline QVector() : p(&QVectorData::shared_null) { d->ref.ref(); }
+ inline QVector() : d(&QVectorData::shared_null) { d->ref.ref(); }
explicit QVector(int size);
QVector(int size, const T &t);
inline QVector(const QVector<T> &v) : d(v.d) { d->ref.ref(); if (!d->sharable) detach_helper(); }
- inline ~QVector() { if (!d) return; if (!d->ref.deref()) free(d); }
+ inline ~QVector() { if (!d) return; if (!d->ref.deref()) free(p); }
QVector<T> &operator=(const QVector<T> &v);
bool operator==(const QVector<T> &v) const;
inline bool operator!=(const QVector<T> &v) const { return !(*this == v); }
@@ -130,9 +128,9 @@ public:
inline bool isDetached() const { return d->ref == 1; }
inline void setSharable(bool sharable) { if (!sharable) detach(); d->sharable = sharable; }
- inline T *data() { detach(); return d->array; }
- inline const T *data() const { return d->array; }
- inline const T *constData() const { return d->array; }
+ inline T *data() { detach(); return p->array; }
+ inline const T *data() const { return p->array; }
+ inline const T *constData() const { return p->array; }
void clear();
const T &at(int i) const;
@@ -225,12 +223,12 @@ public:
typedef T* iterator;
typedef const T* const_iterator;
#endif
- inline iterator begin() { detach(); return d->array; }
- inline const_iterator begin() const { return d->array; }
- inline const_iterator constBegin() const { return d->array; }
- inline iterator end() { detach(); return d->array + d->size; }
- inline const_iterator end() const { return d->array + d->size; }
- inline const_iterator constEnd() const { return d->array + d->size; }
+ inline iterator begin() { detach(); return p->array; }
+ inline const_iterator begin() const { return p->array; }
+ inline const_iterator constBegin() const { return p->array; }
+ inline iterator end() { detach(); return p->array + d->size; }
+ inline const_iterator end() const { return p->array + d->size; }
+ inline const_iterator constEnd() const { return p->array + d->size; }
iterator insert(iterator before, int n, const T &x);
inline iterator insert(iterator before, const T &x) { return insert(before, 1, x); }
iterator erase(iterator begin, iterator end);
@@ -255,11 +253,7 @@ public:
typedef const value_type* const_pointer;
typedef value_type& reference;
typedef const value_type& const_reference;
-#ifndef QT_NO_STL
typedef ptrdiff_t difference_type;
-#else
- typedef int difference_type;
-#endif
typedef iterator Iterator;
typedef const_iterator ConstIterator;
typedef int size_type;
@@ -327,11 +321,11 @@ inline void QVector<T>::clear()
template <typename T>
inline const T &QVector<T>::at(int i) const
{ Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::at", "index out of range");
- return d->array[i]; }
+ return p->array[i]; }
template <typename T>
inline const T &QVector<T>::operator[](int i) const
{ Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::operator[]", "index out of range");
- return d->array[i]; }
+ return p->array[i]; }
template <typename T>
inline T &QVector<T>::operator[](int i)
{ Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::operator[]", "index out of range");
@@ -369,7 +363,7 @@ QVector<T> &QVector<T>::operator=(const QVector<T> &v)
{
v.d->ref.ref();
if (!d->ref.deref())
- free(d);
+ free(p);
d = v.d;
if (!d->sharable)
detach_helper();
@@ -379,37 +373,39 @@ QVector<T> &QVector<T>::operator=(const QVector<T> &v)
template <typename T>
inline QVectorData *QVector<T>::malloc(int aalloc)
{
- return static_cast<QVectorData *>(qMalloc(sizeOfTypedData() + (aalloc - 1) * sizeof(T)));
+ QVectorData *data = static_cast<QVectorData *>(qMalloc(sizeOfTypedData() + (aalloc - 1) * sizeof(T)));
+ Q_CHECK_PTR(data);
+ return data;
}
template <typename T>
QVector<T>::QVector(int asize)
{
- p = malloc(asize);
+ d = malloc(asize);
d->ref = 1;
d->alloc = d->size = asize;
d->sharable = true;
d->capacity = false;
if (QTypeInfo<T>::isComplex) {
- T* b = d->array;
- T* i = d->array + d->size;
+ T* b = p->array;
+ T* i = p->array + d->size;
while (i != b)
new (--i) T;
} else {
- qMemSet(d->array, 0, asize * sizeof(T));
+ qMemSet(p->array, 0, asize * sizeof(T));
}
}
template <typename T>
QVector<T>::QVector(int asize, const T &t)
{
- p = malloc(asize);
+ d = malloc(asize);
d->ref = 1;
d->alloc = d->size = asize;
d->sharable = true;
d->capacity = false;
- T* i = d->array + d->size;
- while (i != d->array)
+ T* i = p->array + d->size;
+ while (i != p->array)
new (--i) T(t);
}
@@ -418,7 +414,9 @@ void QVector<T>::free(Data *x)
{
if (QTypeInfo<T>::isComplex) {
T* b = x->array;
- T* i = b + x->size;
+ union { QVectorData *d; Data *p; } u;
+ u.p = x;
+ T* i = b + u.d->size;
while (i-- != b)
i->~T();
}
@@ -428,77 +426,82 @@ void QVector<T>::free(Data *x)
template <typename T>
void QVector<T>::realloc(int asize, int aalloc)
{
- T *j, *i, *b;
- union { QVectorData *p; Data *d; } x;
+ T *pOld;
+ T *pNew;
+ union { QVectorData *d; Data *p; } x;
x.d = d;
- if (QTypeInfo<T>::isComplex && aalloc == d->alloc && d->ref == 1) {
- // pure resize
- i = d->array + d->size;
- j = d->array + asize;
- if (i > j) {
- while (i-- != j)
- i->~T();
- } else {
- while (j-- != i)
- new (j) T;
+ if (QTypeInfo<T>::isComplex && asize < d->size && d->ref == 1 ) {
+ // call the destructor on all objects that need to be
+ // destroyed when shrinking
+ pOld = p->array + d->size;
+ pNew = p->array + asize;
+ while (asize < d->size) {
+ (--pOld)->~T();
+ d->size--;
}
- d->size = asize;
- return;
}
if (aalloc != d->alloc || d->ref != 1) {
// (re)allocate memory
if (QTypeInfo<T>::isStatic) {
- x.p = malloc(aalloc);
+ x.d = malloc(aalloc);
+ Q_CHECK_PTR(x.p);
+ x.d->size = 0;
} else if (d->ref != 1) {
- x.p = QVectorData::malloc(sizeOfTypedData(), aalloc, sizeof(T), p);
- } else {
+ x.d = malloc(aalloc);
+ Q_CHECK_PTR(x.p);
if (QTypeInfo<T>::isComplex) {
- // call the destructor on all objects that need to be
- // destroyed when shrinking
- if (asize < d->size) {
- j = d->array + asize;
- i = d->array + d->size;
- while (i-- != j)
- i->~T();
- i = d->array + asize;
- }
+ x.d->size = 0;
+ } else {
+ ::memcpy(x.p, p, sizeOfTypedData() + (qMin(aalloc, d->alloc) - 1) * sizeof(T));
+ x.d->size = d->size;
+ }
+ } else {
+ QT_TRY {
+ QVectorData *mem = static_cast<QVectorData *>(qRealloc(p, sizeOfTypedData() + (aalloc - 1) * sizeof(T)));
+ Q_CHECK_PTR(mem);
+ x.d = d = mem;
+ x.d->size = d->size;
+ } QT_CATCH (const std::bad_alloc &) {
+ if (aalloc > d->alloc) // ignore the error in case we are just shrinking.
+ QT_RETHROW;
}
- x.p = p = static_cast<QVectorData *>(qRealloc(p, sizeOfTypedData() + (aalloc - 1) * sizeof(T)));
}
x.d->ref = 1;
+ x.d->alloc = aalloc;
x.d->sharable = true;
x.d->capacity = d->capacity;
-
}
+
if (QTypeInfo<T>::isComplex) {
- if (asize < d->size) {
- j = d->array + asize;
- i = x.d->array + asize;
- } else {
- // construct all new objects when growing
- i = x.d->array + asize;
- j = x.d->array + d->size;
- while (i != j)
- new (--i) T;
- j = d->array + d->size;
- }
- if (i != j) {
+ QT_TRY {
+ pOld = p->array + x.d->size;
+ pNew = x.p->array + x.d->size;
// copy objects from the old array into the new array
- b = x.d->array;
- while (i != b)
- new (--i) T(*--j);
+ while (x.d->size < qMin(asize, d->size)) {
+ new (pNew++) T(*pOld++);
+ x.d->size++;
+ }
+ // construct all new objects when growing
+ while (x.d->size < asize) {
+ new (pNew++) T;
+ x.d->size++;
+ }
+ } QT_CATCH (...) {
+ free(x.p);
+ QT_RETHROW;
}
- } else if (asize > d->size) {
+
+ } else if (asize > x.d->size) {
// initialize newly allocated memory to 0
- qMemSet(x.d->array + d->size, 0, (asize - d->size) * sizeof(T));
+ qMemSet(x.p->array + x.d->size, 0, (asize - x.d->size) * sizeof(T));
}
x.d->size = asize;
- x.d->alloc = aalloc;
+
if (d != x.d) {
if (!d->ref.deref())
- free(d);
+ free(p);
d = x.d;
}
}
@@ -506,15 +509,15 @@ void QVector<T>::realloc(int asize, int aalloc)
template<typename T>
Q_OUTOFLINE_TEMPLATE T QVector<T>::value(int i) const
{
- if (i < 0 || i >= p->size) {
+ if (i < 0 || i >= d->size) {
return T();
}
- return d->array[i];
+ return p->array[i];
}
template<typename T>
Q_OUTOFLINE_TEMPLATE T QVector<T>::value(int i, const T &defaultValue) const
{
- return ((i < 0 || i >= p->size) ? defaultValue : d->array[i]);
+ return ((i < 0 || i >= d->size) ? defaultValue : p->array[i]);
}
template <typename T>
@@ -525,14 +528,14 @@ void QVector<T>::append(const T &t)
realloc(d->size, QVectorData::grow(sizeOfTypedData(), d->size + 1, sizeof(T),
QTypeInfo<T>::isStatic));
if (QTypeInfo<T>::isComplex)
- new (d->array + d->size) T(copy);
+ new (p->array + d->size) T(copy);
else
- d->array[d->size] = copy;
+ p->array[d->size] = copy;
} else {
if (QTypeInfo<T>::isComplex)
- new (d->array + d->size) T(t);
+ new (p->array + d->size) T(t);
else
- d->array[d->size] = t;
+ p->array[d->size] = t;
}
++d->size;
}
@@ -540,27 +543,27 @@ void QVector<T>::append(const T &t)
template <typename T>
Q_TYPENAME QVector<T>::iterator QVector<T>::insert(iterator before, size_type n, const T &t)
{
- int offset = before - d->array;
+ int offset = before - p->array;
if (n != 0) {
const T copy(t);
if (d->ref != 1 || d->size + n > d->alloc)
realloc(d->size, QVectorData::grow(sizeOfTypedData(), d->size + n, sizeof(T),
QTypeInfo<T>::isStatic));
if (QTypeInfo<T>::isStatic) {
- T *b = d->array + d->size;
- T *i = d->array + d->size + n;
+ T *b = p->array + d->size;
+ T *i = p->array + d->size + n;
while (i != b)
new (--i) T;
- i = d->array + d->size;
+ i = p->array + d->size;
T *j = i + n;
- b = d->array + offset;
+ b = p->array + offset;
while (i != b)
*--j = *--i;
i = b+n;
while (i != b)
*--i = copy;
} else {
- T *b = d->array + offset;
+ T *b = p->array + offset;
T *i = b + n;
memmove(i, b, (d->size - offset) * sizeof(T));
while (i != b)
@@ -568,29 +571,29 @@ Q_TYPENAME QVector<T>::iterator QVector<T>::insert(iterator before, size_type n,
}
d->size += n;
}
- return d->array + offset;
+ return p->array + offset;
}
template <typename T>
Q_TYPENAME QVector<T>::iterator QVector<T>::erase(iterator abegin, iterator aend)
{
- int f = abegin - d->array;
- int l = aend - d->array;
+ int f = abegin - p->array;
+ int l = aend - p->array;
int n = l - f;
detach();
if (QTypeInfo<T>::isComplex) {
- qCopy(d->array+l, d->array+d->size, d->array+f);
- T *i = d->array+d->size;
- T* b = d->array+d->size-n;
+ qCopy(p->array+l, p->array+d->size, p->array+f);
+ T *i = p->array+d->size;
+ T* b = p->array+d->size-n;
while (i != b) {
--i;
i->~T();
}
} else {
- memmove(d->array + f, d->array + l, (d->size-l)*sizeof(T));
+ memmove(p->array + f, p->array + l, (d->size-l)*sizeof(T));
}
d->size -= n;
- return d->array + f;
+ return p->array + f;
}
template <typename T>
@@ -600,9 +603,9 @@ bool QVector<T>::operator==(const QVector<T> &v) const
return false;
if (d == v.d)
return true;
- T* b = d->array;
+ T* b = p->array;
T* i = b + d->size;
- T* j = v.d->array + d->size;
+ T* j = v.p->array + d->size;
while (i != b)
if (!(*--i == *--j))
return false;
@@ -615,8 +618,8 @@ QVector<T> &QVector<T>::fill(const T &from, int asize)
const T copy(from);
resize(asize < 0 ? d->size : asize);
if (d->size) {
- T *i = d->array + d->size;
- T *b = d->array;
+ T *i = p->array + d->size;
+ T *b = p->array;
while (i != b)
*--i = copy;
}
@@ -629,9 +632,9 @@ QVector<T> &QVector<T>::operator+=(const QVector &l)
int newSize = d->size + l.d->size;
realloc(d->size, newSize);
- T *w = d->array + newSize;
- T *i = l.d->array + l.d->size;
- T *b = l.d->array;
+ T *w = p->array + newSize;
+ T *i = l.p->array + l.d->size;
+ T *b = l.p->array;
while (i != b) {
if (QTypeInfo<T>::isComplex)
new (--w) T(*--i);
@@ -648,11 +651,11 @@ int QVector<T>::indexOf(const T &t, int from) const
if (from < 0)
from = qMax(from + d->size, 0);
if (from < d->size) {
- T* n = d->array + from - 1;
- T* e = d->array + d->size;
+ T* n = p->array + from - 1;
+ T* e = p->array + d->size;
while (++n != e)
if (*n == t)
- return n - d->array;
+ return n - p->array;
}
return -1;
}
@@ -665,8 +668,8 @@ int QVector<T>::lastIndexOf(const T &t, int from) const
else if (from >= d->size)
from = d->size-1;
if (from >= 0) {
- T* b = d->array;
- T* n = d->array + from + 1;
+ T* b = p->array;
+ T* n = p->array + from + 1;
while (n != b) {
if (*--n == t)
return n - b;
@@ -678,8 +681,8 @@ int QVector<T>::lastIndexOf(const T &t, int from) const
template <typename T>
bool QVector<T>::contains(const T &t) const
{
- T* b = d->array;
- T* i = d->array + d->size;
+ T* b = p->array;
+ T* i = p->array + d->size;
while (i != b)
if (*--i == t)
return true;
@@ -690,8 +693,8 @@ template <typename T>
int QVector<T>::count(const T &t) const
{
int c = 0;
- T* b = d->array;
- T* i = d->array + d->size;
+ T* b = p->array;
+ T* i = p->array + d->size;
while (i != b)
if (*--i == t)
++c;
diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri
index b70c7df8d7..464c60ffad 100644
--- a/src/corelib/tools/tools.pri
+++ b/src/corelib/tools/tools.pri
@@ -5,12 +5,14 @@ HEADERS += \
tools/qbitarray.h \
tools/qbytearray.h \
tools/qbytearraymatcher.h \
+ tools/qbytedata_p.h \
tools/qcache.h \
tools/qchar.h \
tools/qcontainerfwd.h \
tools/qcryptographichash.h \
tools/qdatetime.h \
tools/qdatetime_p.h \
+ tools/qeasingcurve.h \
tools/qhash.h \
tools/qline.h \
tools/qlinkedlist.h \
@@ -19,6 +21,7 @@ HEADERS += \
tools/qlocale_p.h \
tools/qlocale_data_p.h \
tools/qmap.h \
+ tools/qcontiguouscache.h \
tools/qpodlist_p.h \
tools/qpoint.h \
tools/qqueue.h \
@@ -32,13 +35,15 @@ HEADERS += \
tools/qsize.h \
tools/qstack.h \
tools/qstring.h \
+ tools/qstringbuilder.h \
tools/qstringlist.h \
tools/qstringmatcher.h \
tools/qtextboundaryfinder.h \
tools/qtimeline.h \
tools/qunicodetables_p.h \
tools/qvarlengtharray.h \
- tools/qvector.h
+ tools/qvector.h \
+ tools/qscopedpointer.h
SOURCES += \
@@ -47,26 +52,29 @@ SOURCES += \
tools/qbytearraymatcher.cpp \
tools/qcryptographichash.cpp \
tools/qdatetime.cpp \
- tools/qdumper.cpp \
+ tools/qeasingcurve.cpp \
tools/qhash.cpp \
tools/qline.cpp \
tools/qlinkedlist.cpp \
- tools/qlistdata.cpp \
+ tools/qlist.cpp \
tools/qlocale.cpp \
tools/qpoint.cpp \
tools/qmap.cpp \
+ tools/qcontiguouscache.cpp \
tools/qrect.cpp \
tools/qregexp.cpp \
tools/qshareddata.cpp \
tools/qsharedpointer.cpp \
tools/qsize.cpp \
tools/qstring.cpp \
+ tools/qstringbuilder.cpp \
tools/qstringlist.cpp \
tools/qtextboundaryfinder.cpp \
tools/qtimeline.cpp \
tools/qvector.cpp \
tools/qvsnprintf.cpp
+symbian:SOURCES+=tools/qlocale_symbian.cpp
#zlib support
contains(QT_CONFIG, zlib) {
@@ -85,7 +93,7 @@ contains(QT_CONFIG, zlib) {
../3rdparty/zlib/uncompr.c \
../3rdparty/zlib/zutil.c
} else:!contains(QT_CONFIG, no-zlib) {
- unix:LIBS += -lz
+ unix:LIBS_PRIVATE += -lz
# win32:LIBS += libz.lib
}
@@ -103,4 +111,9 @@ SOURCES += ../3rdparty/harfbuzz/src/harfbuzz-buffer.c \
tools/qharfbuzz.cpp
HEADERS += tools/qharfbuzz_p.h
-!macx-icc:unix:LIBS += -lm
+INCLUDEPATH += ../3rdparty/md5 \
+ ../3rdparty/md4
+
+# Note: libm should be present by default becaue this is C++
+!macx-icc:!vxworks:!symbian:unix:LIBS_PRIVATE += -lm
+