Merge remote-tracking branch 'origin/api_changes'

Change-Id: I964b0a6f5c38351fdfafb8a2a128a349ff8c89d1
This commit is contained in:
Lars Knoll 2012-04-17 12:58:41 +02:00
commit 64255ef650
583 changed files with 28611 additions and 23936 deletions

View File

@ -1,3 +0,0 @@
SOURCES = 3dnow.cpp
CONFIG -= x11 qt
mac:CONFIG -= app_bundle

View File

@ -1,9 +1,9 @@
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Copyright (C) 2012 Intel Corporation.
** Contact: http://www.qt-project.org/
**
** This file is part of the config.tests of the Qt Toolkit.
** This file is part of the configuration of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
@ -39,13 +39,17 @@
**
****************************************************************************/
#include <mm3dnow.h>
#if defined(__GNUC__) && __GNUC__ < 4 && __GNUC_MINOR__ < 3
#error GCC < 3.2 is known to create internal compiler errors with our MMX code
#endif
#include <immintrin.h>
int main(int, char**)
{
_m_femms();
/* AVX */
_mm256_zeroall();
volatile __m256i a = _mm256_setzero_si256();
/* AVX2 */
volatile __m256i b = _mm256_and_si256(a, a);
volatile __m256i result = _mm256_add_epi8(a, b);
(void)result;
return 0;
}

View File

@ -1,3 +1,3 @@
SOURCES = sse.cpp
SOURCES = avx2.cpp
CONFIG -= x11 qt
mac:CONFIG -= app_bundle

View File

@ -1,3 +0,0 @@
SOURCES = mmx.cpp
CONFIG -= x11 qt
mac:CONFIG -= app_bundle

140
configure vendored
View File

@ -718,20 +718,17 @@ CFG_GSTREAMER=auto
CFG_QGTKSTYLE=auto
CFG_LARGEFILE=auto
CFG_OPENSSL=auto
CFG_STL=auto
CFG_PRECOMPILE=auto
CFG_SEPARATE_DEBUG_INFO=no
CFG_SEPARATE_DEBUG_INFO_NOCOPY=no
CFG_REDUCE_EXPORTS=auto
CFG_MMX=auto
CFG_3DNOW=auto
CFG_SSE=auto
CFG_SSE2=auto
CFG_SSE3=auto
CFG_SSSE3=auto
CFG_SSE4_1=auto
CFG_SSE4_2=auto
CFG_AVX=auto
CFG_AVX2=auto
CFG_REDUCE_RELOCATIONS=auto
CFG_ACCESSIBILITY=auto
CFG_IWMMXT=no
@ -892,7 +889,7 @@ while [ "$#" -gt 0 ]; do
VAL=no
;;
#Qt style yes options
-profile|-shared|-static|-sm|-xinerama|-xshape|-xsync|-xinput|-xinput2|-egl|-reduce-exports|-pch|-separate-debug-info|-stl|-freetype|-xcursor|-xfixes|-xrandr|-xrender|-mitshm|-fontconfig|-xkb|-xcb|-eglfs|-directfb|-nis|-dbus|-dbus-linked|-glib|-gstreamer|-gtkstyle|-cups|-iconv|-largefile|-h|-help|-v|-verbose|-debug|-release|-fast|-accessibility|-confirm-license|-gnumake|-framework|-debug-and-release|-exceptions|-harfbuzz|-prefix-install|-silent|-optimized-qmake|-dwarf2|-reduce-relocations|-sse|-openssl|-openssl-linked|-phonon-backend|-audio-backend|-qml-debug|-javascript-jit|-rpath|-pkg-config|-force-pkg-config|-icu|-force-asserts|-testcocoon)
-profile|-shared|-static|-sm|-xinerama|-xshape|-xsync|-xinput|-xinput2|-egl|-reduce-exports|-pch|-separate-debug-info|-freetype|-xcursor|-xfixes|-xrandr|-xrender|-mitshm|-fontconfig|-xkb|-xcb|-eglfs|-directfb|-nis|-dbus|-dbus-linked|-glib|-gstreamer|-gtkstyle|-cups|-iconv|-largefile|-h|-help|-v|-verbose|-debug|-release|-fast|-accessibility|-confirm-license|-gnumake|-framework|-debug-and-release|-exceptions|-harfbuzz|-prefix-install|-silent|-optimized-qmake|-dwarf2|-reduce-relocations|-sse|-openssl|-openssl-linked|-phonon-backend|-audio-backend|-qml-debug|-javascript-jit|-rpath|-pkg-config|-force-pkg-config|-icu|-force-asserts|-testcocoon)
VAR=`echo $1 | sed "s,^-\(.*\),\1,"`
VAL=yes
;;
@ -1428,13 +1425,6 @@ while [ "$#" -gt 0 ]; do
UNKNOWN_OPT=yes
fi
;;
stl)
if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then
CFG_STL="$VAL"
else
UNKNOWN_OPT=yes
fi
;;
pch)
if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then
CFG_PRECOMPILE="$VAL"
@ -1459,27 +1449,6 @@ while [ "$#" -gt 0 ]; do
UNKNOWN_OPT=yes
fi
;;
mmx)
if [ "$VAL" = "no" ]; then
CFG_MMX="$VAL"
else
UNKNOWN_OPT=yes
fi
;;
3dnow)
if [ "$VAL" = "no" ]; then
CFG_3DNOW="$VAL"
else
UNKNOWN_OPT=yes
fi
;;
sse)
if [ "$VAL" = "no" ]; then
CFG_SSE="$VAL"
else
UNKNOWN_OPT=yes
fi
;;
sse2)
if [ "$VAL" = "no" ]; then
CFG_SSE2="$VAL"
@ -1522,6 +1491,13 @@ while [ "$#" -gt 0 ]; do
UNKNOWN_OPT=yes
fi
;;
avx2)
if [ "$VAL" = "no" ]; then
CFG_AVX2="$VAL"
else
UNKNOWN_OPT=yes
fi
;;
iwmmxt)
CFG_IWMMXT="yes"
;;
@ -2816,13 +2792,6 @@ if [ "$OPT_HELP" = "yes" ]; then
LFSY="*"
LFSN=" "
fi
if [ "$CFG_STL" = "auto" ] || [ "$CFG_STL" = "yes" ]; then
SHY="*"
SHN=" "
else
SHY=" "
SHN="*"
fi
if [ "$CFG_PRECOMPILE" = "auto" ] || [ "$CFG_PRECOMPILE" = "no" ]; then
PHY=" "
PHN="*"
@ -2893,7 +2862,7 @@ Usage: $relconf [-h] [-prefix <dir>] [-prefix-install] [-bindir <dir>] [-libdir
[-release] [-debug] [-debug-and-release]
[-developer-build] [-shared] [-static] [-no-fast] [-fast] [-no-largefile]
[-largefile] [-no-exceptions] [-exceptions] [-no-accessibility]
[-accessibility] [-no-stl] [-stl] [-no-sql-<driver>] [-sql-<driver>]
[-accessibility] [-no-sql-<driver>] [-sql-<driver>]
[-plugin-sql-<driver>] [-system-sqlite]
[-platform] [-D <string>] [-I <string>] [-L <string>] [-help]
[-qt-zlib] [-system-zlib] [-no-gif] [-no-libpng] [-qt-libpng] [-system-libpng]
@ -2901,7 +2870,7 @@ Usage: $relconf [-h] [-prefix <dir>] [-prefix-install] [-bindir <dir>] [-libdir
[-nomake <part>] [-R <string>] [-l <string>] [-no-rpath] [-rpath] [-continue]
[-verbose] [-v] [-silent] [-no-nis] [-nis] [-no-cups] [-cups] [-no-iconv]
[-iconv] [-no-pch] [-pch] [-no-dbus] [-dbus] [-dbus-linked] [-no-gui]
[-no-separate-debug-info] [-no-mmx] [-no-3dnow] [-no-sse] [-no-sse2]
[-no-separate-debug-info] [-no-sse2]
[-no-sse3] [-no-ssse3] [-no-sse4.1] [-no-sse4.2] [-no-avx] [-no-neon]
[-qtnamespace <namespace>] [-qtlibinfix <infix>] [-separate-debug-info]
[-no-phonon-backend] [-phonon-backend] [-no-media-backend] [-media-backend]
@ -3000,9 +2969,6 @@ Configure options:
-no-accessibility .. Do not compile Accessibility support.
* -accessibility ..... Compile Accessibility support.
$SHN -no-stl ............ Do not compile STL support.
$SHY -stl ............... Compile STL support.
-no-sql-<driver> ... Disable SQL <driver> entirely.
-qt-sql-<driver> ... Enable a SQL <driver> in the QtSql library, by default
none are turned on.
@ -3029,15 +2995,13 @@ Configure options:
See the README file for a list of supported
operating systems and compilers.
-no-mmx ............ Do not compile with use of MMX instructions.
-no-3dnow .......... Do not compile with use of 3DNOW instructions.
-no-sse ............ Do not compile with use of SSE instructions.
-no-sse2 ........... Do not compile with use of SSE2 instructions.
-no-sse3 ........... Do not compile with use of SSE3 instructions.
-no-ssse3 .......... Do not compile with use of SSSE3 instructions.
-no-sse4.1.......... Do not compile with use of SSE4.1 instructions.
-no-sse4.2.......... Do not compile with use of SSE4.2 instructions.
-no-avx ............ Do not compile with use of AVX instructions.
-no-avx2 ........... Do not compile with use of AVX2 instructions.
-no-neon ........... Do not compile with use of NEON instructions.
-no-mips_dsp ....... Do not compile with use of MIPS DSP instructions.
-no-mips_dspr2 ..... Do not compile with use of MIPS DSP rev2 instructions.
@ -3733,33 +3697,6 @@ else
CFG_USE_FLOATMATH=no
fi
# detect mmx support
if [ "${CFG_MMX}" = "auto" ]; then
if "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" config.tests/unix/mmx "mmx" $L_FLAGS $I_FLAGS $l_FLAGS "-mmmx"; then
CFG_MMX=yes
else
CFG_MMX=no
fi
fi
# detect 3dnow support
if [ "${CFG_3DNOW}" = "auto" ]; then
if "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" config.tests/unix/3dnow "3dnow" $L_FLAGS $I_FLAGS $l_FLAGS "-m3dnow"; then
CFG_3DNOW=yes
else
CFG_3DNOW=no
fi
fi
# detect sse support
if [ "${CFG_SSE}" = "auto" ]; then
if "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" config.tests/unix/sse "sse" $L_FLAGS $I_FLAGS $l_FLAGS "-msse"; then
CFG_SSE=yes
else
CFG_SSE=no
fi
fi
# detect sse2 support
if [ "${CFG_SSE2}" = "auto" ]; then
if "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" config.tests/unix/sse2 "sse2" $L_FLAGS $I_FLAGS $l_FLAGS "-msse2"; then
@ -3814,6 +3751,15 @@ if [ "${CFG_AVX}" = "auto" ]; then
fi
fi
# detect avx2 support
if [ "${CFG_AVX2}" = "auto" ]; then
if "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" config.tests/unix/avx2 "avx2" $L_FLAGS $I_FLAGS $l_FLAGS "-march=core-avx2"; then
CFG_AVX2=yes
else
CFG_AVX2=no
fi
fi
# check iWMMXt support
if [ "$CFG_IWMMXT" = "yes" ]; then
"$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" config.tests/unix/iwmmxt "iwmmxt" $L_FLAGS $I_FLAGS $l_FLAGS "-mcpu=iwmmxt"
@ -4725,26 +4671,13 @@ if [ "$CFG_LIBFREETYPE" = "auto" ]; then
fi
fi
HAVE_STL=no
if "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" config.tests/unix/stl "STL" $L_FLAGS $I_FLAGS $l_FLAGS; then
HAVE_STL=yes
if ! "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" config.tests/unix/stl "STL" $L_FLAGS $I_FLAGS $l_FLAGS &&
[ "$CFG_CONFIGURE_EXIT_ON_ERROR" = "yes" ]; then
echo "STL functionality check failed! Cannot build Qt with this STL library."
echo " Turn on verbose messaging (-v) to $0 to see the final report."
exit 101
fi
if [ "$CFG_STL" != "no" ]; then
if [ "$HAVE_STL" = "yes" ]; then
CFG_STL=yes
else
if [ "$CFG_STL" = "yes" ] && [ "$CFG_CONFIGURE_EXIT_ON_ERROR" = "yes" ]; then
echo "STL support cannot be enabled due to functionality tests!"
echo " Turn on verbose messaging (-v) to $0 to see the final report."
echo " If you believe this message is in error you may use the continue"
echo " switch (-continue) to $0 to continue."
exit 101
else
CFG_STL=no
fi
fi
fi
# detect POSIX clock_gettime()
if [ "$CFG_CLOCK_GETTIME" = "auto" ]; then
@ -5086,11 +5019,6 @@ QMakeVar set UI_DIR ".uic/$QMAKE_OUTDIR"
if [ "$CFG_LARGEFILE" = "yes" ] && [ "$XPLATFORM_MINGW" != "yes" ]; then
QMAKE_CONFIG="$QMAKE_CONFIG largefile"
fi
if [ "$CFG_STL" = "no" ]; then
QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_STL"
else
QMAKE_CONFIG="$QMAKE_CONFIG stl"
fi
if [ "$CFG_USE_GNUMAKE" = "yes" ]; then
QMAKE_CONFIG="$QMAKE_CONFIG GNUmake"
fi
@ -5105,15 +5033,13 @@ fi
if [ "$CFG_SEPARATE_DEBUG_INFO_NOCOPY" = "yes" ] ; then
QT_CONFIG="$QT_CONFIG separate_debug_info_nocopy"
fi
[ "$CFG_MMX" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG mmx"
[ "$CFG_3DNOW" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG 3dnow"
[ "$CFG_SSE" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG sse"
[ "$CFG_SSE2" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG sse2"
[ "$CFG_SSE3" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG sse3"
[ "$CFG_SSSE3" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG ssse3"
[ "$CFG_SSE4_1" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG sse4_1"
[ "$CFG_SSE4_2" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG sse4_2"
[ "$CFG_AVX" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG avx"
[ "$CFG_AVX2" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG avx2"
[ "$CFG_IWMMXT" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG iwmmxt"
[ "$CFG_NEON" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG neon"
if [ "$CFG_ARCH" = "mips" ]; then
@ -5750,9 +5676,6 @@ elif [ "$CFG_DEBUG" = "no" ]; then
fi
QT_CONFIG="$QT_CONFIG release"
fi
if [ "$CFG_STL" = "yes" ]; then
QTCONFIG_CONFIG="$QTCONFIG_CONFIG stl"
fi
if [ "$CFG_FRAMEWORK" = "no" ]; then
QTCONFIG_CONFIG="$QTCONFIG_CONFIG qt_no_framework"
else
@ -6008,12 +5931,11 @@ else
echo "JavaScriptCore JIT ..... $CFG_JAVASCRIPTCORE_JIT"
fi
echo "QML debugging .......... $CFG_QML_DEBUG"
echo "STL support ............ $CFG_STL"
echo "PCH support ............ $CFG_PRECOMPILE"
if [ "$CFG_ARCH" = "i386" -o "$CFG_ARCH" = "x86_64" ]; then
echo "MMX/3DNOW/SSE/SSE2/SSE3. ${CFG_MMX}/${CFG_3DNOW}/${CFG_SSE}/${CFG_SSE2}/${CFG_SSE3}"
echo "SSSE3/SSE4.1/SSE4.2..... ${CFG_SSSE3}/${CFG_SSE4_1}/${CFG_SSE4_2}"
echo "AVX..................... ${CFG_AVX}"
echo "SSE2/SSE3/SSSE3......... ${CFG_SSE2}/${CFG_SSE3}/${CFG_SSSE3}"
echo "SSE4.1/SSE4.2........... ${CFG_SSSE3}/${CFG_SSE4_1}/${CFG_SSE4_2}"
echo "AVX/AVX2................ ${CFG_AVX}/${CFG_AVX2}"
elif [ "$CFG_ARCH" = "arm" ]; then
echo "iWMMXt support ......... ${CFG_IWMMXT}"
echo "NEON support ........... ${CFG_NEON}"
@ -6317,7 +6239,7 @@ for file in .projects .projects.3; do
fi
SPEC=$XQMAKESPEC ;;
*/qmake/qmake.pro) continue ;;
*tools/bootstrap*|*tools/moc*|*tools/rcc*|*tools/uic*|*tools/qdoc*) SPEC=$QMAKESPEC ;;
*tools/bootstrap*|*tools/moc*|*tools/rcc*|*tools/uic*|*tools/qdoc*|*tools/qdbusxml2cpp*|*tools/qdbuscpp2xml*) SPEC=$QMAKESPEC ;;
*) if [ "$CFG_NOPROCESS" = "yes" ]; then
continue
else

62
dist/changes-5.0.0 vendored
View File

@ -36,6 +36,13 @@ information about a particular change.
- QCoreApplication::translate() will no longer return the source text when
the translation is empty. Use lrelease -removeidentical for optimization.
- QString and QByteArray constructors that take a size argument will now treat
negative sizes to indicate nul-terminated strings (a nul-terminated array of
QChar, in the case of QString). In Qt 4, negative sizes were ignored and
result in empty QString and QByteArray, respectively. The size argument to
those constructors now has a default value of -1, thus replacing the separate
constructors that did the same.
- Qt::escape() is deprecated (but can be enabled via
QT_DISABLE_DEPRECATED_BEFORE), use QString::toHtmlEscaped() instead.
@ -51,6 +58,16 @@ information about a particular change.
* QMetaType::construct() has been renamed to QMetaType::create().
* QMetaType::unregisterType() has been removed.
- QMetaMethod:
* QMetaMethod::signature() has been renamed to QMetaMethod::methodSignature(),
and the return type has been changed to QByteArray. This was done to be able
to generate the signature string on demand, rather than always storing it in
the meta-data.
* QMetaMethod::typeName() no longer returns an empty string when the return
type is void; it returns "void". The recommended way of checking whether a
method returns void is to compare the return value of QMetaMethod::returnType()
to QMetaType::Void.
- QTestLib:
* The plain-text, xml and lightxml test output formats have been changed to
show a test result for every row of test data in data-driven tests. In
@ -231,9 +248,17 @@ information about a particular change.
- QSqlQueryModel::indexInQuery() is now virtual. See note below under QtSql.
- QSqlDriver::subscribeToNotification, unsubscribeFromNotification,
subscribedToNotifications, isIdentifierEscaped, and stripDelimiters
are now virtual. See note below under QtSql.
- qMacVersion() has been removed. Use QSysInfo::macVersion() or
QSysInfo::MacintoshVersion instead.
- QColorDialog::customColor() now returns a QColor value instead of QRgb.
QColorDialog::setCustomColor() and QColorDialog::setStandardColor() now
take a QColor value for their second parameter instead of QRgb.
****************************************************************************
* General *
****************************************************************************
@ -325,6 +350,10 @@ QtCore
* QEvent::AccessibilityPrepare, AccessibilityHelp and AccessibilityDescription removed:
* The enum values simply didn't make sense in the first place and should simply be dropped.
* [QTBUG-23529] QHash is now more resilient to a family of denial of service
attacks exploiting algorithmic complexity, by supporting two-arguments overloads
of the qHash() hashing function.
QtGui
-----
* Accessibility has been refactored. The hierachy of accessible objects is implemented via
@ -378,6 +407,11 @@ QtWidgets
* ResizeMode resizeMode(int logicalindex) const -
use sectionResizeMode(int logicalindex) instead.
* QDateEdit and QTimeEdit have re-gained a USER property. These were originally removed
before Qt 4.7.0, and are re-added for 5.0. This means that the userProperty for
those classes are now QDate and QTime respectively, not QDateTime as they have been
for the 4.7 and 4.8 releases.
QtNetwork
---------
* QHostAddress::isLoopback() API added. Returns true if the address is
@ -389,6 +423,14 @@ QtNetwork
* The openssl network backend now reads the ssl configuration file allowing
the use of openssl engines.
QtDBus
------
* QtDBus now generates property annotations for the Qt type names
in the org.qtproject.QtDBus namespace. When parsing such annotations
both the old and new namespaces are accepted.
* QtDBus error codes have been updated to be on the org.qtproject.QtDBus.Error
namespace.
QtOpenGL
--------
@ -466,6 +508,12 @@ changes. insertRows() and insertRecord() also respect the edit strategy.
* QSqlTableModel::setData() and setRecord() in OnRowChange no longer have the
side effect of submitting the cached row when invoked on a different row.
* QSqlDriver::subscribeToNotification, unsubscribeFromNotification,
subscribedToNotifications, isIdentifierEscaped, and stripDelimiters
are now virtual. Their xxxImplemenation counterparts have been removed
now that QSqlDriver subclasses can reimplement these directly.
****************************************************************************
* Database Drivers *
****************************************************************************
@ -580,6 +628,20 @@ Qt for Windows CE
QMetaType::User, which means that it points to the first registered custom
type, instead of a nonexistent type.
- QMetaType
* Interpretation of QMetaType::Void was changed. Before, in some cases
it was returned as an invalid type id, but sometimes it was used as a valid
type (C++ "void"). In Qt5, new QMetaType::UnknownType was introduced to
distinguish between these two. QMetaType::UnknownType is an invalid type id
signaling that a type is unknown to QMetaType, and QMetaType::Void
is a valid type id of C++ void type. The difference will be visible for
example in call to QMetaType::typeName(), this function will return null for
QMetaType::UnknownType and a pointer to "void" string for
QMetaType::Void.
Please, notice that QMetaType::UnknownType has value 0, which previously was
reserved for QMetaType::Void.
- QMessageBox

View File

@ -68,7 +68,7 @@ sock.connectToHost(url.host(), url.port(80));
//! [4]
http://www.example.com/cgi-bin/drawgraph.cgi?type-pie/color-green
http://www.example.com/cgi-bin/drawgraph.cgi?type(pie)color(green)
//! [4]

View File

@ -107,7 +107,7 @@ for(int i = metaObject->propertyOffset(); i < metaObject->propertyCount(); ++i)
const QMetaObject* metaObject = obj->metaObject();
QStringList methods;
for(int i = metaObject->methodOffset(); i < metaObject->methodCount(); ++i)
methods << QString::fromLatin1(metaObject->method(i).signature());
methods << QString::fromLatin1(metaObject->method(i).methodSignature());
//! [methodCount]
//! [6]

View File

@ -73,7 +73,7 @@ MyStruct s2 = var.value<MyStruct>();
//! [3]
int id = QMetaType::type("MyClass");
if (id != 0) {
if (id != QMetaType::UnknownType) {
void *myClassPtr = QMetaType::create(id);
...
QMetaType::destroy(id, myClassPtr);

View File

@ -155,9 +155,9 @@ inline bool operator==(const Employee &e1, const Employee &e2)
&& e1.dateOfBirth() == e2.dateOfBirth();
}
inline uint qHash(const Employee &key)
inline uint qHash(const Employee &key, uint seed)
{
return qHash(key.name()) ^ key.dateOfBirth().day();
return qHash(key.name(), seed) ^ key.dateOfBirth().day();
}
#endif // EMPLOYEE_H

View File

@ -1,48 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
** the names of its contributors may be used to endorse or promote
** products derived from this software without specific prior written
** permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
//! [0]
MainWindow::MainWindow()
{
workspace = new QWorkspace;
setCentralWidget(workspace);
...
}
//! [0]

View File

@ -314,6 +314,11 @@ void Widget::countFunction()
QString str = "banana and panama";
str.count(QRegExp("a[nm]a")); // returns 4
//! [18]
//! [95]
QString str = "banana and panama";
str.count(QRegularExpression("a[nm]a")); // returns 4
//! [95]
}
void Widget::dataFunction()
@ -384,6 +389,11 @@ void Widget::firstIndexOfFunction()
QString str = "the minimum";
str.indexOf(QRegExp("m[aeiou]"), 0); // returns 4
//! [25]
//! [93]
QString str = "the minimum";
str.indexOf(QRegularExpression("m[aeiou]"), 0); // returns 4
//! [93]
}
void Widget::insertFunction()
@ -429,6 +439,11 @@ void Widget::lastIndexOfFunction()
QString str = "the minimum";
str.lastIndexOf(QRegExp("m[aeiou]")); // returns 8
//! [30]
//! [94]
QString str = "the minimum";
str.lastIndexOf(QRegularExpression("m[aeiou]")); // returns 8
//! [94]
}
void Widget::leftFunction()
@ -499,6 +514,12 @@ void Widget::removeFunction()
r.remove(QRegExp("[aeiou]."));
// r == "The"
//! [39]
//! [96]
QString r = "Telephone";
r.remove(QRegularExpression("[aeiou]."));
// r == "The"
//! [96]
}
void Widget::replaceFunction()
@ -533,6 +554,18 @@ void Widget::replaceFunction()
equis.replace("xx", "x");
// equis == "xxx"
//! [86]
//! [87]
QString s = "Banana";
s.replace(QRegularExpression("a[mn]"), "ox");
// s == "Boxoxa"
//! [87]
//! [88]
QString t = "A <i>bon mot</i>.";
t.replace(QRegularExpression("<i>([^<]*)</i>"), "\\emph{\\1}");
// t == "A \\emph{bon mot}."
//! [88]
}
void Widget::reserveFunction()
@ -627,9 +660,16 @@ void Widget::sectionFunction()
//! [55]
QString line = "forename\tmiddlename surname \t \t phone";
QRegExp sep("\\s+");
str = line.section(sep, 2, 2); // s == "surname"
str = line.section(sep, -3, -2); // s == "middlename surname"
str = line.section(sep, 2, 2); // str == "surname"
str = line.section(sep, -3, -2); // str == "middlename surname"
//! [55]
//! [89]
QString line = "forename\tmiddlename surname \t \t phone";
QRegularExpression sep("\\s+");
str = line.section(sep, 2, 2); // str == "surname"
str = line.section(sep, -3, -2); // str == "middlename surname"
//! [89]
}
void Widget::setNumFunction()
@ -682,6 +722,27 @@ void Widget::splitFunction()
list = str.split(QRegExp("\\b"));
// list: [ "", "Now", ": ", "this", " ", "sentence", " ", "fragment", "." ]
//! [61]
//! [90]
QString str;
QStringList list;
str = "Some text\n\twith strange whitespace.";
list = str.split(QRegularExpression("\\s+"));
// list: [ "Some", "text", "with", "strange", "whitespace." ]
//! [90]
//! [91]
str = "This time, a normal English sentence.";
list = str.split(QRegularExpression("\\W+"), QString::SkipEmptyParts);
// list: [ "This", "time", "a", "normal", "English", "sentence" ]
//! [91]
//! [92]
str = "Now: this sentence fragment.";
list = str.split(QRegularExpression("\\b"));
// list: [ "", "Now", ": ", "this", " ", "sentence", " ", "fragment", "." ]
//! [92]
}
void Widget::splitCaseSensitiveFunction()

View File

@ -144,6 +144,21 @@ Widget::Widget(QWidget *parent)
list.replaceInStrings(QRegExp("^(.*), (.*)$"), "\\2 \\1");
// list == ["Bill Clinton", "Bill Murray"]
//! [15]
list.clear();
//! [16]
list << "alpha" << "beta" << "gamma" << "epsilon";
list.replaceInStrings(QRegularExpression("^a"), "o");
// list == ["olpha", "beta", "gamma", "epsilon"]
//! [16]
list.clear();
//! [17]
list << "Bill Clinton" << "Murray, Bill";
list.replaceInStrings(QRegularExpression("^(.*), (.*)$"), "\\2 \\1");
// list == ["Bill Clinton", "Bill Murray"]
//! [17]
}
int main(int argc, char *argv[])

View File

@ -103,9 +103,9 @@ void Window::mouseMoveEvent(QMouseEvent *event)
p.setRenderHint(QPainter::Antialiasing);
p.drawLine(m_lastPos, event->pos());
m_lastPos = event->pos();
}
scheduleRender();
scheduleRender();
}
}
void Window::mouseReleaseEvent(QMouseEvent *event)
@ -115,9 +115,9 @@ void Window::mouseReleaseEvent(QMouseEvent *event)
p.setRenderHint(QPainter::Antialiasing);
p.drawLine(m_lastPos, event->pos());
m_lastPos = QPoint(-1, -1);
}
scheduleRender();
scheduleRender();
}
}
void Window::exposeEvent(QExposeEvent *)
@ -139,8 +139,7 @@ void Window::resizeEvent(QResizeEvent *)
QPainter p(&m_image);
p.drawImage(0, 0, old);
}
render();
scheduleRender();
}
void Window::keyPressEvent(QKeyEvent *event)
@ -168,7 +167,8 @@ void Window::scheduleRender()
void Window::timerEvent(QTimerEvent *)
{
render();
if (isExposed())
render();
killTimer(m_renderTimer);
m_renderTimer = 0;
}

View File

@ -204,13 +204,11 @@ mac {
}
#SIMD defines:
mmx:DEFINES += QT_HAVE_MMX
3dnow:DEFINES += QT_HAVE_3DNOW
sse:DEFINES += QT_HAVE_SSE QT_HAVE_MMXEXT
sse2:DEFINES += QT_HAVE_SSE2
sse3:DEFINES += QT_HAVE_SSE3
ssse3:DEFINES += QT_HAVE_SSSE3
sse4_1:DEFINES += QT_HAVE_SSE4_1
sse4_2:DEFINES += QT_HAVE_SSE4_2
avx:DEFINES += QT_HAVE_AVX
avx2:DEFINES += QT_HAVE_AVX2
iwmmxt:DEFINES += QT_HAVE_IWMMXT

View File

@ -15,4 +15,4 @@ contains(QT_CONFIG, separate_debug_info_nocopy):CONFIG += separate_debug_info_no
load(qt_targets)
wince*:LIBS += $$QMAKE_LIBS_GUI
QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF

View File

@ -16,14 +16,14 @@ OBJS=project.o property.o main.o makefile.o unixmake2.o unixmake.o \
gbuild.o
#qt code
QOBJS=qtextcodec.o qutfcodec.o qstring.o qtextstream.o qiodevice.o qmalloc.o qglobal.o \
qbytearray.o qbytearraymatcher.o qdatastream.o qbuffer.o qlist.o qfile.o \
QOBJS=qtextcodec.o qutfcodec.o qstring.o qstringbuilder.o qtextstream.o qiodevice.o qmalloc.o qglobal.o \
qarraydata.o qbytearray.o qbytearraymatcher.o qdatastream.o qbuffer.o qlist.o qfiledevice.o qfile.o \
qfilesystementry.o qfilesystemengine_unix.o qfilesystemengine.o qfilesystemiterator_unix.o \
qfsfileengine_unix.o qfsfileengine.o \
qfsfileengine_iterator.o qregexp.o qvector.o qbitarray.o qdir.o qdiriterator.o quuid.o qhash.o \
qfileinfo.o qdatetime.o qstringlist.o qabstractfileengine.o qtemporaryfile.o \
qmap.o qmetatype.o qsettings.o qsystemerror.o qlibraryinfo.o qvariant.o qvsnprintf.o \
qlocale.o qlocale_tools.o qlocale_unix.o qlinkedlist.o qurl.o qnumeric.o qcryptographichash.o \
qlocale.o qlocale_tools.o qlocale_unix.o qlinkedlist.o qnumeric.o qcryptographichash.o \
qxmlstream.o qxmlutils.o qlogging.o \
$(QTOBJS)
@ -39,10 +39,12 @@ DEPEND_SRC=project.cpp property.cpp meta.cpp main.cpp generators/makefile.cpp ge
generators/integrity/gbuild.cpp \
$(SOURCE_PATH)/src/corelib/codecs/qtextcodec.cpp $(SOURCE_PATH)/src/corelib/codecs/qutfcodec.cpp \
$(SOURCE_PATH)/src/corelib/tools/qstring.cpp $(SOURCE_PATH)/src/corelib/io/qfile.cpp \
$(SOURCE_PATH)/src/corelib/io/qfiledevice.cpp \
$(SOURCE_PATH)/src/corelib/io/qtextstream.cpp $(SOURCE_PATH)/src/corelib/io/qiodevice.cpp \
$(SOURCE_PATH)/src/corelib/global/qmalloc.cpp \
$(SOURCE_PATH)/src/corelib/global/qglobal.cpp $(SOURCE_PATH)/src/corelib/tools/qregexp.cpp \
$(SOURCE_PATH)/src/corelib/tools/qbytearray.cpp $(SOURCE_PATH)/src/corelib/tools/qbytearraymatcher.cpp \
$(SOURCE_PATH)/src/corelib/tools/qarraydata.cpp $(SOURCE_PATH)/src/corelib/tools/qbytearray.cpp\
$(SOURCE_PATH)/src/corelib/tools/qbytearraymatcher.cpp \
$(SOURCE_PATH)/src/corelib/io/qdatastream.cpp $(SOURCE_PATH)/src/corelib/io/qbuffer.cpp \
$(SOURCE_PATH)/src/corelib/io/qfilesystementry.cpp $(SOURCE_PATH)/src/corelib/io/qfilesystemengine_unix.cpp \
$(SOURCE_PATH)/src/corelib/io/qfilesystemengine_mac.cpp \
@ -55,7 +57,8 @@ DEPEND_SRC=project.cpp property.cpp meta.cpp main.cpp generators/makefile.cpp ge
$(SOURCE_PATH)/src/corelib/io/qdir.cpp $(SOURCE_PATH)/src/corelib/plugin/quuid.cpp \
$(SOURCE_PATH)/src/corelib/io/qfileinfo.cpp $(SOURCE_PATH)/src/corelib/tools/qdatetime.cpp \
$(SOURCE_PATH)/src/corelib/tools/qstringlist.cpp $(SOURCE_PATH)/src/corelib/tools/qmap.cpp \
$(SOURCE_PATH)/src/corelib/global/qconfig.cpp $(SOURCE_PATH)/src/corelib/io/qurl.cpp \
$(SOURCE_PATH)/src/corelib/global/qconfig.cpp \
$(SOURCE_PATH)/src/corelib/tools/qstringbuilder.cpp \
$(SOURCE_PATH)/src/corelib/tools/qlocale.cpp \
$(SOURCE_PATH)/src/corelib/tools/qlocale_tools.cpp \
$(SOURCE_PATH)/src/corelib/tools/qlocale_unix.cpp \
@ -78,7 +81,7 @@ CPPFLAGS = -g -I$(QMKSRC) -I$(QMKSRC)/generators -I$(QMKSRC)/generators/unix -I$
-I$(BUILD_PATH)/src/corelib/global \
-I$(SOURCE_PATH)/tools/shared \
-DQT_BUILD_QMAKE -DQT_BOOTSTRAPPED \
-DQT_NO_TEXTCODEC -DQT_NO_UNICODETABLES -DQT_NO_COMPONENT -DQT_NO_STL \
-DQT_NO_TEXTCODEC -DQT_NO_UNICODETABLES -DQT_NO_COMPONENT \
-DQT_NO_COMPRESS -I$(QMAKESPEC) -DHAVE_QCONFIG_CPP -DQT_NO_THREAD -DQT_NO_QOBJECT \
-DQT_NO_GEOM_VARIANT -DQT_NO_DEPRECATED $(OPENSOURCE_CXXFLAGS)
@ -197,6 +200,9 @@ qmalloc.o: $(SOURCE_PATH)/src/corelib/global/qmalloc.cpp
qglobal.o: $(SOURCE_PATH)/src/corelib/global/qglobal.cpp
$(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qglobal.cpp
qarraydata.o: $(SOURCE_PATH)/src/corelib/tools/qarraydata.cpp
$(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qarraydata.cpp
qbytearray.o: $(SOURCE_PATH)/src/corelib/tools/qbytearray.cpp
$(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qbytearray.cpp
@ -212,9 +218,6 @@ qmetatype.o: $(SOURCE_PATH)/src/corelib/kernel/qmetatype.cpp
qcore_mac.o: $(SOURCE_PATH)/src/corelib/kernel/qcore_mac.cpp
$(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/kernel/qcore_mac.cpp
qurl.o: $(SOURCE_PATH)/src/corelib/io/qurl.cpp
$(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qurl.cpp
qutfcodec.o: $(SOURCE_PATH)/src/corelib/codecs/qutfcodec.cpp
$(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/codecs/qutfcodec.cpp
@ -224,6 +227,9 @@ qtextcodec.o: $(SOURCE_PATH)/src/corelib/codecs/qtextcodec.cpp
qstring.o: $(SOURCE_PATH)/src/corelib/tools/qstring.cpp
$(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qstring.cpp
qstringbuilder.o: $(SOURCE_PATH)/src/corelib/tools/qstringbuilder.cpp
$(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qstringbuilder.cpp
qlocale.o: $(SOURCE_PATH)/src/corelib/tools/qlocale.cpp
$(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qlocale.cpp
@ -245,6 +251,9 @@ qlist.o: $(SOURCE_PATH)/src/corelib/tools/qlist.cpp
qfile.o: $(SOURCE_PATH)/src/corelib/io/qfile.cpp
$(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfile.cpp
qfiledevice.o: $(SOURCE_PATH)/src/corelib/io/qfiledevice.cpp
$(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfiledevice.cpp
qfilesystementry.o: $(SOURCE_PATH)/src/corelib/io/qfilesystementry.cpp
$(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfilesystementry.cpp

View File

@ -38,7 +38,7 @@ CFLAGS_BARE = -c -Fo./ \
-I$(BUILD_PATH)\src\corelib\global \
-I$(SOURCE_PATH)\mkspecs\$(QMAKESPEC) \
-I$(SOURCE_PATH)\tools\shared \
-DQT_NO_TEXTCODEC -DQT_NO_UNICODETABLES -DQT_LITE_COMPONENT -DQT_NODLL -DQT_NO_STL \
-DQT_NO_TEXTCODEC -DQT_NO_UNICODETABLES -DQT_LITE_COMPONENT -DQT_NODLL \
-DQT_NO_COMPRESS -DUNICODE -DHAVE_QCONFIG_CPP -DQT_BUILD_QMAKE -DQT_NO_THREAD \
-DQT_NO_QOBJECT -DQT_NO_GEOM_VARIANT -DQT_NO_DATASTREAM -DQT_BOOTSTRAPPED
CFLAGS = -Yuqmake_pch.h -FIqmake_pch.h -Fpqmake_pch.pch $(CFLAGS_BARE) $(CFLAGS)
@ -78,12 +78,14 @@ QTOBJS= \
qfilesystemiterator_win.obj \
qfsfileengine.obj \
qfsfileengine_iterator.obj \
qarraydata.obj \
qbytearray.obj \
qvsnprintf.obj \
qbytearraymatcher.obj \
qdatetime.obj \
qdir.obj \
qdiriterator.obj \
qfiledevice.obj \
qfile.obj \
qtemporaryfile.obj \
qabstractfileengine.obj \
@ -105,6 +107,7 @@ QTOBJS= \
qutfcodec.obj \
qstring.obj \
qstringlist.obj \
qstringbuilder.obj \
qsystemerror.obj \
qtextstream.obj \
qdatastream.obj \
@ -113,7 +116,6 @@ QTOBJS= \
qsettings.obj \
qlibraryinfo.obj \
qvariant.obj \
qurl.obj \
qsettings_win.obj \
qmetatype.obj \
qxmlstream.obj \

View File

@ -49,7 +49,7 @@ CFLAGS = -c -o$@ -O \
-I$(SOURCE_PATH)/mkspecs/win32-g++ \
-I$(SOURCE_PATH)/tools/shared \
-DQT_NO_TEXTCODEC -DQT_NO_UNICODETABLES -DQT_LITE_COMPONENT \
-DQT_NODLL -DQT_NO_STL -DQT_NO_COMPRESS -DUNICODE -DHAVE_QCONFIG_CPP \
-DQT_NODLL -DQT_NO_COMPRESS -DUNICODE -DHAVE_QCONFIG_CPP \
-DQT_BUILD_QMAKE -DQT_NO_THREAD -DQT_NO_QOBJECT -DQT_NO_GEOM_VARIANT -DQT_NO_DATASTREAM \
-DQT_BOOTSTRAPPED
CXXFLAGS = $(CFLAGS)
@ -74,6 +74,7 @@ endif
QTOBJS= \
qbitarray.o \
qbuffer.o \
qarraydata.o \
qbytearray.o \
qcryptographichash.o \
qvsnprintf.o \
@ -82,6 +83,7 @@ QTOBJS= \
qdatetime.o \
qdir.o \
qdiriterator.o \
qfiledevice.o \
qfile.o \
qtemporaryfile.o \
qfileinfo.o \
@ -109,12 +111,12 @@ QTOBJS= \
qutfcodec.o \
qstring.o \
qstringlist.o \
qstringbuilder.o \
qsystemerror.o \
qsystemlibrary.o \
qtextstream.o \
quuid.o \
qvector.o \
qurl.o \
qsettings.o \
qsettings_win.o \
qvariant.o \

View File

@ -1928,7 +1928,7 @@ ProjectBuilderMakefileGenerator::writeSettings(QString var, QStringList vals, in
{
QString ret;
const QString quote = (flags & SettingsNoQuote) ? "" : "\"";
const QString escape_quote = quote.isEmpty() ? "" : "\\" + quote;
const QString escape_quote = quote.isEmpty() ? "" : QString("\\" + quote);
QString newline = "\n";
for(int i = 0; i < indent_level; ++i)
newline += "\t";

View File

@ -1026,7 +1026,7 @@ QMakeProject::parse(const QString &t, QHash<QString, QStringList> &place, int nu
debug_msg(1, "Project Parser: %s:%d : Entering block %d (%d). [%s]", parser.file.toLatin1().constData(),
parser.line_no, scope_blocks.count(), scope_failed, s.toLatin1().constData());
} else if(iterator) {
iterator->parselist.append(var+s.mid(d_off));
iterator->parselist.append(QString(var+s.mid(d_off)));
bool ret = iterator->exec(this, place);
delete iterator;
return ret;

View File

@ -1,7 +1,7 @@
CONFIG += depend_includepath
SKIP_DEPENDS += qconfig.h qmodules.h
DEFINES += QT_NO_TEXTCODEC QT_NO_LIBRARY QT_NO_STL QT_NO_COMPRESS QT_NO_UNICODETABLES \
DEFINES += QT_NO_TEXTCODEC QT_NO_LIBRARY QT_NO_COMPRESS QT_NO_UNICODETABLES \
QT_NO_GEOM_VARIANT QT_NO_DATASTREAM
#qmake code
@ -35,12 +35,14 @@ bootstrap { #Qt code
SOURCES+= \
qbitarray.cpp \
qbuffer.cpp \
qarraydata.cpp \
qbytearray.cpp \
qbytearraymatcher.cpp \
qcryptographichash.cpp \
qdatetime.cpp \
qdir.cpp \
qdiriterator.cpp \
qfiledevice.cpp \
qfile.cpp \
qabstractfileengine.cpp \
qfileinfo.cpp \
@ -66,7 +68,6 @@ bootstrap { #Qt code
qstringlist.cpp \
qtemporaryfile.cpp \
qtextstream.cpp \
qurl.cpp \
quuid.cpp \
qsettings.cpp \
qlibraryinfo.cpp \
@ -81,7 +82,10 @@ bootstrap { #Qt code
HEADERS+= \
qbitarray.h \
qbuffer.h \
qarraydata.h \
qbytearray.h \
qarraydataops.h \
qarraydatapointer.h \
qbytearraymatcher.h \
qchar.h \
qcryptographichash.h \
@ -113,7 +117,6 @@ bootstrap { #Qt code
qsystemerror_p.h \
qtemporaryfile.h \
qtextstream.h \
qurl.h \
quuid.h \
qvector.h \
qxmlstream.h \

View File

@ -41,6 +41,11 @@
#ifndef QMAKE_PCH_H
#define QMAKE_PCH_H
// for rand_s, _CRT_RAND_S must be #defined before #including stdlib.h.
// put it at the beginning so some indirect inclusion doesn't break it
#ifndef _CRT_RAND_S
#define _CRT_RAND_S
#endif
#include <qglobal.h>
#ifdef Q_OS_WIN
# define _POSIX_

View File

@ -50,9 +50,7 @@
#include <QtConcurrent/qtconcurrentmedian.h>
#include <QtConcurrent/qtconcurrentthreadengine.h>
#ifndef QT_NO_STL
# include <iterator>
#endif
#include <iterator>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
@ -62,15 +60,7 @@ QT_BEGIN_NAMESPACE
namespace QtConcurrent {
#ifndef QT_NO_STL
using std::advance;
#else
template <typename It, typename T>
void advance(It &it, T value)
{
it+=value;
}
#endif
/*
The BlockSizeManager class manages how many iterations a thread should
@ -149,7 +139,6 @@ public:
inline void * getPointer() { return 0; }
};
#ifndef QT_NO_STL
inline bool selectIteration(std::bidirectional_iterator_tag)
{
return false; // while
@ -164,14 +153,6 @@ inline bool selectIteration(std::random_access_iterator_tag)
{
return true; // for
}
#else
// no stl support, always use while iteration
template <typename T>
inline bool selectIteration(T)
{
return false; // while
}
#endif
template <typename Iterator, typename T>
class IterateKernel : public ThreadEngine<T>
@ -180,20 +161,10 @@ public:
typedef T ResultType;
IterateKernel(Iterator _begin, Iterator _end)
#if defined (QT_NO_STL)
: begin(_begin), end(_end), current(_begin), currentIndex(0),
forIteration(false), progressReportingEnabled(true)
#else
: begin(_begin), end(_end), current(_begin), currentIndex(0),
forIteration(selectIteration(typename std::iterator_traits<Iterator>::iterator_category())), progressReportingEnabled(true)
#endif
{
#if defined (QT_NO_STL)
iterationCount = 0;
#else
iterationCount = forIteration ? std::distance(_begin, _end) : 0;
#endif
}
virtual ~IterateKernel() { }

View File

@ -9,14 +9,13 @@ HEADERS += \
arch/qatomic_armv7.h \
arch/qatomic_bfin.h \
arch/qatomic_bootstrap.h \
arch/qatomic_i386.h \
arch/qatomic_ia64.h \
arch/qatomic_mips.h \
arch/qatomic_power.h \
arch/qatomic_s390.h \
arch/qatomic_sh4a.h \
arch/qatomic_sparc.h \
arch/qatomic_x86_64.h \
arch/qatomic_x86.h \
arch/qatomic_gcc.h \
arch/qatomic_cxx11.h

View File

@ -1,358 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Copyright (C) 2011 Thiago Macieira <thiago@kde.org>
** Contact: http://www.qt-project.org/
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** 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.
**
** 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.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QATOMIC_I386_H
#define QATOMIC_I386_H
#include <QtCore/qgenericatomic.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
#if 0
// silence syncqt warnings
QT_END_NAMESPACE
QT_END_HEADER
#pragma qt_sync_stop_processing
#endif
template<> struct QAtomicIntegerTraits<int> { enum { IsInteger = 1 }; };
template<> struct QAtomicIntegerTraits<unsigned int> { enum { IsInteger = 1 }; };
#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_WAIT_FREE
#define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE
#define Q_ATOMIC_INT_TEST_AND_SET_IS_WAIT_FREE
#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE
#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_WAIT_FREE
#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE
#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_WAIT_FREE
#define Q_ATOMIC_INT32_IS_SUPPORTED
#define Q_ATOMIC_INT32_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
#define Q_ATOMIC_INT32_REFERENCE_COUNTING_IS_WAIT_FREE
#define Q_ATOMIC_INT32_TEST_AND_SET_IS_ALWAYS_NATIVE
#define Q_ATOMIC_INT32_TEST_AND_SET_IS_WAIT_FREE
#define Q_ATOMIC_INT32_FETCH_AND_STORE_IS_ALWAYS_NATIVE
#define Q_ATOMIC_INT32_FETCH_AND_STORE_IS_WAIT_FREE
#define Q_ATOMIC_INT32_FETCH_AND_ADD_IS_ALWAYS_NATIVE
#define Q_ATOMIC_INT32_FETCH_AND_ADD_IS_WAIT_FREE
#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE
#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_WAIT_FREE
#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE
#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_WAIT_FREE
#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE
#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_WAIT_FREE
template <int size> struct QBasicAtomicOps: QGenericAtomicOps<QBasicAtomicOps<size> >
{
static inline bool isReferenceCountingNative() { return true; }
static inline bool isReferenceCountingWaitFree() { return true; }
template <typename T> static bool ref(T &_q_value);
template <typename T> static bool deref(T &_q_value);
static inline bool isTestAndSetNative() { return true; }
static inline bool isTestAndSetWaitFree() { return true; }
template <typename T> static bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue);
static inline bool isFetchAndStoreNative() { return true; }
static inline bool isFetchAndStoreWaitFree() { return true; }
template <typename T> static T fetchAndStoreRelaxed(T &_q_value, T newValue);
static inline bool isFetchAndAddNative() { return true; }
static inline bool isFetchAndAddWaitFree() { return true; }
template <typename T> static
T fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd);
};
template <typename T> struct QAtomicOps : QBasicAtomicOps<sizeof(T)>
{
typedef T Type;
};
#if defined(Q_CC_GNU) || defined(Q_CC_INTEL)
template<> struct QAtomicIntegerTraits<char> { enum { IsInteger = 1 }; };
template<> struct QAtomicIntegerTraits<signed char> { enum { IsInteger = 1 }; };
template<> struct QAtomicIntegerTraits<unsigned char> { enum { IsInteger = 1 }; };
template<> struct QAtomicIntegerTraits<short> { enum { IsInteger = 1 }; };
template<> struct QAtomicIntegerTraits<unsigned short> { enum { IsInteger = 1 }; };
template<> struct QAtomicIntegerTraits<long> { enum { IsInteger = 1 }; };
template<> struct QAtomicIntegerTraits<unsigned long> { enum { IsInteger = 1 }; };
template<> struct QAtomicIntegerTraits<long long> { enum { IsInteger = 1 }; };
template<> struct QAtomicIntegerTraits<unsigned long long> { enum { IsInteger = 1 }; };
template<> template<typename T> inline
bool QBasicAtomicOps<1>::ref(T &_q_value)
{
unsigned char ret;
asm volatile("lock\n"
"incb %0\n"
"setne %1"
: "+m" (_q_value), "=qm" (ret)
:
: "memory");
return ret != 0;
}
template<> template<typename T> inline
bool QBasicAtomicOps<2>::ref(T &_q_value)
{
unsigned char ret;
asm volatile("lock\n"
"incw %0\n"
"setne %1"
: "+m" (_q_value), "=qm" (ret)
:
: "memory");
return ret != 0;
}
template<> template<typename T> inline
bool QBasicAtomicOps<4>::ref(T &_q_value)
{
unsigned char ret;
asm volatile("lock\n"
"incl %0\n"
"setne %1"
: "+m" (_q_value), "=qm" (ret)
:
: "memory");
return ret != 0;
}
template<> template <typename T> inline
bool QBasicAtomicOps<1>::deref(T &_q_value)
{
unsigned char ret;
asm volatile("lock\n"
"decb %0\n"
"setne %1"
: "+m" (_q_value), "=qm" (ret)
:
: "memory");
return ret != 0;
}
template<> template <typename T> inline
bool QBasicAtomicOps<2>::deref(T &_q_value)
{
unsigned char ret;
asm volatile("lock\n"
"decw %0\n"
"setne %1"
: "+m" (_q_value), "=qm" (ret)
:
: "memory");
return ret != 0;
}
template<> template <typename T> inline
bool QBasicAtomicOps<4>::deref(T &_q_value)
{
unsigned char ret;
asm volatile("lock\n"
"decl %0\n"
"setne %1"
: "+m" (_q_value), "=qm" (ret)
:
: "memory");
return ret != 0;
}
template<int size> template <typename T> inline
bool QBasicAtomicOps<size>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue)
{
unsigned char ret;
asm volatile("lock\n"
"cmpxchg %3,%2\n"
"sete %1\n"
: "=a" (newValue), "=qm" (ret), "+m" (_q_value)
: "r" (newValue), "0" (expectedValue)
: "memory");
return ret != 0;
}
template<> template <typename T> inline
bool QBasicAtomicOps<1>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue)
{
unsigned char ret;
asm volatile("lock\n"
"cmpxchg %3,%2\n"
"sete %1\n"
: "=a" (newValue), "=qm" (ret), "+m" (_q_value)
: "q" (newValue), "0" (expectedValue)
: "memory");
return ret != 0;
}
template<int size> template <typename T> inline
T QBasicAtomicOps<size>::fetchAndStoreRelaxed(T &_q_value, T newValue)
{
asm volatile("xchg %0,%1"
: "=r" (newValue), "+m" (_q_value)
: "0" (newValue)
: "memory");
return newValue;
}
template<> template <typename T> inline
T QBasicAtomicOps<1>::fetchAndStoreRelaxed(T &_q_value, T newValue)
{
asm volatile("xchg %0,%1"
: "=q" (newValue), "+m" (_q_value)
: "0" (newValue)
: "memory");
return newValue;
}
template<int size> template <typename T> inline
T QBasicAtomicOps<size>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd)
{
T result;
asm volatile("lock\n"
"xadd %0,%1"
: "=r" (result), "+m" (_q_value)
: "0" (T(valueToAdd * QAtomicAdditiveType<T>::AddScale))
: "memory");
return result;
}
template<> template <typename T> inline
T QBasicAtomicOps<1>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd)
{
T result;
asm volatile("lock\n"
"xadd %0,%1"
: "=q" (result), "+m" (_q_value)
: "0" (T(valueToAdd * QAtomicAdditiveType<T>::AddScale))
: "memory");
return result;
}
#define Q_ATOMIC_INT8_IS_SUPPORTED
#define Q_ATOMIC_INT8_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
#define Q_ATOMIC_INT8_REFERENCE_COUNTING_IS_WAIT_FREE
#define Q_ATOMIC_INT8_TEST_AND_SET_IS_ALWAYS_NATIVE
#define Q_ATOMIC_INT8_TEST_AND_SET_IS_WAIT_FREE
#define Q_ATOMIC_INT8_FETCH_AND_STORE_IS_ALWAYS_NATIVE
#define Q_ATOMIC_INT8_FETCH_AND_STORE_IS_WAIT_FREE
#define Q_ATOMIC_INT8_FETCH_AND_ADD_IS_ALWAYS_NATIVE
#define Q_ATOMIC_INT8_FETCH_AND_ADD_IS_WAIT_FREE
#define Q_ATOMIC_INT16_IS_SUPPORTED
#define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
#define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_WAIT_FREE
#define Q_ATOMIC_INT16_TEST_AND_SET_IS_ALWAYS_NATIVE
#define Q_ATOMIC_INT16_TEST_AND_SET_IS_WAIT_FREE
#define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_ALWAYS_NATIVE
#define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_WAIT_FREE
#define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_ALWAYS_NATIVE
#define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_WAIT_FREE
template <> struct QBasicAtomicOps<8>: QGenericAtomicOps<QBasicAtomicOps<8> >
{
static inline bool isTestAndSetNative() { return true; }
static inline bool isTestAndSetWaitFree() { return true; }
template <typename T> static inline
bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue)
{
#ifdef __PIC__
# define EBX_reg "r"
# define EBX_load(reg) "xchg " reg ", %%ebx\n"
#else
# define EBX_reg "b"
# define EBX_load(reg)
#endif
unsigned char ret;
asm volatile(EBX_load("%3")
"lock\n"
"cmpxchg8b %0\n"
EBX_load("%3")
"sete %1\n"
: "+m" (_q_value), "=qm" (ret),
"+A" (expectedValue)
: EBX_reg (quint32(newValue & 0xffffffff)), "c" (quint32(newValue >> 32))
: "memory");
return ret != 0;
#undef EBX_reg
#undef EBX_load
}
};
#define Q_ATOMIC_INT64_IS_SUPPORTED
#define Q_ATOMIC_INT64_REFERENCE_COUNTING_IS_NOT_NATIVE
#define Q_ATOMIC_INT64_TEST_AND_SET_IS_NOT_NATIVE
#define Q_ATOMIC_INT64_TEST_AND_SET_IS_WAIT_FREE
#define Q_ATOMIC_INT64_FETCH_AND_STORE_IS_NATIVE
#define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_NOT_NATIVE
#else
# error "This compiler for i386 is not supported"
#endif
QT_END_NAMESPACE
QT_END_HEADER
#endif // QATOMIC_I386_H

View File

@ -40,8 +40,8 @@
**
****************************************************************************/
#ifndef QATOMIC_X86_64_H
#define QATOMIC_X86_64_H
#ifndef QATOMIC_X86_H
#define QATOMIC_X86_H
#include <QtCore/qgenericatomic.h>
@ -121,7 +121,7 @@ template <typename T> struct QAtomicOps : QBasicAtomicOps<sizeof(T)>
typedef T Type;
};
#if defined(Q_CC_GNU) || defined(Q_CC_INTEL)
#if defined(Q_CC_GNU)
template<> struct QAtomicIntegerTraits<char> { enum { IsInteger = 1 }; };
template<> struct QAtomicIntegerTraits<signed char> { enum { IsInteger = 1 }; };
@ -133,12 +133,40 @@ template<> struct QAtomicIntegerTraits<unsigned long> { enum { IsInteger = 1 };
template<> struct QAtomicIntegerTraits<long long> { enum { IsInteger = 1 }; };
template<> struct QAtomicIntegerTraits<unsigned long long> { enum { IsInteger = 1 }; };
/*
* Guide for the inline assembly below:
*
* x86 instructions are in the form "{opcode}{length} {source}, {destination}",
* where the length is one of the letters "b" (byte), "w" (word, 16-bit), "l"
* (dword, 32-bit), "q" (qword, 64-bit).
*
* In most cases, we can omit the length because it's inferred from one of the
* registers. For example, "xchg %0,%1" doesn't need the length suffix because
* we can only exchange data of the same size and one of the operands must be a
* register.
*
* The exception is the increment and decrement functions, where we add and
* subtract an immediate value (1). For those, we need to specify the length.
* GCC and ICC support the syntax "add%z0 $1, %0", where "%z0" expands to the
* length of the operand. Unfortunately, clang as of 3.0 doesn't support that.
* For that reason, the ref() and deref() functions are rolled out for all
* sizes.
*
* The functions are also rolled out for the 1-byte operations since those
* require a special register constraint "q" to force the compiler to schedule
* one of the 8-bit registers. It's probably a compiler bug that it tries to
* use a register that doesn't exist.
*
* Finally, 64-bit operations are supported via the cmpxchg8b instruction on
* 32-bit processors, via specialisation below.
*/
template<> template<typename T> inline
bool QBasicAtomicOps<1>::ref(T &_q_value)
{
unsigned char ret;
asm volatile("lock\n"
"incb %0\n"
"addb $1, %0\n"
"setne %1"
: "=m" (_q_value), "=qm" (ret)
: "m" (_q_value)
@ -164,20 +192,7 @@ bool QBasicAtomicOps<4>::ref(T &_q_value)
{
unsigned char ret;
asm volatile("lock\n"
"incl %0\n"
"setne %1"
: "=m" (_q_value), "=qm" (ret)
: "m" (_q_value)
: "memory");
return ret != 0;
}
template<> template<typename T> inline
bool QBasicAtomicOps<8>::ref(T &_q_value)
{
unsigned char ret;
asm volatile("lock\n"
"incq %0\n"
"addl $1, %0\n"
"setne %1"
: "=m" (_q_value), "=qm" (ret)
: "m" (_q_value)
@ -190,7 +205,7 @@ bool QBasicAtomicOps<1>::deref(T &_q_value)
{
unsigned char ret;
asm volatile("lock\n"
"decb %0\n"
"subb $1, %0\n"
"setne %1"
: "=m" (_q_value), "=qm" (ret)
: "m" (_q_value)
@ -215,20 +230,7 @@ bool QBasicAtomicOps<4>::deref(T &_q_value)
{
unsigned char ret;
asm volatile("lock\n"
"decl %0\n"
"setne %1"
: "=m" (_q_value), "=qm" (ret)
: "m" (_q_value)
: "memory");
return ret != 0;
}
template<> template <typename T> inline
bool QBasicAtomicOps<8>::deref(T &_q_value)
{
unsigned char ret;
asm volatile("lock\n"
"decq %0\n"
"subl $1, %0\n"
"setne %1"
: "=m" (_q_value), "=qm" (ret)
: "m" (_q_value)
@ -348,12 +350,73 @@ T QBasicAtomicOps<1>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveTy
#define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_ALWAYS_NATIVE
#define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_WAIT_FREE
#else // !Q_CC_INTEL && !Q_CC_GNU
# error "This compiler for x86_64 is not supported"
#endif // Q_CC_GNU || Q_CC_INTEL
#ifdef Q_PROCESSOR_X86_64
// native support for 64-bit types
template<> template<typename T> inline
bool QBasicAtomicOps<8>::ref(T &_q_value)
{
unsigned char ret;
asm volatile("lock\n"
"addq $1, %0\n"
"setne %1"
: "=m" (_q_value), "=qm" (ret)
: "m" (_q_value)
: "memory");
return ret != 0;
}
template<> template <typename T> inline
bool QBasicAtomicOps<8>::deref(T &_q_value)
{
unsigned char ret;
asm volatile("lock\n"
"subq $1, %0\n"
"setne %1"
: "=m" (_q_value), "=qm" (ret)
: "m" (_q_value)
: "memory");
return ret != 0;
}
#else
// i386 architecture, emulate 64-bit support via cmpxchg8b
template <> struct QBasicAtomicOps<8>: QGenericAtomicOps<QBasicAtomicOps<8> >
{
static inline bool isTestAndSetNative() { return true; }
static inline bool isTestAndSetWaitFree() { return true; }
template <typename T> static inline
bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue)
{
#ifdef __PIC__
# define EBX_reg "r"
# define EBX_load(reg) "xchg " reg ", %%ebx\n"
#else
# define EBX_reg "b"
# define EBX_load(reg)
#endif
quint32 highExpectedValue = quint32(newValue >> 32); // ECX
asm volatile(EBX_load("%3")
"lock\n"
"cmpxchg8b %0\n"
EBX_load("%3")
"sete %%cl\n"
: "+m" (_q_value), "+c" (highExpectedValue), "+&A" (expectedValue)
: EBX_reg (quint32(newValue & 0xffffffff))
: "memory");
// if the comparison failed, expectedValue here contains the current value
return quint8(highExpectedValue) != 0;
#undef EBX_reg
#undef EBX_load
}
};
#endif
#else
# error "This compiler for x86 is not supported"
#endif
QT_END_NAMESPACE
QT_END_HEADER
#endif // QATOMIC_X86_64_H
#endif // QATOMIC_X86_H

View File

@ -102,6 +102,10 @@
# undef QT_HAVE_3DNOW
# endif
# if defined(Q_CC_MSVC) && _MSC_VER >= 1400
# define Q_COMPILER_VARIADIC_MACROS
# endif
#if defined(Q_CC_MSVC) && _MSC_VER >= 1600
# define Q_COMPILER_RVALUE_REFS
# define Q_COMPILER_AUTO_TYPE

View File

@ -159,9 +159,6 @@
#ifndef QT_NO_DATETIMEEDIT
# define QT_NO_DATETIMEEDIT
#endif
#ifndef QT_NO_WORKSPACE
# define QT_NO_WORKSPACE
#endif
#ifndef QT_NO_DIAL
# define QT_NO_DIAL
#endif

View File

@ -242,9 +242,6 @@
#ifndef QT_NO_MENUBAR
# define QT_NO_MENUBAR
#endif
#ifndef QT_NO_WORKSPACE
# define QT_NO_WORKSPACE
#endif
#ifndef QT_NO_PROGRESSBAR
# define QT_NO_PROGRESSBAR
#endif

View File

@ -43,9 +43,6 @@
#ifndef QT_NO_QUUID_STRING
# define QT_NO_QUUID_STRING
#endif
#ifndef QT_NO_STL
# define QT_NO_STL
#endif
#ifndef QT_NO_TEXTDATE
# define QT_NO_TEXTDATE
#endif
@ -494,9 +491,6 @@
#ifndef QT_NO_MENUBAR
# define QT_NO_MENUBAR
#endif
#ifndef QT_NO_WORKSPACE
# define QT_NO_WORKSPACE
#endif
#ifndef QT_NO_PROGRESSBAR
# define QT_NO_PROGRESSBAR
#endif

View File

@ -45,9 +45,6 @@
#ifndef QT_NO_QUUID_STRING
# define QT_NO_QUUID_STRING
#endif
#ifndef QT_NO_STL
# define QT_NO_STL
#endif
#ifndef QT_NO_TEXTDATE
# define QT_NO_TEXTDATE
#endif

View File

@ -43,9 +43,6 @@
#ifndef QT_NO_QUUID_STRING
# define QT_NO_QUUID_STRING
#endif
#ifndef QT_NO_STL
# define QT_NO_STL
#endif
/* Dialogs */
#ifndef QT_NO_COLORDIALOG
@ -282,9 +279,6 @@
#ifndef QT_NO_MENUBAR
# define QT_NO_MENUBAR
#endif
#ifndef QT_NO_WORKSPACE
# define QT_NO_WORKSPACE
#endif
#ifndef QT_NO_PROGRESSBAR
# define QT_NO_PROGRESSBAR
#endif

View File

@ -79,7 +79,7 @@ template <typename T> inline void qbswap(const T src, uchar *dest)
// If you want to avoid the memcopy, you must write specializations for this function
template <typename T> inline void qToUnaligned(const T src, uchar *dest)
{
qMemCopy(dest, &src, sizeof(T));
memcpy(dest, &src, sizeof(T));
}
/* T qFromLittleEndian(const uchar *src)
@ -171,6 +171,11 @@ template <> inline qint16 qFromLittleEndian<qint16>(const uchar *src)
{ return static_cast<qint16>(qFromLittleEndian<quint16>(src)); }
#endif
template <> inline quint8 qFromLittleEndian<quint8>(const uchar *src)
{ return static_cast<quint8>(src[0]); }
template <> inline qint8 qFromLittleEndian<qint8>(const uchar *src)
{ return static_cast<qint8>(src[0]); }
/* This function will read a big-endian (also known as network order) encoded value from \a src
* and return the value in host-endian encoding.
* There is no requirement that \a src must be aligned.
@ -263,6 +268,12 @@ template <> inline qint32 qFromBigEndian<qint32>(const uchar *src)
template <> inline qint16 qFromBigEndian<qint16>(const uchar *src)
{ return static_cast<qint16>(qFromBigEndian<quint16>(src)); }
#endif
template <> inline quint8 qFromBigEndian<quint8>(const uchar *src)
{ return static_cast<quint8>(src[0]); }
template <> inline qint8 qFromBigEndian<qint8>(const uchar *src)
{ return static_cast<qint8>(src[0]); }
/*
* T qbswap(T source).
* Changes the byte order of a value from big endian to little endian or vice versa.
@ -367,6 +378,11 @@ template <> inline quint8 qbswap<quint8>(quint8 source)
return source;
}
template <> inline qint8 qbswap<qint8>(qint8 source)
{
return source;
}
QT_END_NAMESPACE
QT_END_HEADER

View File

@ -208,9 +208,6 @@
// Status Tip
//#define QT_NO_STATUSTIP
// Standard Template Library
//#define QT_NO_STL
// QMotifStyle
//#define QT_NO_STYLE_MOTIF
@ -487,11 +484,6 @@
#define QT_NO_STYLE_STYLESHEET
#endif
// Q3TabDialog
#if !defined(QT_NO_TABDIALOG) && (defined(QT_NO_TABBAR))
#define QT_NO_TABDIALOG
#endif
// QColorDialog
#if !defined(QT_NO_COLORDIALOG) && (defined(QT_NO_SPINBOX))
#define QT_NO_COLORDIALOG
@ -662,11 +654,6 @@
#define QT_NO_PRINTPREVIEWWIDGET
#endif
// QWorkSpace
#if !defined(QT_NO_WORKSPACE) && (defined(QT_NO_SCROLLBAR) || defined(QT_NO_MAINWINDOW) || defined(QT_NO_MENUBAR))
#define QT_NO_WORKSPACE
#endif
// QCalendarWidget
#if !defined(QT_NO_CALENDARWIDGET) && (defined(QT_NO_TABLEVIEW) || defined(QT_NO_MENU) || defined(QT_NO_TEXTDATE) || defined(QT_NO_SPINBOX) || defined(QT_NO_TOOLBUTTON))
#define QT_NO_CALENDARWIDGET

View File

@ -407,13 +407,6 @@ Requires: RUBBERBAND MAINWINDOW
Name: QDockwidget
SeeAlso: ???
Feature: WORKSPACE
Description: Supports workspace windows, e.g. used in an MDI application.
Section: Widgets
Requires: SCROLLBAR MAINWINDOW MENUBAR
Name: QWorkSpace
SeeAlso: ???
Feature: MDIAREA
Description: Provides an area in which MDI windows are displayed.
Section: Widgets
@ -644,13 +637,6 @@ Requires: COMBOBOX SPINBOX STACKEDWIDGET
Name: QInputDialog
SeeAlso: ???
Feature: TABDIALOG
Description: Supports a stack of tabbed widgets.
Section: Dialogs
Requires: TABBAR
Name: Q3TabDialog
SeeAlso: ???
Feature: ERRORMESSAGE
Description: Supports an error message display dialog.
Section: Dialogs

View File

@ -1968,13 +1968,6 @@ Q_CORE_EXPORT unsigned int qt_int_sqrt(unsigned int n)
return p;
}
#if defined(qMemCopy)
# undef qMemCopy
#endif
#if defined(qMemSet)
# undef qMemSet
#endif
void *qMemCopy(void *dest, const void *src, size_t n) { return memcpy(dest, src, n); }
void *qMemSet(void *dest, int c, size_t n) { return memset(dest, c, n); }

View File

@ -69,9 +69,7 @@
#ifdef __cplusplus
#ifndef QT_NO_STL
#include <algorithm>
#endif
#ifndef QT_NAMESPACE /* user namespace */
@ -254,6 +252,56 @@ typedef quint64 qulonglong;
#if defined(__cplusplus)
namespace QtPrivate {
template <class T>
struct AlignOfHelper
{
char c;
T type;
AlignOfHelper();
~AlignOfHelper();
};
template <class T>
struct AlignOf_Default
{
enum { Value = sizeof(AlignOfHelper<T>) - sizeof(T) };
};
template <class T> struct AlignOf : AlignOf_Default<T> { };
template <class T> struct AlignOf<T &> : AlignOf<T> {};
template <size_t N, class T> struct AlignOf<T[N]> : AlignOf<T> {};
#ifdef Q_COMPILER_RVALUE_REFS
template <class T> struct AlignOf<T &&> : AlignOf<T> {};
#endif
#if defined(Q_PROCESSOR_X86_32) && !defined(Q_OS_WIN)
template <class T> struct AlignOf_WorkaroundForI386Abi { enum { Value = sizeof(T) }; };
// x86 ABI weirdness
// Alignment of naked type is 8, but inside struct has alignment 4.
template <> struct AlignOf<double> : AlignOf_WorkaroundForI386Abi<double> {};
template <> struct AlignOf<qint64> : AlignOf_WorkaroundForI386Abi<qint64> {};
template <> struct AlignOf<quint64> : AlignOf_WorkaroundForI386Abi<quint64> {};
#ifdef Q_CC_CLANG
// GCC and Clang seem to disagree wrt to alignment of arrays
template <size_t N> struct AlignOf<double[N]> : AlignOf_Default<double> {};
template <size_t N> struct AlignOf<qint64[N]> : AlignOf_Default<qint64> {};
template <size_t N> struct AlignOf<quint64[N]> : AlignOf_Default<quint64> {};
#endif
#endif
} // namespace QtPrivate
#define QT_EMULATED_ALIGNOF(T) \
(size_t(QT_PREPEND_NAMESPACE(QtPrivate)::AlignOf<T>::Value))
#ifndef Q_ALIGNOF
#define Q_ALIGNOF(T) QT_EMULATED_ALIGNOF(T)
#endif
/*
quintptr and qptrdiff is guaranteed to be the same size as a pointer, i.e.
@ -421,9 +469,15 @@ QT_END_INCLUDE_NAMESPACE
#ifdef Q_COMPILER_EXPLICIT_OVERRIDES
# define Q_DECL_OVERRIDE override
# define Q_DECL_FINAL final
# ifdef Q_COMPILER_DECLTYPE // required for class-level final to compile in qvariant_p.h
# define Q_DECL_FINAL_CLASS final
# else
# define Q_DECL_FINAL_CLASS
# endif
#else
# define Q_DECL_OVERRIDE
# define Q_DECL_FINAL
# define Q_DECL_FINAL_CLASS
#endif
#if defined(Q_COMPILER_ALIGNOF) && !defined(Q_ALIGNOF)
@ -1127,28 +1181,20 @@ static inline bool qIsNull(float f)
template <typename T>
inline void qSwap(T &value1, T &value2)
{
#ifdef QT_NO_STL
const T t = value1;
value1 = value2;
value2 = t;
#else
using std::swap;
swap(value1, value2);
#endif
}
/*
These functions make it possible to use standard C++ functions with
a similar name from Qt header files (especially template classes).
*/
Q_CORE_EXPORT void *qMalloc(size_t size) Q_ALLOC_SIZE(1);
Q_CORE_EXPORT void qFree(void *ptr);
Q_CORE_EXPORT void *qRealloc(void *ptr, size_t size) Q_ALLOC_SIZE(2);
#if QT_DEPRECATED_SINCE(5, 0)
Q_CORE_EXPORT QT_DEPRECATED void *qMalloc(size_t size) Q_ALLOC_SIZE(1);
Q_CORE_EXPORT QT_DEPRECATED void qFree(void *ptr);
Q_CORE_EXPORT QT_DEPRECATED void *qRealloc(void *ptr, size_t size) Q_ALLOC_SIZE(2);
Q_CORE_EXPORT QT_DEPRECATED void *qMemCopy(void *dest, const void *src, size_t n);
Q_CORE_EXPORT QT_DEPRECATED void *qMemSet(void *dest, int c, size_t n);
#endif
Q_CORE_EXPORT void *qMallocAligned(size_t size, size_t alignment) Q_ALLOC_SIZE(1);
Q_CORE_EXPORT void *qReallocAligned(void *ptr, size_t size, size_t oldsize, size_t alignment) Q_ALLOC_SIZE(2);
Q_CORE_EXPORT void qFreeAligned(void *ptr);
Q_CORE_EXPORT void *qMemCopy(void *dest, const void *src, size_t n);
Q_CORE_EXPORT void *qMemSet(void *dest, int c, size_t n);
/*
@ -1258,14 +1304,6 @@ inline const QForeachContainer<T> *qForeachContainer(const QForeachContainerBase
# endif
#endif
#if 0
/* tell gcc to use its built-in methods for some common functions */
#if defined(QT_NO_DEBUG) && defined(Q_CC_GNU)
# define qMemCopy __builtin_memcpy
# define qMemSet __builtin_memset
#endif
#endif
template <typename T> static inline T *qGetPtrHelper(T *ptr) { return ptr; }
template <typename Wrapper> static inline typename Wrapper::pointer qGetPtrHelper(const Wrapper &p) { return p.data(); }

View File

@ -49,10 +49,16 @@
# define Q_IS_ENUM(x) __is_enum(x)
# elif defined(Q_CC_MSVC) && defined(_MSC_FULL_VER) && (_MSC_FULL_VER >=140050215)
# define Q_IS_ENUM(x) __is_enum(x)
# else
# include <QtCore/qtypetraits.h>
# define Q_IS_ENUM(x) QtPrivate::is_enum<x>::value
# elif defined(Q_CC_CLANG)
# if __has_extension(is_enum)
# define Q_IS_ENUM(x) __is_enum(x)
# endif
# endif
#endif
#ifndef Q_IS_ENUM
# include <QtCore/qtypetraits.h>
# define Q_IS_ENUM(x) QtPrivate::is_enum<x>::value
#endif
#endif // QISENUM_H

View File

@ -342,7 +342,6 @@ public:
WA_UpdatesDisabled = 10,
WA_Mapped = 11,
WA_MacNoClickThrough = 12, // Mac only
WA_PaintOutsidePaintEvent = 13,
WA_InputMethodEnabled = 14,
WA_WState_Visible = 15,
WA_WState_Hidden = 16,
@ -1101,8 +1100,7 @@ public:
enum TextFormat {
PlainText,
RichText,
AutoText,
LogText
AutoText
};
enum AspectRatioMode {
@ -1111,12 +1109,6 @@ public:
KeepAspectRatioByExpanding
};
// This is for Q3TextEdit only, actually.
enum AnchorAttribute {
AnchorName,
AnchorHref
};
enum DockWidgetArea {
LeftDockWidgetArea = 0x1,
RightDockWidgetArea = 0x2,
@ -1200,7 +1192,6 @@ public:
AutoConnection,
DirectConnection,
QueuedConnection,
AutoCompatConnection,
BlockingQueuedConnection,
UniqueConnection = 0x80
};

View File

@ -537,13 +537,6 @@
same pair of objects, then the connection will fail. This
connection type was introduced in Qt 4.6.
\value AutoCompatConnection
The default type when Qt 3 support is enabled. Same as
AutoConnection but will also cause warnings to be output in
certain situations. See \l{Porting to Qt 4#Compatibility
Signals and Slots}{Compatibility Signals and Slots} for
further information.
With queued connections, the parameters must be of types that are
known to Qt's meta-object system, because Qt needs to copy the
arguments to store them in an event behind the scenes. If you try
@ -1000,11 +993,6 @@
require native painting primitives, you need to reimplement
QWidget::paintEngine() to return 0 and set this flag.
\value WA_PaintOutsidePaintEvent Makes it possible to use QPainter to
paint on the widget outside \l{QWidget::paintEvent()}{paintEvent()}. This
flag is not supported on Windows, Mac OS X or Embedded Linux. We recommend
that you use it only when porting Qt 3 code to Qt 4.
\value WA_PaintUnclipped Makes all painters operating on this widget
unclipped. Children of this widget or other widgets in front of it do not
clip the area the painter can paint on. This flag is only supported for
@ -2309,9 +2297,6 @@
\value AutoText The text string is interpreted as for
Qt::RichText if Qt::mightBeRichText() returns true, otherwise
as Qt::PlainText.
\value LogText A special, limited text format which is only used
by Q3TextEdit in an optimized mode.
*/
/*!

View File

@ -100,7 +100,7 @@ static inline double qt_inf()
: qt_le_inf_bytes);
union { unsigned char c[8]; double d; } returnValue;
qMemCopy(returnValue.c, bytes, sizeof(returnValue.c));
memcpy(returnValue.c, bytes, sizeof(returnValue.c));
return returnValue.d;
}
@ -115,7 +115,7 @@ static inline double qt_snan()
: qt_le_snan_bytes);
union { unsigned char c[8]; double d; } returnValue;
qMemCopy(returnValue.c, bytes, sizeof(returnValue.c));
memcpy(returnValue.c, bytes, sizeof(returnValue.c));
return returnValue.d;
}
@ -130,7 +130,7 @@ static inline double qt_qnan()
: qt_le_qnan_bytes);
union { unsigned char c[8]; double d; } returnValue;
qMemCopy(returnValue.c, bytes, sizeof(returnValue.c));
memcpy(returnValue.c, bytes, sizeof(returnValue.c));
return returnValue.d;
}

View File

@ -49,6 +49,12 @@
#if defined __cplusplus
// for rand_s, _CRT_RAND_S must be #defined before #including stdlib.h.
// put it at the beginning so some indirect inclusion doesn't break it
#ifndef _CRT_RAND_S
#define _CRT_RAND_S
#endif
#include <stdlib.h>
#include <qglobal.h>
#ifdef Q_OS_WIN
# define _POSIX_
@ -63,5 +69,4 @@
#include <qstring.h>
#include <qstringlist.h>
#include <qtextcodec.h>
#include <stdlib.h>
#endif

View File

@ -172,9 +172,6 @@ Q_DECLARE_TYPEINFO_BODY(QFlags<T>, Q_PRIMITIVE_TYPE);
types must declare a 'bool isDetached(void) const;' member for this
to work.
*/
#ifdef QT_NO_STL
#define Q_DECLARE_SHARED_STL(TYPE)
#else
#define Q_DECLARE_SHARED_STL(TYPE) \
QT_END_NAMESPACE \
namespace std { \
@ -182,7 +179,6 @@ namespace std { \
{ swap(value1.data_ptr(), value2.data_ptr()); } \
} \
QT_BEGIN_NAMESPACE
#endif
#define Q_DECLARE_SHARED(TYPE) \
template <> inline void qSwap<TYPE>(TYPE &value1, TYPE &value2) \

View File

@ -11,8 +11,11 @@ HEADERS += \
io/qdir_p.h \
io/qdiriterator.h \
io/qfile.h \
io/qfiledevice.h \
io/qfiledevice_p.h \
io/qfileinfo.h \
io/qfileinfo_p.h \
io/qipaddress_p.h \
io/qiodevice.h \
io/qiodevice_p.h \
io/qnoncontiguousbytedevice_p.h \
@ -25,6 +28,8 @@ HEADERS += \
io/qresource_iterator_p.h \
io/qstandardpaths.h \
io/qurl.h \
io/qurl_p.h \
io/qurlquery.h \
io/qurltlds_p.h \
io/qtldurl_p.h \
io/qsettings.h \
@ -49,7 +54,9 @@ SOURCES += \
io/qdir.cpp \
io/qdiriterator.cpp \
io/qfile.cpp \
io/qfiledevice.cpp \
io/qfileinfo.cpp \
io/qipaddress.cpp \
io/qiodevice.cpp \
io/qnoncontiguousbytedevice.cpp \
io/qprocess.cpp \
@ -60,6 +67,9 @@ SOURCES += \
io/qresource_iterator.cpp \
io/qstandardpaths.cpp \
io/qurl.cpp \
io/qurlidna.cpp \
io/qurlquery.cpp \
io/qurlrecode.cpp \
io/qsettings.cpp \
io/qfsfileengine.cpp \
io/qfsfileengine_iterator.cpp \

View File

@ -114,7 +114,7 @@ public:
explicit QDataStream(QIODevice *);
QDataStream(QByteArray *, QIODevice::OpenMode flags);
QDataStream(const QByteArray &);
virtual ~QDataStream();
~QDataStream();
QIODevice *device() const;
void setDevice(QIODevice *);
@ -385,7 +385,6 @@ Q_OUTOFLINE_TEMPLATE QDataStream &operator>>(QDataStream &in, QMap<aKey, aT> &ma
in >> n;
map.detach();
map.setInsertInOrder(true);
for (quint32 i = 0; i < n; ++i) {
if (in.status() != QDataStream::Ok)
break;
@ -395,7 +394,6 @@ Q_OUTOFLINE_TEMPLATE QDataStream &operator>>(QDataStream &in, QMap<aKey, aT> &ma
in >> key >> value;
map.insertMulti(key, value);
}
map.setInsertInOrder(false);
if (in.status() != QDataStream::Ok)
map.clear();
if (oldStatus != QDataStream::Ok)

View File

@ -61,11 +61,8 @@ Q_CORE_EXPORT bool qDecodeDataUrl(const QUrl &uri, QString &mimeType, QByteArray
// the following would have been the correct thing, but
// reality often differs from the specification. People have
// data: URIs with ? and #
//QByteArray data = QByteArray::fromPercentEncoding(uri.encodedPath());
QByteArray data = QByteArray::fromPercentEncoding(uri.toEncoded());
// remove the data: scheme
data.remove(0, 5);
//QByteArray data = QByteArray::fromPercentEncoding(uri.path(QUrl::PrettyDecoded).toLatin1());
QByteArray data = QByteArray::fromPercentEncoding(uri.url(QUrl::PrettyDecoded | QUrl::RemoveScheme).toLatin1());
// parse it:
int pos = data.indexOf(',');

View File

@ -52,6 +52,7 @@ QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class QDirIterator;
class QDirPrivate;
class Q_CORE_EXPORT QDir
@ -210,6 +211,7 @@ protected:
QSharedDataPointer<QDirPrivate> d_ptr;
private:
friend class QDirIterator;
// Q_DECLARE_PRIVATE equivalent for shared data pointers
QDirPrivate* d_func();
inline const QDirPrivate* d_func() const

View File

@ -410,9 +410,7 @@ bool QDirIteratorPrivate::matchesFilters(const QString &fileName, const QFileInf
*/
QDirIterator::QDirIterator(const QDir &dir, IteratorFlags flags)
{
// little trick to get hold of the QDirPrivate while there is no API on QDir to give it to us
class MyQDir : public QDir { public: const QDirPrivate *priv() const { return d_ptr.constData(); } };
const QDirPrivate *other = static_cast<const MyQDir*>(&dir)->priv();
const QDirPrivate *other = dir.d_ptr.constData();
d.reset(new QDirIteratorPrivate(other->dirEntry, other->nameFilters, other->filters, flags, !other->fileEngine.isNull()));
}

View File

@ -70,7 +70,7 @@ public:
QDir::Filters filters = QDir::NoFilter,
IteratorFlags flags = NoIteratorFlags);
virtual ~QDirIterator();
~QDirIterator();
QString next();
bool hasNext() const;

View File

@ -59,8 +59,6 @@
QT_BEGIN_NAMESPACE
static const int QFILE_WRITEBUFFER_SIZE = 16384;
static QByteArray locale_encode(const QString &f)
{
#if defined(Q_OS_DARWIN)
@ -86,16 +84,11 @@ QFile::EncoderFn QFilePrivate::encoder = locale_encode;
QFile::DecoderFn QFilePrivate::decoder = locale_decode;
QFilePrivate::QFilePrivate()
: fileEngine(0), lastWasWrite(false),
writeBuffer(QFILE_WRITEBUFFER_SIZE), error(QFile::NoError),
cachedSize(0)
{
}
QFilePrivate::~QFilePrivate()
{
delete fileEngine;
fileEngine = 0;
}
bool
@ -137,39 +130,6 @@ QAbstractFileEngine *QFilePrivate::engine() const
return fileEngine;
}
inline bool QFilePrivate::ensureFlushed() const
{
// This function ensures that the write buffer has been flushed (const
// because certain const functions need to call it.
if (lastWasWrite) {
const_cast<QFilePrivate *>(this)->lastWasWrite = false;
if (!const_cast<QFile *>(q_func())->flush())
return false;
}
return true;
}
void
QFilePrivate::setError(QFile::FileError err)
{
error = err;
errorString.clear();
}
void
QFilePrivate::setError(QFile::FileError err, const QString &errStr)
{
error = err;
errorString = errStr;
}
void
QFilePrivate::setError(QFile::FileError err, int errNum)
{
error = err;
errorString = qt_error_string(errNum);
}
//************* QFile
/*!
@ -278,98 +238,18 @@ QFilePrivate::setError(QFile::FileError err, int errNum)
\sa QTextStream, QDataStream, QFileInfo, QDir, {The Qt Resource System}
*/
/*!
\enum QFile::FileError
This enum describes the errors that may be returned by the error()
function.
\value NoError No error occurred.
\value ReadError An error occurred when reading from the file.
\value WriteError An error occurred when writing to the file.
\value FatalError A fatal error occurred.
\value ResourceError
\value OpenError The file could not be opened.
\value AbortError The operation was aborted.
\value TimeOutError A timeout occurred.
\value UnspecifiedError An unspecified error occurred.
\value RemoveError The file could not be removed.
\value RenameError The file could not be renamed.
\value PositionError The position in the file could not be changed.
\value ResizeError The file could not be resized.
\value PermissionsError The file could not be accessed.
\value CopyError The file could not be copied.
\omitvalue ConnectError
*/
/*!
\enum QFile::Permission
This enum is used by the permission() function to report the
permissions and ownership of a file. The values may be OR-ed
together to test multiple permissions and ownership values.
\value ReadOwner The file is readable by the owner of the file.
\value WriteOwner The file is writable by the owner of the file.
\value ExeOwner The file is executable by the owner of the file.
\value ReadUser The file is readable by the user.
\value WriteUser The file is writable by the user.
\value ExeUser The file is executable by the user.
\value ReadGroup The file is readable by the group.
\value WriteGroup The file is writable by the group.
\value ExeGroup The file is executable by the group.
\value ReadOther The file is readable by anyone.
\value WriteOther The file is writable by anyone.
\value ExeOther The file is executable by anyone.
\warning Because of differences in the platforms supported by Qt,
the semantics of ReadUser, WriteUser and ExeUser are
platform-dependent: On Unix, the rights of the owner of the file
are returned and on Windows the rights of the current user are
returned. This behavior might change in a future Qt version.
Note that Qt does not by default check for permissions on NTFS
file systems, as this may decrease the performance of file
handling considerably. It is possible to force permission checking
on NTFS by including the following code in your source:
\snippet doc/src/snippets/ntfsp.cpp 0
Permission checking is then turned on and off by incrementing and
decrementing \c qt_ntfs_permission_lookup by 1.
\snippet doc/src/snippets/ntfsp.cpp 1
*/
/*!
\enum QFile::FileHandleFlag
This enum is used when opening a file to specify additional
options which only apply to files and not to a generic
QIODevice.
\value AutoCloseHandle The file handle passed into open() should be
closed by close(), the default behavior is that close just flushes
the file and the application is responsible for closing the file handle.
When opening a file by name, this flag is ignored as Qt always owns the
file handle and must close it.
\value DontCloseHandle If not explicitly closed, the underlying file
handle is left open when the QFile object is destroyed.
*/
#ifdef QT_NO_QOBJECT
QFile::QFile()
: QIODevice(*new QFilePrivate)
: QFileDevice(*new QFilePrivate)
{
}
QFile::QFile(const QString &name)
: QIODevice(*new QFilePrivate)
: QFileDevice(*new QFilePrivate)
{
d_func()->fileName = name;
}
QFile::QFile(QFilePrivate &dd)
: QIODevice(dd)
: QFileDevice(dd)
{
}
#else
@ -377,21 +257,21 @@ QFile::QFile(QFilePrivate &dd)
\internal
*/
QFile::QFile()
: QIODevice(*new QFilePrivate, 0)
: QFileDevice(*new QFilePrivate, 0)
{
}
/*!
Constructs a new file object with the given \a parent.
*/
QFile::QFile(QObject *parent)
: QIODevice(*new QFilePrivate, parent)
: QFileDevice(*new QFilePrivate, parent)
{
}
/*!
Constructs a new file object to represent the file with the given \a name.
*/
QFile::QFile(const QString &name)
: QIODevice(*new QFilePrivate, 0)
: QFileDevice(*new QFilePrivate, 0)
{
Q_D(QFile);
d->fileName = name;
@ -401,7 +281,7 @@ QFile::QFile(const QString &name)
file with the specified \a name.
*/
QFile::QFile(const QString &name, QObject *parent)
: QIODevice(*new QFilePrivate, parent)
: QFileDevice(*new QFilePrivate, parent)
{
Q_D(QFile);
d->fileName = name;
@ -410,7 +290,7 @@ QFile::QFile(const QString &name, QObject *parent)
\internal
*/
QFile::QFile(QFilePrivate &dd, QObject *parent)
: QIODevice(dd, parent)
: QFileDevice(dd, parent)
{
}
#endif
@ -420,7 +300,6 @@ QFile::QFile(QFilePrivate &dd, QObject *parent)
*/
QFile::~QFile()
{
close();
}
/*!
@ -966,20 +845,6 @@ QFile::copy(const QString &fileName, const QString &newName)
return QFile(fileName).copy(newName);
}
/*!
Returns true if the file can only be manipulated sequentially;
otherwise returns false.
Most files support random-access, but some special files may not.
\sa QIODevice::isSequential()
*/
bool QFile::isSequential() const
{
Q_D(const QFile);
return d->fileEngine && d->fileEngine->isSequential();
}
/*!
Opens the file using OpenMode \a mode, returning true if successful;
otherwise false.
@ -1154,119 +1019,11 @@ bool QFile::open(int fd, OpenMode mode, FileHandleFlags handleFlags)
}
/*!
Returns the file handle of the file.
This is a small positive integer, suitable for use with C library
functions such as fdopen() and fcntl(). On systems that use file
descriptors for sockets (i.e. Unix systems, but not Windows) the handle
can be used with QSocketNotifier as well.
If the file is not open, or there is an error, handle() returns -1.
This function is not supported on Windows CE.
\sa QSocketNotifier
\reimp
*/
int
QFile::handle() const
bool QFile::resize(qint64 sz)
{
Q_D(const QFile);
if (!isOpen() || !d->fileEngine)
return -1;
return d->fileEngine->handle();
}
/*!
\enum QFile::MemoryMapFlags
\since 4.4
This enum describes special options that may be used by the map()
function.
\value NoOptions No options.
*/
/*!
\since 4.4
Maps \a size bytes of the file into memory starting at \a offset. A file
should be open for a map to succeed but the file does not need to stay
open after the memory has been mapped. When the QFile is destroyed
or a new file is opened with this object, any maps that have not been
unmapped will automatically be unmapped.
Any mapping options can be passed through \a flags.
Returns a pointer to the memory or 0 if there is an error.
\note On Windows CE 5.0 the file will be closed before mapping occurs.
\sa unmap()
*/
uchar *QFile::map(qint64 offset, qint64 size, MemoryMapFlags flags)
{
Q_D(QFile);
if (d->engine()
&& d->fileEngine->supportsExtension(QAbstractFileEngine::MapExtension)) {
unsetError();
uchar *address = d->fileEngine->map(offset, size, flags);
if (address == 0)
d->setError(d->fileEngine->error(), d->fileEngine->errorString());
return address;
}
return 0;
}
/*!
\since 4.4
Unmaps the memory \a address.
Returns true if the unmap succeeds; false otherwise.
\sa map()
*/
bool QFile::unmap(uchar *address)
{
Q_D(QFile);
if (d->engine()
&& d->fileEngine->supportsExtension(QAbstractFileEngine::UnMapExtension)) {
unsetError();
bool success = d->fileEngine->unmap(address);
if (!success)
d->setError(d->fileEngine->error(), d->fileEngine->errorString());
return success;
}
d->setError(PermissionsError, tr("No file engine available or engine does not support UnMapExtension"));
return false;
}
/*!
Sets the file size (in bytes) \a sz. Returns true if the file if the
resize succeeds; false otherwise. If \a sz is larger than the file
currently is the new bytes will be set to 0, if \a sz is smaller the
file is simply truncated.
\sa size(), setFileName()
*/
bool
QFile::resize(qint64 sz)
{
Q_D(QFile);
if (!d->ensureFlushed())
return false;
d->engine();
if (isOpen() && d->fileEngine->pos() > sz)
seek(sz);
if(d->fileEngine->setSize(sz)) {
unsetError();
d->cachedSize = sz;
return true;
}
d->cachedSize = 0;
d->setError(QFile::ResizeError, d->fileEngine->errorString());
return false;
return QFileDevice::resize(sz); // for now
}
/*!
@ -1287,18 +1044,11 @@ QFile::resize(const QString &fileName, qint64 sz)
}
/*!
Returns the complete OR-ed together combination of
QFile::Permission for the file.
\sa setPermissions(), setFileName()
\reimp
*/
QFile::Permissions
QFile::permissions() const
QFile::Permissions QFile::permissions() const
{
Q_D(const QFile);
QAbstractFileEngine::FileFlags perms = d->engine()->fileFlags(QAbstractFileEngine::PermsMask) & QAbstractFileEngine::PermsMask;
return QFile::Permissions((int)perms); //ewww
return QFileDevice::permissions(); // for now
}
/*!
@ -1322,16 +1072,9 @@ QFile::permissions(const QString &fileName)
\sa permissions(), setFileName()
*/
bool
QFile::setPermissions(Permissions permissions)
bool QFile::setPermissions(Permissions permissions)
{
Q_D(QFile);
if (d->engine()->setPermissions(permissions)) {
unsetError();
return true;
}
d->setError(QFile::PermissionsError, d->fileEngine->errorString());
return false;
return QFileDevice::setPermissions(permissions); // for now
}
/*!
@ -1346,354 +1089,12 @@ QFile::setPermissions(const QString &fileName, Permissions permissions)
return QFile(fileName).setPermissions(permissions);
}
static inline qint64 _qfile_writeData(QAbstractFileEngine *engine, QRingBuffer *buffer)
{
qint64 ret = engine->write(buffer->readPointer(), buffer->nextDataBlockSize());
if (ret > 0)
buffer->free(ret);
return ret;
}
/*!
Flushes any buffered data to the file. Returns true if successful;
otherwise returns false.
\reimp
*/
bool
QFile::flush()
{
Q_D(QFile);
if (!d->fileEngine) {
qWarning("QFile::flush: No file engine. Is IODevice open?");
return false;
}
if (!d->writeBuffer.isEmpty()) {
qint64 size = d->writeBuffer.size();
if (_qfile_writeData(d->fileEngine, &d->writeBuffer) != size) {
QFile::FileError err = d->fileEngine->error();
if(err == QFile::UnspecifiedError)
err = QFile::WriteError;
d->setError(err, d->fileEngine->errorString());
return false;
}
}
if (!d->fileEngine->flush()) {
QFile::FileError err = d->fileEngine->error();
if(err == QFile::UnspecifiedError)
err = QFile::WriteError;
d->setError(err, d->fileEngine->errorString());
return false;
}
return true;
}
/*!
Calls QFile::flush() and closes the file. Errors from flush are ignored.
\sa QIODevice::close()
*/
void
QFile::close()
{
Q_D(QFile);
if(!isOpen())
return;
bool flushed = flush();
QIODevice::close();
// reset write buffer
d->lastWasWrite = false;
d->writeBuffer.clear();
// keep earlier error from flush
if (d->fileEngine->close() && flushed)
unsetError();
else if (flushed)
d->setError(d->fileEngine->error(), d->fileEngine->errorString());
}
/*!
Returns the size of the file.
For regular empty files on Unix (e.g. those in \c /proc), this function
returns 0; the contents of such a file are generated on demand in response
to you calling read().
*/
qint64 QFile::size() const
{
Q_D(const QFile);
if (!d->ensureFlushed())
return 0;
d->cachedSize = d->engine()->size();
return d->cachedSize;
}
/*!
\reimp
*/
qint64 QFile::pos() const
{
return QIODevice::pos();
}
/*!
Returns true if the end of the file has been reached; otherwise returns
false.
For regular empty files on Unix (e.g. those in \c /proc), this function
returns true, since the file system reports that the size of such a file is
0. Therefore, you should not depend on atEnd() when reading data from such a
file, but rather call read() until no more data can be read.
*/
bool QFile::atEnd() const
{
Q_D(const QFile);
// If there's buffered data left, we're not at the end.
if (!d->buffer.isEmpty())
return false;
if (!isOpen())
return true;
if (!d->ensureFlushed())
return false;
// If the file engine knows best, say what it says.
if (d->fileEngine->supportsExtension(QAbstractFileEngine::AtEndExtension)) {
// Check if the file engine supports AtEndExtension, and if it does,
// check if the file engine claims to be at the end.
return d->fileEngine->atEnd();
}
// if it looks like we are at the end, or if size is not cached,
// fall through to bytesAvailable() to make sure.
if (pos() < d->cachedSize)
return false;
// Fall back to checking how much is available (will stat files).
return bytesAvailable() == 0;
}
/*!
\fn bool QFile::seek(qint64 pos)
For random-access devices, this function sets the current position
to \a pos, returning true on success, or false if an error occurred.
For sequential devices, the default behavior is to do nothing and
return false.
Seeking beyond the end of a file:
If the position is beyond the end of a file, then seek() shall not
immediately extend the file. If a write is performed at this position,
then the file shall be extended. The content of the file between the
previous end of file and the newly written data is UNDEFINED and
varies between platforms and file systems.
*/
bool QFile::seek(qint64 off)
{
Q_D(QFile);
if (!isOpen()) {
qWarning("QFile::seek: IODevice is not open");
return false;
}
if (!d->ensureFlushed())
return false;
if (!d->fileEngine->seek(off) || !QIODevice::seek(off)) {
QFile::FileError err = d->fileEngine->error();
if(err == QFile::UnspecifiedError)
err = QFile::PositionError;
d->setError(err, d->fileEngine->errorString());
return false;
}
unsetError();
return true;
}
/*!
\reimp
*/
qint64 QFile::readLineData(char *data, qint64 maxlen)
{
Q_D(QFile);
if (!d->ensureFlushed())
return -1;
qint64 read;
if (d->fileEngine->supportsExtension(QAbstractFileEngine::FastReadLineExtension)) {
read = d->fileEngine->readLine(data, maxlen);
} else {
// Fall back to QIODevice's readLine implementation if the engine
// cannot do it faster.
read = QIODevice::readLineData(data, maxlen);
}
if (read < maxlen) {
// failed to read all requested, may be at the end of file, stop caching size so that it's rechecked
d->cachedSize = 0;
}
return read;
}
/*!
\reimp
*/
qint64 QFile::readData(char *data, qint64 len)
{
Q_D(QFile);
unsetError();
if (!d->ensureFlushed())
return -1;
qint64 read = d->fileEngine->read(data, len);
if(read < 0) {
QFile::FileError err = d->fileEngine->error();
if(err == QFile::UnspecifiedError)
err = QFile::ReadError;
d->setError(err, d->fileEngine->errorString());
}
if (read < len) {
// failed to read all requested, may be at the end of file, stop caching size so that it's rechecked
d->cachedSize = 0;
}
return read;
}
/*!
\internal
*/
bool QFilePrivate::putCharHelper(char c)
{
#ifdef QT_NO_QOBJECT
return QIODevicePrivate::putCharHelper(c);
#else
// Cutoff for code that doesn't only touch the buffer.
int writeBufferSize = writeBuffer.size();
if ((openMode & QIODevice::Unbuffered) || writeBufferSize + 1 >= QFILE_WRITEBUFFER_SIZE
#ifdef Q_OS_WIN
|| ((openMode & QIODevice::Text) && c == '\n' && writeBufferSize + 2 >= QFILE_WRITEBUFFER_SIZE)
#endif
) {
return QIODevicePrivate::putCharHelper(c);
}
if (!(openMode & QIODevice::WriteOnly)) {
if (openMode == QIODevice::NotOpen)
qWarning("QIODevice::putChar: Closed device");
else
qWarning("QIODevice::putChar: ReadOnly device");
return false;
}
// Make sure the device is positioned correctly.
const bool sequential = isSequential();
if (pos != devicePos && !sequential && !q_func()->seek(pos))
return false;
lastWasWrite = true;
int len = 1;
#ifdef Q_OS_WIN
if ((openMode & QIODevice::Text) && c == '\n') {
++len;
*writeBuffer.reserve(1) = '\r';
}
#endif
// Write to buffer.
*writeBuffer.reserve(1) = c;
if (!sequential) {
pos += len;
devicePos += len;
if (!buffer.isEmpty())
buffer.skip(len);
}
return true;
#endif
}
/*!
\reimp
*/
qint64
QFile::writeData(const char *data, qint64 len)
{
Q_D(QFile);
unsetError();
d->lastWasWrite = true;
bool buffered = !(d->openMode & Unbuffered);
// Flush buffered data if this read will overflow.
if (buffered && (d->writeBuffer.size() + len) > QFILE_WRITEBUFFER_SIZE) {
if (!flush())
return -1;
}
// Write directly to the engine if the block size is larger than
// the write buffer size.
if (!buffered || len > QFILE_WRITEBUFFER_SIZE) {
qint64 ret = d->fileEngine->write(data, len);
if(ret < 0) {
QFile::FileError err = d->fileEngine->error();
if(err == QFile::UnspecifiedError)
err = QFile::WriteError;
d->setError(err, d->fileEngine->errorString());
}
return ret;
}
// Write to the buffer.
char *writePointer = d->writeBuffer.reserve(len);
if (len == 1)
*writePointer = *data;
else
::memcpy(writePointer, data, len);
return len;
}
/*!
Returns the file error status.
The I/O device status returns an error code. For example, if open()
returns false, or a read/write operation returns -1, this function can
be called to find out the reason why the operation failed.
\sa unsetError()
*/
QFile::FileError
QFile::error() const
{
Q_D(const QFile);
return d->error;
}
/*!
Sets the file's error to QFile::NoError.
\sa error()
*/
void
QFile::unsetError()
{
Q_D(QFile);
d->setError(QFile::NoError);
return QFileDevice::size(); // for now
}
QT_END_NAMESPACE

View File

@ -42,7 +42,7 @@
#ifndef QFILE_H
#define QFILE_H
#include <QtCore/qiodevice.h>
#include <QtCore/qfiledevice.h>
#include <QtCore/qstring.h>
#include <stdio.h>
@ -57,7 +57,7 @@ QT_BEGIN_NAMESPACE
class QTemporaryFile;
class QFilePrivate;
class Q_CORE_EXPORT QFile : public QIODevice
class Q_CORE_EXPORT QFile : public QFileDevice
{
#ifndef QT_NO_QOBJECT
Q_OBJECT
@ -65,39 +65,6 @@ class Q_CORE_EXPORT QFile : public QIODevice
Q_DECLARE_PRIVATE(QFile)
public:
enum FileError {
NoError = 0,
ReadError = 1,
WriteError = 2,
FatalError = 3,
ResourceError = 4,
OpenError = 5,
AbortError = 6,
TimeOutError = 7,
UnspecifiedError = 8,
RemoveError = 9,
RenameError = 10,
PositionError = 11,
ResizeError = 12,
PermissionsError = 13,
CopyError = 14
};
enum Permission {
ReadOwner = 0x4000, WriteOwner = 0x2000, ExeOwner = 0x1000,
ReadUser = 0x0400, WriteUser = 0x0200, ExeUser = 0x0100,
ReadGroup = 0x0040, WriteGroup = 0x0020, ExeGroup = 0x0010,
ReadOther = 0x0004, WriteOther = 0x0002, ExeOther = 0x0001
};
Q_DECLARE_FLAGS(Permissions, Permission)
enum FileHandleFlag {
AutoCloseHandle = 0x0001,
DontCloseHandle = 0
};
Q_DECLARE_FLAGS(FileHandleFlags, FileHandleFlag)
QFile();
QFile(const QString &name);
#ifndef QT_NO_QOBJECT
@ -106,9 +73,6 @@ public:
#endif
~QFile();
FileError error() const;
void unsetError();
QString fileName() const;
void setFileName(const QString &name);
@ -141,18 +105,11 @@ public:
bool copy(const QString &newName);
static bool copy(const QString &fileName, const QString &newName);
bool isSequential() const;
bool open(OpenMode flags);
bool open(FILE *f, OpenMode ioFlags, FileHandleFlags handleFlags=DontCloseHandle);
bool open(int fd, OpenMode ioFlags, FileHandleFlags handleFlags=DontCloseHandle);
virtual void close();
qint64 size() const;
qint64 pos() const;
bool seek(qint64 offset);
bool atEnd() const;
bool flush();
bool resize(qint64 sz);
static bool resize(const QString &filename, qint64 sz);
@ -162,15 +119,6 @@ public:
bool setPermissions(Permissions permissionSpec);
static bool setPermissions(const QString &filename, Permissions permissionSpec);
int handle() const;
enum MemoryMapFlags {
NoOptions = 0
};
uchar *map(qint64 offset, qint64 size, MemoryMapFlags flags = NoOptions);
bool unmap(uchar *address);
protected:
#ifdef QT_NO_QOBJECT
QFile(QFilePrivate &dd);
@ -178,17 +126,11 @@ protected:
QFile(QFilePrivate &dd, QObject *parent = 0);
#endif
qint64 readData(char *data, qint64 maxlen);
qint64 writeData(const char *data, qint64 len);
qint64 readLineData(char *data, qint64 maxlen);
private:
friend class QTemporaryFile;
Q_DISABLE_COPY(QFile)
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QFile::Permissions)
QT_END_NAMESPACE
QT_END_HEADER

View File

@ -53,15 +53,13 @@
// We mean it.
//
#include "private/qabstractfileengine_p.h"
#include "private/qiodevice_p.h"
#include "private/qringbuffer_p.h"
#include "private/qfiledevice_p.h"
QT_BEGIN_NAMESPACE
class QTemporaryFile;
class QFilePrivate : public QIODevicePrivate
class QFilePrivate : public QFileDevicePrivate
{
Q_DECLARE_PUBLIC(QFile)
friend class QTemporaryFile;
@ -76,20 +74,6 @@ protected:
virtual QAbstractFileEngine *engine() const;
QString fileName;
mutable QAbstractFileEngine *fileEngine;
bool lastWasWrite;
QRingBuffer writeBuffer;
inline bool ensureFlushed() const;
bool putCharHelper(char c);
QFile::FileError error;
void setError(QFile::FileError err);
void setError(QFile::FileError err, const QString &errorString);
void setError(QFile::FileError err, int errNum);
mutable qint64 cachedSize;
private:
static QFile::EncoderFn encoder;

View File

@ -0,0 +1,736 @@
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** 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.
**
** 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.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qplatformdefs.h"
#include "qfiledevice.h"
#include "qfiledevice_p.h"
#include "qfsfileengine_p.h"
#ifdef QT_NO_QOBJECT
#define tr(X) QString::fromLatin1(X)
#endif
QT_BEGIN_NAMESPACE
static const int QFILE_WRITEBUFFER_SIZE = 16384;
QFileDevicePrivate::QFileDevicePrivate()
: fileEngine(0), lastWasWrite(false),
writeBuffer(QFILE_WRITEBUFFER_SIZE), error(QFile::NoError),
cachedSize(0)
{
}
QFileDevicePrivate::~QFileDevicePrivate()
{
delete fileEngine;
fileEngine = 0;
}
QAbstractFileEngine * QFileDevicePrivate::engine() const
{
if (!fileEngine)
fileEngine = new QFSFileEngine;
return fileEngine;
}
void QFileDevicePrivate::setError(QFileDevice::FileError err)
{
error = err;
errorString.clear();
}
void QFileDevicePrivate::setError(QFileDevice::FileError err, const QString &errStr)
{
error = err;
errorString = errStr;
}
void QFileDevicePrivate::setError(QFileDevice::FileError err, int errNum)
{
error = err;
errorString = qt_error_string(errNum);
}
/*!
\enum QFileDevice::FileError
This enum describes the errors that may be returned by the error()
function.
\value NoError No error occurred.
\value ReadError An error occurred when reading from the file.
\value WriteError An error occurred when writing to the file.
\value FatalError A fatal error occurred.
\value ResourceError
\value OpenError The file could not be opened.
\value AbortError The operation was aborted.
\value TimeOutError A timeout occurred.
\value UnspecifiedError An unspecified error occurred.
\value RemoveError The file could not be removed.
\value RenameError The file could not be renamed.
\value PositionError The position in the file could not be changed.
\value ResizeError The file could not be resized.
\value PermissionsError The file could not be accessed.
\value CopyError The file could not be copied.
\omitvalue ConnectError
*/
/*!
\enum QFileDevice::Permission
This enum is used by the permission() function to report the
permissions and ownership of a file. The values may be OR-ed
together to test multiple permissions and ownership values.
\value ReadOwner The file is readable by the owner of the file.
\value WriteOwner The file is writable by the owner of the file.
\value ExeOwner The file is executable by the owner of the file.
\value ReadUser The file is readable by the user.
\value WriteUser The file is writable by the user.
\value ExeUser The file is executable by the user.
\value ReadGroup The file is readable by the group.
\value WriteGroup The file is writable by the group.
\value ExeGroup The file is executable by the group.
\value ReadOther The file is readable by anyone.
\value WriteOther The file is writable by anyone.
\value ExeOther The file is executable by anyone.
\warning Because of differences in the platforms supported by Qt,
the semantics of ReadUser, WriteUser and ExeUser are
platform-dependent: On Unix, the rights of the owner of the file
are returned and on Windows the rights of the current user are
returned. This behavior might change in a future Qt version.
Note that Qt does not by default check for permissions on NTFS
file systems, as this may decrease the performance of file
handling considerably. It is possible to force permission checking
on NTFS by including the following code in your source:
\snippet doc/src/snippets/ntfsp.cpp 0
Permission checking is then turned on and off by incrementing and
decrementing \c qt_ntfs_permission_lookup by 1.
\snippet doc/src/snippets/ntfsp.cpp 1
*/
//************* QFileDevice
/*!
\class QFileDevice
\since 5.0
\brief The QFileDevice class provides an interface for reading from and writing to open files.
\ingroup io
\reentrant
QFileDevice is the base class for I/O devices that can read and write text and binary files
and \l{The Qt Resource System}{resources}. QFile offers the main functionality,
QFileDevice serves as a base class for sharing functionality with other file devices such
as QTemporaryFile, by providing all the operations that can be done on files that have
been opened by QFile or QTemporaryFile.
\sa QFile, QTemporaryFile
*/
/*!
\enum QFileDevice::FileHandleFlag
This enum is used when opening a file to specify additional
options which only apply to files and not to a generic
QIODevice.
\value AutoCloseHandle The file handle passed into open() should be
closed by close(), the default behavior is that close just flushes
the file and the application is responsible for closing the file handle.
When opening a file by name, this flag is ignored as Qt always owns the
file handle and must close it.
\value DontCloseHandle If not explicitly closed, the underlying file
handle is left open when the QFile object is destroyed.
*/
#ifdef QT_NO_QOBJECT
QFileDevice::QFileDevice()
: QIODevice(*new QFileDevicePrivate)
{
}
QFileDevice::QFileDevice(QFileDevicePrivate &dd)
: QIODevice(dd)
{
}
#else
/*!
\internal
*/
QFileDevice::QFileDevice()
: QIODevice(*new QFileDevicePrivate, 0)
{
}
/*!
\internal
*/
QFileDevice::QFileDevice(QObject *parent)
: QIODevice(*new QFileDevicePrivate, parent)
{
}
/*!
\internal
*/
QFileDevice::QFileDevice(QFileDevicePrivate &dd, QObject *parent)
: QIODevice(dd, parent)
{
}
#endif
/*!
Destroys the file device, closing it if necessary.
*/
QFileDevice::~QFileDevice()
{
close();
}
/*!
Returns true if the file can only be manipulated sequentially;
otherwise returns false.
Most files support random-access, but some special files may not.
\sa QIODevice::isSequential()
*/
bool QFileDevice::isSequential() const
{
Q_D(const QFileDevice);
return d->fileEngine && d->fileEngine->isSequential();
}
/*!
Returns the file handle of the file.
This is a small positive integer, suitable for use with C library
functions such as fdopen() and fcntl(). On systems that use file
descriptors for sockets (i.e. Unix systems, but not Windows) the handle
can be used with QSocketNotifier as well.
If the file is not open, or there is an error, handle() returns -1.
This function is not supported on Windows CE.
\sa QSocketNotifier
*/
int QFileDevice::handle() const
{
Q_D(const QFileDevice);
if (!isOpen() || !d->fileEngine)
return -1;
return d->fileEngine->handle();
}
/*!
Returns the name of the file.
The default implementation in QFileDevice returns QString().
*/
QString QFileDevice::fileName() const
{
return QString();
}
static inline qint64 _qfile_writeData(QAbstractFileEngine *engine, QRingBuffer *buffer)
{
qint64 ret = engine->write(buffer->readPointer(), buffer->nextDataBlockSize());
if (ret > 0)
buffer->free(ret);
return ret;
}
/*!
Flushes any buffered data to the file. Returns true if successful;
otherwise returns false.
*/
bool QFileDevice::flush()
{
Q_D(QFileDevice);
if (!d->fileEngine) {
qWarning("QFileDevice::flush: No file engine. Is IODevice open?");
return false;
}
if (!d->writeBuffer.isEmpty()) {
qint64 size = d->writeBuffer.size();
if (_qfile_writeData(d->fileEngine, &d->writeBuffer) != size) {
QFileDevice::FileError err = d->fileEngine->error();
if (err == QFileDevice::UnspecifiedError)
err = QFileDevice::WriteError;
d->setError(err, d->fileEngine->errorString());
return false;
}
}
if (!d->fileEngine->flush()) {
QFileDevice::FileError err = d->fileEngine->error();
if (err == QFileDevice::UnspecifiedError)
err = QFileDevice::WriteError;
d->setError(err, d->fileEngine->errorString());
return false;
}
return true;
}
/*!
Calls QFileDevice::flush() and closes the file. Errors from flush are ignored.
\sa QIODevice::close()
*/
void QFileDevice::close()
{
Q_D(QFileDevice);
if (!isOpen())
return;
bool flushed = flush();
QIODevice::close();
// reset write buffer
d->lastWasWrite = false;
d->writeBuffer.clear();
// keep earlier error from flush
if (d->fileEngine->close() && flushed)
unsetError();
else if (flushed)
d->setError(d->fileEngine->error(), d->fileEngine->errorString());
}
/*!
\reimp
*/
qint64 QFileDevice::pos() const
{
return QIODevice::pos();
}
/*!
Returns true if the end of the file has been reached; otherwise returns
false.
For regular empty files on Unix (e.g. those in \c /proc), this function
returns true, since the file system reports that the size of such a file is
0. Therefore, you should not depend on atEnd() when reading data from such a
file, but rather call read() until no more data can be read.
*/
bool QFileDevice::atEnd() const
{
Q_D(const QFileDevice);
// If there's buffered data left, we're not at the end.
if (!d->buffer.isEmpty())
return false;
if (!isOpen())
return true;
if (!d->ensureFlushed())
return false;
// If the file engine knows best, say what it says.
if (d->fileEngine->supportsExtension(QAbstractFileEngine::AtEndExtension)) {
// Check if the file engine supports AtEndExtension, and if it does,
// check if the file engine claims to be at the end.
return d->fileEngine->atEnd();
}
// if it looks like we are at the end, or if size is not cached,
// fall through to bytesAvailable() to make sure.
if (pos() < d->cachedSize)
return false;
// Fall back to checking how much is available (will stat files).
return bytesAvailable() == 0;
}
/*!
\fn bool QFileDevice::seek(qint64 pos)
For random-access devices, this function sets the current position
to \a pos, returning true on success, or false if an error occurred.
For sequential devices, the default behavior is to do nothing and
return false.
Seeking beyond the end of a file:
If the position is beyond the end of a file, then seek() shall not
immediately extend the file. If a write is performed at this position,
then the file shall be extended. The content of the file between the
previous end of file and the newly written data is UNDEFINED and
varies between platforms and file systems.
*/
bool QFileDevice::seek(qint64 off)
{
Q_D(QFileDevice);
if (!isOpen()) {
qWarning("QFileDevice::seek: IODevice is not open");
return false;
}
if (!d->ensureFlushed())
return false;
if (!d->fileEngine->seek(off) || !QIODevice::seek(off)) {
QFileDevice::FileError err = d->fileEngine->error();
if (err == QFileDevice::UnspecifiedError)
err = QFileDevice::PositionError;
d->setError(err, d->fileEngine->errorString());
return false;
}
unsetError();
return true;
}
/*!
\reimp
*/
qint64 QFileDevice::readLineData(char *data, qint64 maxlen)
{
Q_D(QFileDevice);
if (!d->ensureFlushed())
return -1;
qint64 read;
if (d->fileEngine->supportsExtension(QAbstractFileEngine::FastReadLineExtension)) {
read = d->fileEngine->readLine(data, maxlen);
} else {
// Fall back to QIODevice's readLine implementation if the engine
// cannot do it faster.
read = QIODevice::readLineData(data, maxlen);
}
if (read < maxlen) {
// failed to read all requested, may be at the end of file, stop caching size so that it's rechecked
d->cachedSize = 0;
}
return read;
}
/*!
\reimp
*/
qint64 QFileDevice::readData(char *data, qint64 len)
{
Q_D(QFileDevice);
unsetError();
if (!d->ensureFlushed())
return -1;
const qint64 read = d->fileEngine->read(data, len);
if (read < 0) {
QFileDevice::FileError err = d->fileEngine->error();
if (err == QFileDevice::UnspecifiedError)
err = QFileDevice::ReadError;
d->setError(err, d->fileEngine->errorString());
}
if (read < len) {
// failed to read all requested, may be at the end of file, stop caching size so that it's rechecked
d->cachedSize = 0;
}
return read;
}
/*!
\internal
*/
bool QFileDevicePrivate::putCharHelper(char c)
{
#ifdef QT_NO_QOBJECT
return QIODevicePrivate::putCharHelper(c);
#else
// Cutoff for code that doesn't only touch the buffer.
int writeBufferSize = writeBuffer.size();
if ((openMode & QIODevice::Unbuffered) || writeBufferSize + 1 >= QFILE_WRITEBUFFER_SIZE
#ifdef Q_OS_WIN
|| ((openMode & QIODevice::Text) && c == '\n' && writeBufferSize + 2 >= QFILE_WRITEBUFFER_SIZE)
#endif
) {
return QIODevicePrivate::putCharHelper(c);
}
if (!(openMode & QIODevice::WriteOnly)) {
if (openMode == QIODevice::NotOpen)
qWarning("QIODevice::putChar: Closed device");
else
qWarning("QIODevice::putChar: ReadOnly device");
return false;
}
// Make sure the device is positioned correctly.
const bool sequential = isSequential();
if (pos != devicePos && !sequential && !q_func()->seek(pos))
return false;
lastWasWrite = true;
int len = 1;
#ifdef Q_OS_WIN
if ((openMode & QIODevice::Text) && c == '\n') {
++len;
*writeBuffer.reserve(1) = '\r';
}
#endif
// Write to buffer.
*writeBuffer.reserve(1) = c;
if (!sequential) {
pos += len;
devicePos += len;
if (!buffer.isEmpty())
buffer.skip(len);
}
return true;
#endif
}
/*!
\reimp
*/
qint64 QFileDevice::writeData(const char *data, qint64 len)
{
Q_D(QFileDevice);
unsetError();
d->lastWasWrite = true;
bool buffered = !(d->openMode & Unbuffered);
// Flush buffered data if this read will overflow.
if (buffered && (d->writeBuffer.size() + len) > QFILE_WRITEBUFFER_SIZE) {
if (!flush())
return -1;
}
// Write directly to the engine if the block size is larger than
// the write buffer size.
if (!buffered || len > QFILE_WRITEBUFFER_SIZE) {
const qint64 ret = d->fileEngine->write(data, len);
if (ret < 0) {
QFileDevice::FileError err = d->fileEngine->error();
if (err == QFileDevice::UnspecifiedError)
err = QFileDevice::WriteError;
d->setError(err, d->fileEngine->errorString());
}
return ret;
}
// Write to the buffer.
char *writePointer = d->writeBuffer.reserve(len);
if (len == 1)
*writePointer = *data;
else
::memcpy(writePointer, data, len);
return len;
}
/*!
Returns the file error status.
The I/O device status returns an error code. For example, if open()
returns false, or a read/write operation returns -1, this function can
be called to find out the reason why the operation failed.
\sa unsetError()
*/
QFileDevice::FileError QFileDevice::error() const
{
Q_D(const QFileDevice);
return d->error;
}
/*!
Sets the file's error to QFileDevice::NoError.
\sa error()
*/
void QFileDevice::unsetError()
{
Q_D(QFileDevice);
d->setError(QFileDevice::NoError);
}
/*!
Returns the size of the file.
For regular empty files on Unix (e.g. those in \c /proc), this function
returns 0; the contents of such a file are generated on demand in response
to you calling read().
*/
qint64 QFileDevice::size() const
{
Q_D(const QFileDevice);
if (!d->ensureFlushed())
return 0;
d->cachedSize = d->engine()->size();
return d->cachedSize;
}
/*!
Sets the file size (in bytes) \a sz. Returns true if the file if the
resize succeeds; false otherwise. If \a sz is larger than the file
currently is the new bytes will be set to 0, if \a sz is smaller the
file is simply truncated.
\sa size()
*/
bool QFileDevice::resize(qint64 sz)
{
Q_D(QFileDevice);
if (!d->ensureFlushed())
return false;
d->engine();
if (isOpen() && d->fileEngine->pos() > sz)
seek(sz);
if (d->fileEngine->setSize(sz)) {
unsetError();
d->cachedSize = sz;
return true;
}
d->cachedSize = 0;
d->setError(QFile::ResizeError, d->fileEngine->errorString());
return false;
}
/*!
Returns the complete OR-ed together combination of
QFile::Permission for the file.
\sa setPermissions()
*/
QFile::Permissions QFileDevice::permissions() const
{
Q_D(const QFileDevice);
QAbstractFileEngine::FileFlags perms = d->engine()->fileFlags(QAbstractFileEngine::PermsMask) & QAbstractFileEngine::PermsMask;
return QFile::Permissions((int)perms); //ewww
}
/*!
Sets the permissions for the file to the \a permissions specified.
Returns true if successful, or false if the permissions cannot be
modified.
\sa permissions()
*/
bool QFileDevice::setPermissions(Permissions permissions)
{
Q_D(QFileDevice);
if (d->engine()->setPermissions(permissions)) {
unsetError();
return true;
}
d->setError(QFile::PermissionsError, d->fileEngine->errorString());
return false;
}
/*!
\enum QFileDevice::MemoryMapFlags
\since 4.4
This enum describes special options that may be used by the map()
function.
\value NoOptions No options.
*/
/*!
Maps \a size bytes of the file into memory starting at \a offset. A file
should be open for a map to succeed but the file does not need to stay
open after the memory has been mapped. When the QFile is destroyed
or a new file is opened with this object, any maps that have not been
unmapped will automatically be unmapped.
Any mapping options can be passed through \a flags.
Returns a pointer to the memory or 0 if there is an error.
\note On Windows CE 5.0 the file will be closed before mapping occurs.
\sa unmap()
*/
uchar *QFileDevice::map(qint64 offset, qint64 size, MemoryMapFlags flags)
{
Q_D(QFileDevice);
if (d->engine()
&& d->fileEngine->supportsExtension(QAbstractFileEngine::MapExtension)) {
unsetError();
uchar *address = d->fileEngine->map(offset, size, flags);
if (address == 0)
d->setError(d->fileEngine->error(), d->fileEngine->errorString());
return address;
}
return 0;
}
/*!
Unmaps the memory \a address.
Returns true if the unmap succeeds; false otherwise.
\sa map()
*/
bool QFileDevice::unmap(uchar *address)
{
Q_D(QFileDevice);
if (d->engine()
&& d->fileEngine->supportsExtension(QAbstractFileEngine::UnMapExtension)) {
unsetError();
bool success = d->fileEngine->unmap(address);
if (!success)
d->setError(d->fileEngine->error(), d->fileEngine->errorString());
return success;
}
d->setError(PermissionsError, tr("No file engine available or engine does not support UnMapExtension"));
return false;
}
QT_END_NAMESPACE

View File

@ -0,0 +1,147 @@
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** 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.
**
** 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.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QFILEDEVICE_H
#define QFILEDEVICE_H
#include <QtCore/qiodevice.h>
#include <QtCore/qstring.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class QFileDevicePrivate;
class Q_CORE_EXPORT QFileDevice : public QIODevice
{
#ifndef QT_NO_QOBJECT
Q_OBJECT
#endif
Q_DECLARE_PRIVATE(QFileDevice)
public:
enum FileError {
NoError = 0,
ReadError = 1,
WriteError = 2,
FatalError = 3,
ResourceError = 4,
OpenError = 5,
AbortError = 6,
TimeOutError = 7,
UnspecifiedError = 8,
RemoveError = 9,
RenameError = 10,
PositionError = 11,
ResizeError = 12,
PermissionsError = 13,
CopyError = 14
};
enum Permission {
ReadOwner = 0x4000, WriteOwner = 0x2000, ExeOwner = 0x1000,
ReadUser = 0x0400, WriteUser = 0x0200, ExeUser = 0x0100,
ReadGroup = 0x0040, WriteGroup = 0x0020, ExeGroup = 0x0010,
ReadOther = 0x0004, WriteOther = 0x0002, ExeOther = 0x0001
};
Q_DECLARE_FLAGS(Permissions, Permission)
enum FileHandleFlag {
AutoCloseHandle = 0x0001,
DontCloseHandle = 0
};
Q_DECLARE_FLAGS(FileHandleFlags, FileHandleFlag)
~QFileDevice();
FileError error() const;
void unsetError();
virtual void close();
bool isSequential() const;
int handle() const;
virtual QString fileName() const;
qint64 pos() const;
bool seek(qint64 offset);
bool atEnd() const;
bool flush();
qint64 size() const;
virtual bool resize(qint64 sz);
virtual Permissions permissions() const;
virtual bool setPermissions(Permissions permissionSpec);
enum MemoryMapFlags {
NoOptions = 0
};
uchar *map(qint64 offset, qint64 size, MemoryMapFlags flags = NoOptions);
bool unmap(uchar *address);
protected:
QFileDevice();
#ifdef QT_NO_QOBJECT
QFileDevice(QFileDevicePrivate &dd);
#else
explicit QFileDevice(QObject *parent);
QFileDevice(QFileDevicePrivate &dd, QObject *parent = 0);
#endif
qint64 readData(char *data, qint64 maxlen);
qint64 writeData(const char *data, qint64 len);
qint64 readLineData(char *data, qint64 maxlen);
private:
Q_DISABLE_COPY(QFileDevice)
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QFileDevice::Permissions)
QT_END_NAMESPACE
QT_END_HEADER
#endif // QFILEDEVICE_H

View File

@ -0,0 +1,104 @@
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** 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.
**
** 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.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QFILEDEVICE_P_H
#define QFILEDEVICE_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include "private/qiodevice_p.h"
#include "private/qringbuffer_p.h"
QT_BEGIN_NAMESPACE
class QAbstractFileEngine;
class QFSFileEngine;
class QFileDevicePrivate : public QIODevicePrivate
{
Q_DECLARE_PUBLIC(QFileDevice)
protected:
QFileDevicePrivate();
~QFileDevicePrivate();
virtual QAbstractFileEngine *engine() const;
QFileDevice::FileHandleFlags handleFlags;
mutable QAbstractFileEngine *fileEngine;
bool lastWasWrite;
QRingBuffer writeBuffer;
inline bool ensureFlushed() const;
bool putCharHelper(char c);
QFileDevice::FileError error;
void setError(QFileDevice::FileError err);
void setError(QFileDevice::FileError err, const QString &errorString);
void setError(QFileDevice::FileError err, int errNum);
mutable qint64 cachedSize;
};
inline bool QFileDevicePrivate::ensureFlushed() const
{
// This function ensures that the write buffer has been flushed (const
// because certain const functions need to call it.
if (lastWasWrite) {
const_cast<QFileDevicePrivate *>(this)->lastWasWrite = false;
if (!const_cast<QFileDevice *>(q_func())->flush())
return false;
}
return true;
}
QT_END_NAMESPACE
#endif // QFILEDEVICE_P_H

View File

@ -41,7 +41,6 @@
#include "qfilesystemengine_p.h"
#define _POSIX_
#include "qplatformdefs.h"
#include "private/qabstractfileengine_p.h"
#include "private/qfsfileengine_p.h"

View File

@ -39,7 +39,6 @@
**
****************************************************************************/
#define _POSIX_
#include "qplatformdefs.h"
#include "private/qabstractfileengine_p.h"
#include "private/qfsfileengine_p.h"
@ -66,6 +65,7 @@
#include <accctrl.h>
#include <ctype.h>
#include <limits.h>
#include <stdio.h>
#define SECURITY_WIN32
#include <security.h>

View File

@ -0,0 +1,344 @@
/****************************************************************************
**
** Copyright (C) 2012 Intel Corporation
** Contact: http://www.qt-project.org/
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** 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.
**
** 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.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qipaddress_p.h"
#include "private/qlocale_tools_p.h"
#include "qvarlengtharray.h"
QT_BEGIN_NAMESPACE
namespace QIPAddressUtils {
static QString number(quint8 val, int base = 10)
{
QChar zero(0x30);
return val ? qulltoa(val, base, zero) : zero;
}
typedef QVarLengthArray<char, 64> Buffer;
static bool checkedToAscii(Buffer &buffer, const QChar *begin, const QChar *end)
{
const ushort *const ubegin = reinterpret_cast<const ushort *>(begin);
const ushort *const uend = reinterpret_cast<const ushort *>(end);
const ushort *src = ubegin;
buffer.resize(uend - ubegin + 1);
char *dst = buffer.data();
while (src != uend) {
if (*src >= 0x7f)
return false;
*dst++ = *src++;
}
*dst = '\0';
return true;
}
static bool parseIp4Internal(IPv4Address &address, const char *ptr, bool acceptLeadingZero);
bool parseIp4(IPv4Address &address, const QChar *begin, const QChar *end)
{
Q_ASSERT(begin != end);
Buffer buffer;
if (!checkedToAscii(buffer, begin, end))
return false;
const char *ptr = buffer.data();
return parseIp4Internal(address, ptr, true);
}
static bool parseIp4Internal(IPv4Address &address, const char *ptr, bool acceptLeadingZero)
{
address = 0;
int dotCount = 0;
while (dotCount < 4) {
if (!acceptLeadingZero && *ptr == '0' &&
ptr[1] != '.' && ptr[1] != '\0')
return false;
const char *endptr;
bool ok;
quint64 ll = qstrtoull(ptr, &endptr, 0, &ok);
quint32 x = ll;
if (!ok || endptr == ptr || ll != x)
return false;
if (*endptr == '.' || dotCount == 3) {
if (x & ~0xff)
return false;
address <<= 8;
} else if (dotCount == 2) {
if (x & ~0xffff)
return false;
address <<= 16;
} else if (dotCount == 1) {
if (x & ~0xffffff)
return false;
address <<= 24;
}
address |= x;
if (dotCount == 3 && *endptr != '\0')
return false;
else if (dotCount == 3 || *endptr == '\0')
return true;
++dotCount;
ptr = endptr + 1;
}
return false;
}
void toString(QString &appendTo, IPv4Address address)
{
// reconstructing is easy
// use the fast operator% that pre-calculates the size
appendTo += number(address >> 24)
% QLatin1Char('.')
% number(address >> 16)
% QLatin1Char('.')
% number(address >> 8)
% QLatin1Char('.')
% number(address);
}
bool parseIp6(IPv6Address &address, const QChar *begin, const QChar *end)
{
Q_ASSERT(begin != end);
Buffer buffer;
if (!checkedToAscii(buffer, begin, end))
return false;
const char *ptr = buffer.data();
// count the colons
int colonCount = 0;
int dotCount = 0;
while (*ptr) {
if (*ptr == ':')
++colonCount;
if (*ptr == '.')
++dotCount;
++ptr;
}
// IPv4-in-IPv6 addresses are stricter in what they accept
if (dotCount != 0 && dotCount != 3)
return false;
memset(address, 0, sizeof address);
if (colonCount == 2 && end - begin == 2) // "::"
return true;
// if there's a double colon ("::"), this is how many zeroes it means
int zeroWordsToFill;
ptr = buffer.data();
// there are two cases where 8 colons are allowed: at the ends
// so test that before the colon-count test
if ((ptr[0] == ':' && ptr[1] == ':') ||
(ptr[end - begin - 2] == ':' && ptr[end - begin - 1] == ':')) {
zeroWordsToFill = 9 - colonCount;
} else if (colonCount < 2 || colonCount > 7) {
return false;
} else {
zeroWordsToFill = 8 - colonCount;
}
if (dotCount)
--zeroWordsToFill;
int pos = 0;
while (pos < 15) {
const char *endptr;
bool ok;
quint64 ll = qstrtoull(ptr, &endptr, 16, &ok);
quint16 x = ll;
if (ptr == endptr) {
// empty field, we hope it's "::"
if (zeroWordsToFill < 1)
return false;
if (pos == 0 || pos == colonCount * 2) {
if (ptr[0] == '\0' || ptr[1] != ':')
return false;
++ptr;
}
pos += zeroWordsToFill * 2;
zeroWordsToFill = 0;
++ptr;
continue;
}
if (!ok || ll != x)
return false;
if (*endptr == '.') {
// this could be an IPv4 address
// it's only valid in the last element
if (pos != 12)
return false;
IPv4Address ip4;
if (!parseIp4Internal(ip4, ptr, false))
return false;
address[12] = ip4 >> 24;
address[13] = ip4 >> 16;
address[14] = ip4 >> 8;
address[15] = ip4;
return true;
}
address[pos++] = x >> 8;
address[pos++] = x & 0xff;
if (*endptr == '\0')
break;
if (*endptr != ':')
return false;
ptr = endptr + 1;
}
return pos == 16;
}
static inline QChar toHex(uchar c)
{
return ushort(c > 9 ? c + 'a' - 0xA : c + '0');
}
void toString(QString &appendTo, IPv6Address address)
{
// the longest IPv6 address possible is:
// "1111:2222:3333:4444:5555:6666:255.255.255.255"
// however, this function never generates that. The longest it does
// generate without an IPv4 address is:
// "1111:2222:3333:4444:5555:6666:7777:8888"
// and the longest with an IPv4 address is:
// "::ffff:255.255.255.255"
static const int Ip6AddressMaxLen = sizeof "1111:2222:3333:4444:5555:6666:7777:8888";
static const int Ip6WithIp4AddressMaxLen = sizeof "::ffff:255.255.255.255";
// check for the special cases
const quint64 zeroes[] = { 0, 0 };
bool embeddedIp4 = false;
// we consider embedded IPv4 for:
// ::ffff:x.x.x.x
// ::x.x.x.y except if the x are 0 too
if (memcmp(address, zeroes, 10) == 0) {
if (address[10] == 0xff && address[11] == 0xff) {
embeddedIp4 = true;
} else if (address[10] == 0 && address[11] == 0) {
if (address[12] != 0 || address[13] != 0 || address[14] != 0) {
embeddedIp4 = true;
} else if (address[15] == 0) {
appendTo.append(QLatin1String("::"));
return;
}
}
}
// QString::reserve doesn't shrink, so it's fine to us
appendTo.reserve(appendTo.size() +
(embeddedIp4 ? Ip6WithIp4AddressMaxLen : Ip6AddressMaxLen));
// for finding where to place the "::"
int zeroRunLength = 0; // in octets
int zeroRunOffset = 0; // in octets
for (int i = 0; i < 16; i += 2) {
if (address[i] == 0 && address[i + 1] == 0) {
// found a zero, scan forward to see how many more there are
int j;
for (j = i; j < 16; j += 2) {
if (address[j] != 0 || address[j+1] != 0)
break;
}
if (j - i > zeroRunLength) {
zeroRunLength = j - i;
zeroRunOffset = i;
i = j;
}
}
}
const QChar colon = ushort(':');
if (zeroRunLength < 4)
zeroRunOffset = -1;
else if (zeroRunOffset == 0)
appendTo.append(colon);
for (int i = 0; i < 16; i += 2) {
if (i == zeroRunOffset) {
appendTo.append(colon);
i += zeroRunLength - 2;
continue;
}
if (i == 12 && embeddedIp4) {
IPv4Address ip4 = address[12] << 24 |
address[13] << 16 |
address[14] << 8 |
address[15];
toString(appendTo, ip4);
return;
}
if (address[i]) {
if (address[i] >> 4) {
appendTo.append(toHex(address[i] >> 4));
appendTo.append(toHex(address[i] & 0xf));
appendTo.append(toHex(address[i + 1] >> 4));
appendTo.append(toHex(address[i + 1] & 0xf));
} else if (address[i] & 0xf) {
appendTo.append(toHex(address[i] & 0xf));
appendTo.append(toHex(address[i + 1] >> 4));
appendTo.append(toHex(address[i + 1] & 0xf));
}
} else if (address[i + 1] >> 4) {
appendTo.append(toHex(address[i + 1] >> 4));
appendTo.append(toHex(address[i + 1] & 0xf));
} else {
appendTo.append(toHex(address[i + 1] & 0xf));
}
if (i != 14)
appendTo.append(colon);
}
}
}
QT_END_NAMESPACE

View File

@ -1,9 +1,9 @@
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Copyright (C) 2012 Intel Corporation
** Contact: http://www.qt-project.org/
**
** This file is part of the QtTest module of the Qt Toolkit.
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
@ -39,31 +39,36 @@
**
****************************************************************************/
#ifndef OLDNORMALIZEOBJECT_H
#define OLDNORMALIZEOBJECT_H
#ifndef QIPADDRESS_P_H
#define QIPADDRESS_P_H
#include <QObject>
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience of
// qurl*.cpp This header file may change from version to version without
// notice, or even be removed.
//
// We mean it.
//
struct Struct;
class Class;
template <typename T> class Template;
#include "qstring.h"
// An object with old moc output that incorrectly normalizes 'T<C> const &' in the function
// signatures
class OldNormalizeObject : public QObject
{
/* tmake ignore Q_OBJECT */
Q_OBJECT
QT_BEGIN_NAMESPACE
signals:
void typeRefSignal(Template<Class &> &ref);
void constTypeRefSignal(const Template<const Class &> &ref);
void typeConstRefSignal(Template<Class const &> const &ref);
namespace QIPAddressUtils {
public slots:
void typeRefSlot(Template<Class &> &) {}
void constTypeRefSlot(const Template<const Class &> &) {}
void typeConstRefSlot(Template<Class const &> const &) {}
};
typedef quint32 IPv4Address;
typedef quint8 IPv6Address[16];
#endif // OLDNORMALIZEOBJECT_H
Q_CORE_EXPORT bool parseIp4(IPv4Address &address, const QChar *begin, const QChar *end);
Q_CORE_EXPORT bool parseIp6(IPv6Address &address, const QChar *begin, const QChar *end);
Q_CORE_EXPORT void toString(QString &appendTo, IPv4Address address);
Q_CORE_EXPORT void toString(QString &appendTo, IPv6Address address);
} // namespace
QT_END_NAMESPACE
#endif // QIPADDRESS_P_H

View File

@ -673,7 +673,7 @@ int QResourceRoot::findNode(const QString &_path, const QLocale &locale) const
qDebug() << " " << child+j << " :: " << name(child+j);
}
#endif
const uint h = qHash(segment);
const uint h = qt_hash(segment.toString());
//do the binary search for the hash
int l = 0, r = child_count-1;

View File

@ -309,6 +309,27 @@ QString QStandardPaths::displayName(StandardLocation type)
}
#endif
/*!
\fn void QStandardPaths::enableTestMode(bool testMode)
Enables "test mode" in QStandardPaths, which changes writable locations
to point to test directories, in order to prevent auto tests from reading from
or writing to the current user's configuration.
This affects the locations into which test programs might write files:
GenericDataLocation, DataLocation, ConfigLocation,
GenericCacheLocation, CacheLocation.
Other locations are not affected.
On Unix, XDG_DATA_HOME is set to ~/.qttest/share, XDG_CONFIG_HOME is
set to ~/.qttest/config, and XDG_CACHE_HOME is set to ~/.qttest/cache.
On Mac, data goes to "~/.qttest/Application Support", cache goes to
~/.qttest/Cache, and config goes to ~/.qttest/Preferences.
On Windows, everything goes to a "qttest" directory under Application Data.
*/
QT_END_NAMESPACE
#endif // QT_NO_STANDARDPATHS

View File

@ -91,6 +91,8 @@ public:
static QString findExecutable(const QString &executableName, const QStringList &paths = QStringList());
static void enableTestMode(bool testMode);
private:
// prevent construction
QStandardPaths();

View File

@ -48,6 +48,7 @@
#include <QFile>
#include <QDir>
#include <QAtomicPointer>
#include <QCoreApplication>
#ifndef QT_NO_STANDARDPATHS
@ -62,6 +63,23 @@ public:
Q_GLOBAL_STATIC(QStandardPathsPrivate, configCache);
static bool qsp_testMode = false;
void QStandardPaths::enableTestMode(bool testMode)
{
qsp_testMode = testMode;
}
static void appendOrganizationAndApp(QString &path)
{
const QString org = QCoreApplication::organizationName();
if (!org.isEmpty())
path += QLatin1Char('/') + org;
const QString appName = QCoreApplication::applicationName();
if (!appName.isEmpty())
path += QLatin1Char('/') + appName;
}
QString QStandardPaths::writableLocation(StandardLocation type)
{
switch (type) {
@ -73,6 +91,30 @@ QString QStandardPaths::writableLocation(StandardLocation type)
break;
}
if (qsp_testMode) {
const QString qttestDir = QDir::homePath() + QLatin1String("/.qttest");
QString path;
switch (type) {
case GenericDataLocation:
case DataLocation:
path = qttestDir + QLatin1String("/share");
if (type == DataLocation)
appendOrganizationAndApp(path);
return path;
case GenericCacheLocation:
case CacheLocation:
path = qttestDir + QLatin1String("/cache");
if (type == CacheLocation)
appendOrganizationAndApp(path);
return path;
case ConfigLocation:
return qttestDir + QLatin1String("/config");
default:
break;
}
}
QJsonObject * localConfigObject = configCache()->object.loadAcquire();
if (localConfigObject == 0) {
QString configHome = QFile::decodeName(qgetenv("PATH_CONFIG_HOME"));

View File

@ -90,6 +90,13 @@ OSType translateLocation(QStandardPaths::StandardLocation type)
}
}
static bool qsp_testMode = false;
void QStandardPaths::enableTestMode(bool testMode)
{
qsp_testMode = testMode;
}
/*
Constructs a full unicode path from a FSRef.
*/
@ -101,6 +108,16 @@ static QString getFullPath(const FSRef &ref)
return QString();
}
static void appendOrganizationAndApp(QString &path)
{
const QString org = QCoreApplication::organizationName();
if (!org.isEmpty())
path += QLatin1Char('/') + org;
const QString appName = QCoreApplication::applicationName();
if (!appName.isEmpty())
path += QLatin1Char('/') + appName;
}
static QString macLocation(QStandardPaths::StandardLocation type, short domain)
{
// http://developer.apple.com/documentation/Carbon/Reference/Folder_Manager/Reference/reference.html
@ -111,17 +128,36 @@ static QString macLocation(QStandardPaths::StandardLocation type, short domain)
QString path = getFullPath(ref);
if (type == QStandardPaths::DataLocation || type == QStandardPaths::CacheLocation) {
if (!QCoreApplication::organizationName().isEmpty())
path += QLatin1Char('/') + QCoreApplication::organizationName();
if (!QCoreApplication::applicationName().isEmpty())
path += QLatin1Char('/') + QCoreApplication::applicationName();
}
return path;
if (type == QStandardPaths::DataLocation || type == QStandardPaths::CacheLocation)
appendOrganizationAndApp(path);
return path;
}
QString QStandardPaths::writableLocation(StandardLocation type)
{
if (qsp_testMode) {
const QString qttestDir = QDir::homePath() + QLatin1String("/.qttest");
QString path;
switch (type) {
case GenericDataLocation:
case DataLocation:
path = qttestDir + QLatin1String("/Application Support");
if (type == DataLocation)
appendOrganizationAndApp(path);
return path;
case GenericCacheLocation:
case CacheLocation:
path = qttestDir + QLatin1String("/Cache");
if (type == CacheLocation)
appendOrganizationAndApp(path);
return path;
case ConfigLocation:
return qttestDir + QLatin1String("/Preferences");
default:
break;
}
}
switch (type) {
case HomeLocation:
return QDir::homePath();

View File

@ -63,6 +63,13 @@ static void appendOrganizationAndApp(QString &path)
path += QLatin1Char('/') + appName;
}
static bool qsp_testMode = false;
void QStandardPaths::enableTestMode(bool testMode)
{
qsp_testMode = testMode;
}
QString QStandardPaths::writableLocation(StandardLocation type)
{
switch (type) {
@ -75,6 +82,8 @@ QString QStandardPaths::writableLocation(StandardLocation type)
{
// http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html
QString xdgCacheHome = QFile::decodeName(qgetenv("XDG_CACHE_HOME"));
if (qsp_testMode)
xdgCacheHome = QDir::homePath() + QLatin1String("/.qttest/cache");
if (xdgCacheHome.isEmpty())
xdgCacheHome = QDir::homePath() + QLatin1String("/.cache");
if (type == QStandardPaths::CacheLocation)
@ -85,6 +94,8 @@ QString QStandardPaths::writableLocation(StandardLocation type)
case GenericDataLocation:
{
QString xdgDataHome = QFile::decodeName(qgetenv("XDG_DATA_HOME"));
if (qsp_testMode)
xdgDataHome = QDir::homePath() + QLatin1String("/.qttest/share");
if (xdgDataHome.isEmpty())
xdgDataHome = QDir::homePath() + QLatin1String("/.local/share");
if (type == QStandardPaths::DataLocation)
@ -95,6 +106,8 @@ QString QStandardPaths::writableLocation(StandardLocation type)
{
// http://standards.freedesktop.org/basedir-spec/latest/
QString xdgConfigHome = QFile::decodeName(qgetenv("XDG_CONFIG_HOME"));
if (qsp_testMode)
xdgConfigHome = QDir::homePath() + QLatin1String("/.qttest/config");
if (xdgConfigHome.isEmpty())
xdgConfigHome = QDir::homePath() + QLatin1String("/.config");
return xdgConfigHome;
@ -140,7 +153,7 @@ QString QStandardPaths::writableLocation(StandardLocation type)
if (xdgConfigHome.isEmpty())
xdgConfigHome = QDir::homePath() + QLatin1String("/.config");
QFile file(xdgConfigHome + QLatin1String("/user-dirs.dirs"));
if (file.open(QIODevice::ReadOnly)) {
if (!qsp_testMode && file.open(QIODevice::ReadOnly)) {
QHash<QString, QString> lines;
QTextStream stream(&file);
// Only look for lines like: XDG_DESKTOP_DIR="$HOME/Desktop"

View File

@ -85,6 +85,13 @@ static QString convertCharArray(const wchar_t *path)
return QDir::fromNativeSeparators(QString::fromWCharArray(path));
}
static bool qsp_testMode = false;
void QStandardPaths::enableTestMode(bool testMode)
{
qsp_testMode = testMode;
}
QString QStandardPaths::writableLocation(StandardLocation type)
{
QString result;
@ -105,6 +112,8 @@ QString QStandardPaths::writableLocation(StandardLocation type)
if (SHGetSpecialFolderPath(0, path, CSIDL_LOCAL_APPDATA, FALSE))
#endif
result = convertCharArray(path);
if (qsp_testMode)
result += QLatin1String("/qttest");
if (type != GenericDataLocation) {
if (!QCoreApplication::organizationName().isEmpty())
result += QLatin1Char('/') + QCoreApplication::organizationName();

View File

@ -696,7 +696,7 @@ void QTextStreamPrivate::flushWriteBuffer()
// flush the file
#ifndef QT_NO_QOBJECT
QFile *file = qobject_cast<QFile *>(device);
QFileDevice *file = qobject_cast<QFileDevice *>(device);
bool flushed = !file || file->flush();
#else
bool flushed = true;

View File

@ -44,12 +44,13 @@
#include "private/qurltlds_p.h"
#include "private/qtldurl_p.h"
#include "QtCore/qstringlist.h"
#include "QtCore/qhash.h"
QT_BEGIN_NAMESPACE
static bool containsTLDEntry(const QString &entry)
{
int index = qHash(entry) % tldCount;
int index = qt_hash(entry) % tldCount;
int currentDomainIndex = tldIndices[index];
while (currentDomainIndex < tldIndices[index+1]) {
QString currentEntry = QString::fromUtf8(tldData + currentDomainIndex);

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Copyright (C) 2012 Intel Corporation.
** Contact: http://www.qt-project.org/
**
** This file is part of the QtCore module of the Qt Toolkit.
@ -44,18 +45,74 @@
#include <QtCore/qbytearray.h>
#include <QtCore/qobjectdefs.h>
#include <QtCore/qpair.h>
#include <QtCore/qstring.h>
#include <QtCore/qhash.h>
#include <QtCore/qlist.h>
#include <QtCore/qpair.h>
#include <QtCore/qglobal.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class QUrlQuery;
class QUrlPrivate;
class QDataStream;
template <typename E1, typename E2>
class QUrlTwoFlags
{
int i;
typedef int QUrlTwoFlags:: *Zero;
public:
Q_DECL_CONSTEXPR inline QUrlTwoFlags(E1 f) : i(f) {}
Q_DECL_CONSTEXPR inline QUrlTwoFlags(E2 f) : i(f) {}
Q_DECL_CONSTEXPR inline QUrlTwoFlags(QFlag f) : i(f) {}
Q_DECL_CONSTEXPR inline QUrlTwoFlags(QFlags<E1> f) : i(f.operator int()) {}
Q_DECL_CONSTEXPR inline QUrlTwoFlags(QFlags<E2> f) : i(f.operator int()) {}
Q_DECL_CONSTEXPR inline QUrlTwoFlags(Zero = 0) : i(0) {}
inline QUrlTwoFlags &operator&=(int mask) { i &= mask; return *this; }
inline QUrlTwoFlags &operator&=(uint mask) { i &= mask; return *this; }
inline QUrlTwoFlags &operator|=(QUrlTwoFlags f) { i |= f.i; return *this; }
inline QUrlTwoFlags &operator|=(E1 f) { i |= f; return *this; }
inline QUrlTwoFlags &operator|=(E2 f) { i |= f; return *this; }
inline QUrlTwoFlags &operator^=(QUrlTwoFlags f) { i ^= f.i; return *this; }
inline QUrlTwoFlags &operator^=(E1 f) { i ^= f; return *this; }
inline QUrlTwoFlags &operator^=(E2 f) { i ^= f; return *this; }
Q_DECL_CONSTEXPR inline operator QFlags<E1>() const { return E1(i); }
Q_DECL_CONSTEXPR inline operator QFlags<E2>() const { return E2(i); }
Q_DECL_CONSTEXPR inline operator int() const { return i; }
Q_DECL_CONSTEXPR inline bool operator!() const { return !i; }
Q_DECL_CONSTEXPR inline QUrlTwoFlags operator|(QUrlTwoFlags f) const
{ return QUrlTwoFlags(E1(i | f.i)); }
Q_DECL_CONSTEXPR inline QUrlTwoFlags operator|(E1 f) const
{ return QUrlTwoFlags(E1(i | f)); }
Q_DECL_CONSTEXPR inline QUrlTwoFlags operator|(E2 f) const
{ return QUrlTwoFlags(E2(i | f)); }
Q_DECL_CONSTEXPR inline QUrlTwoFlags operator^(QUrlTwoFlags f) const
{ return QUrlTwoFlags(E1(i ^ f.i)); }
Q_DECL_CONSTEXPR inline QUrlTwoFlags operator^(E1 f) const
{ return QUrlTwoFlags(E1(i ^ f)); }
Q_DECL_CONSTEXPR inline QUrlTwoFlags operator^(E2 f) const
{ return QUrlTwoFlags(E2(i ^ f)); }
Q_DECL_CONSTEXPR inline QUrlTwoFlags operator&(int mask) const
{ return QUrlTwoFlags(E1(i & mask)); }
Q_DECL_CONSTEXPR inline QUrlTwoFlags operator&(uint mask) const
{ return QUrlTwoFlags(E1(i & mask)); }
Q_DECL_CONSTEXPR inline QUrlTwoFlags operator&(E1 f) const
{ return QUrlTwoFlags(E1(i & f)); }
Q_DECL_CONSTEXPR inline QUrlTwoFlags operator&(E2 f) const
{ return QUrlTwoFlags(E2(i & f)); }
Q_DECL_CONSTEXPR inline QUrlTwoFlags operator~() const
{ return QUrlTwoFlags(E1(~i)); }
inline bool testFlag(E1 f) const { return (i & f) == f && (f != 0 || i == int(f)); }
inline bool testFlag(E2 f) const { return (i & f) == f && (f != 0 || i == int(f)); }
};
class Q_CORE_EXPORT QUrl
{
public:
@ -65,7 +122,7 @@ public:
};
// encoding / toString values
enum FormattingOption {
enum UrlFormattingOption {
None = 0x0,
RemoveScheme = 0x1,
RemovePassword = 0x2,
@ -75,23 +132,41 @@ public:
RemovePath = 0x20,
RemoveQuery = 0x40,
RemoveFragment = 0x80,
// 0x100: private: normalized
StripTrailingSlash = 0x10000
// 0x100 was a private code in Qt 4, keep unused for a while
PreferLocalFile = 0x200,
StripTrailingSlash = 0x400
};
Q_DECLARE_FLAGS(FormattingOptions, FormattingOption)
enum ComponentFormattingOption {
PrettyDecoded = 0x000000,
EncodeSpaces = 0x100000,
EncodeUnicode = 0x200000,
EncodeDelimiters = 0x400000 | 0x800000,
EncodeReserved = 0x1000000,
DecodeReserved = 0x2000000,
FullyEncoded = EncodeSpaces | EncodeUnicode | EncodeDelimiters | EncodeReserved,
MostDecoded = PrettyDecoded | DecodeReserved
};
Q_DECLARE_FLAGS(ComponentFormattingOptions, ComponentFormattingOption)
#ifdef qdoc
Q_DECLARE_FLAGS(FormattingOptions, UrlFormattingOption)
#else
typedef QUrlTwoFlags<UrlFormattingOption, ComponentFormattingOption> FormattingOptions;
#endif
QUrl();
#ifdef QT_NO_URL_CAST_FROM_STRING
explicit
#endif
QUrl(const QString &url, ParsingMode mode = TolerantMode);
QUrl(const QUrl &copy);
QUrl &operator =(const QUrl &copy);
#ifndef QT_NO_URL_CAST_FROM_STRING
QUrl &operator =(const QString &url);
#ifdef QT_NO_URL_CAST_FROM_STRING
explicit QUrl(const QString &url, ParsingMode mode = TolerantMode);
#else
QUrl(const QString &url, ParsingMode mode = TolerantMode);
QUrl &operator=(const QString &url);
#endif
#ifdef Q_COMPILER_RVALUE_REFS
QUrl(QUrl &&other) : d(0)
{ qSwap(d, other.d); }
inline QUrl &operator=(QUrl &&other)
{ qSwap(d, other.d); return *this; }
#endif
@ -100,96 +175,63 @@ public:
inline void swap(QUrl &other) { qSwap(d, other.d); }
void setUrl(const QString &url, ParsingMode mode = TolerantMode);
QString url(FormattingOptions options = None) const;
QString toString(FormattingOptions options = None) const;
QString toDisplayString(FormattingOptions options = None) const;
QString url(FormattingOptions options = FormattingOptions(PrettyDecoded)) const;
QString toString(FormattingOptions options = FormattingOptions(PrettyDecoded)) const;
QString toDisplayString(FormattingOptions options = FormattingOptions(PrettyDecoded)) const;
QByteArray toEncoded(FormattingOptions options = FullyEncoded) const;
static QUrl fromEncoded(const QByteArray &url, ParsingMode mode = TolerantMode);
static QUrl fromUserInput(const QString &userInput);
bool isValid() const;
QString errorString() const;
bool isEmpty() const;
void clear();
void setScheme(const QString &scheme);
QString scheme() const;
void setAuthority(const QString &authority);
QString authority() const;
QString authority(ComponentFormattingOptions options = PrettyDecoded) const;
void setUserInfo(const QString &userInfo);
QString userInfo() const;
QString userInfo(ComponentFormattingOptions options = PrettyDecoded) const;
void setUserName(const QString &userName);
QString userName() const;
void setEncodedUserName(const QByteArray &userName);
QByteArray encodedUserName() const;
QString userName(ComponentFormattingOptions options = PrettyDecoded) const;
void setPassword(const QString &password);
QString password() const;
void setEncodedPassword(const QByteArray &password);
QByteArray encodedPassword() const;
QString password(ComponentFormattingOptions = PrettyDecoded) const;
void setHost(const QString &host);
QString host() const;
void setEncodedHost(const QByteArray &host);
QByteArray encodedHost() const;
QString host(ComponentFormattingOptions = PrettyDecoded) const;
QString topLevelDomain(ComponentFormattingOptions options = PrettyDecoded) const;
void setPort(int port);
int port(int defaultPort = -1) const;
void setPath(const QString &path);
QString path() const;
void setEncodedPath(const QByteArray &path);
QByteArray encodedPath() const;
QString path(ComponentFormattingOptions options = PrettyDecoded) const;
bool hasQuery() const;
void setQuery(const QString &query);
void setQuery(const QUrlQuery &query);
QString query(ComponentFormattingOptions = PrettyDecoded) const;
void setEncodedQuery(const QByteArray &query);
QByteArray encodedQuery() const;
void setQueryDelimiters(char valueDelimiter, char pairDelimiter);
char queryValueDelimiter() const;
char queryPairDelimiter() const;
void setQueryItems(const QList<QPair<QString, QString> > &query);
void addQueryItem(const QString &key, const QString &value);
QList<QPair<QString, QString> > queryItems() const;
bool hasQueryItem(const QString &key) const;
QString queryItemValue(const QString &key) const;
QStringList allQueryItemValues(const QString &key) const;
void removeQueryItem(const QString &key);
void removeAllQueryItems(const QString &key);
void setEncodedQueryItems(const QList<QPair<QByteArray, QByteArray> > &query);
void addEncodedQueryItem(const QByteArray &key, const QByteArray &value);
QList<QPair<QByteArray, QByteArray> > encodedQueryItems() const;
bool hasEncodedQueryItem(const QByteArray &key) const;
QByteArray encodedQueryItemValue(const QByteArray &key) const;
QList<QByteArray> allEncodedQueryItemValues(const QByteArray &key) const;
void removeEncodedQueryItem(const QByteArray &key);
void removeAllEncodedQueryItems(const QByteArray &key);
void setFragment(const QString &fragment);
QString fragment() const;
void setEncodedFragment(const QByteArray &fragment);
QByteArray encodedFragment() const;
bool hasFragment() const;
#ifndef QT_BOOTSTRAPPED
QString topLevelDomain() const;
#endif
QString fragment(ComponentFormattingOptions options = PrettyDecoded) const;
void setFragment(const QString &fragment);
QUrl resolved(const QUrl &relative) const;
bool isRelative() const;
bool isParentOf(const QUrl &url) const;
bool isLocalFile() const;
static QUrl fromLocalFile(const QString &localfile);
QString toLocalFile() const;
bool isLocalFile() const;
QByteArray toEncoded(FormattingOptions options = None) const;
static QUrl fromUserInput(const QString &userInput);
void detach();
bool isDetached() const;
@ -202,37 +244,121 @@ public:
static QByteArray toPercentEncoding(const QString &,
const QByteArray &exclude = QByteArray(),
const QByteArray &include = QByteArray());
static QString fromPunycode(const QByteArray &);
static QByteArray toPunycode(const QString &);
#if QT_DEPRECATED_SINCE(5,0)
QT_DEPRECATED static QString fromPunycode(const QByteArray &punycode)
{ return fromAce(punycode); }
QT_DEPRECATED static QByteArray toPunycode(const QString &string)
{ return toAce(string); }
QT_DEPRECATED inline void setQueryItems(const QList<QPair<QString, QString> > &qry);
QT_DEPRECATED inline void addQueryItem(const QString &key, const QString &value);
QT_DEPRECATED inline QList<QPair<QString, QString> > queryItems() const;
QT_DEPRECATED inline bool hasQueryItem(const QString &key) const;
QT_DEPRECATED inline QString queryItemValue(const QString &key) const;
QT_DEPRECATED inline QStringList allQueryItemValues(const QString &key) const;
QT_DEPRECATED inline void removeQueryItem(const QString &key);
QT_DEPRECATED inline void removeAllQueryItems(const QString &key);
QT_DEPRECATED inline void setEncodedQueryItems(const QList<QPair<QByteArray, QByteArray> > &query);
QT_DEPRECATED inline void addEncodedQueryItem(const QByteArray &key, const QByteArray &value);
QT_DEPRECATED inline QList<QPair<QByteArray, QByteArray> > encodedQueryItems() const;
QT_DEPRECATED inline bool hasEncodedQueryItem(const QByteArray &key) const;
QT_DEPRECATED inline QByteArray encodedQueryItemValue(const QByteArray &key) const;
QT_DEPRECATED inline QList<QByteArray> allEncodedQueryItemValues(const QByteArray &key) const;
QT_DEPRECATED inline void removeEncodedQueryItem(const QByteArray &key);
QT_DEPRECATED inline void removeAllEncodedQueryItems(const QByteArray &key);
QT_DEPRECATED void setEncodedUrl(const QByteArray &u, ParsingMode mode = TolerantMode)
{ setUrl(QString::fromUtf8(u.constData(), u.size()), mode); }
QT_DEPRECATED QByteArray encodedUserName() const
{ return userName(FullyEncoded).toLatin1(); }
QT_DEPRECATED void setEncodedUserName(const QByteArray &value)
{ setUserName(QString::fromLatin1(value)); }
QT_DEPRECATED QByteArray encodedPassword() const
{ return password(FullyEncoded).toLatin1(); }
QT_DEPRECATED void setEncodedPassword(const QByteArray &value)
{ setPassword(QString::fromLatin1(value)); }
QT_DEPRECATED QByteArray encodedHost() const
{ return host(FullyEncoded).toLatin1(); }
QT_DEPRECATED void setEncodedHost(const QByteArray &value)
{ setHost(QString::fromLatin1(value)); }
QT_DEPRECATED QByteArray encodedPath() const
{ return path(FullyEncoded).toLatin1(); }
QT_DEPRECATED void setEncodedPath(const QByteArray &value)
{ setPath(QString::fromLatin1(value)); }
QT_DEPRECATED QByteArray encodedQuery() const
{ return toLatin1_helper(query(FullyEncoded)); }
QT_DEPRECATED void setEncodedQuery(const QByteArray &value)
{ setQuery(QString::fromLatin1(value)); }
QT_DEPRECATED QByteArray encodedFragment() const
{ return toLatin1_helper(fragment(FullyEncoded)); }
QT_DEPRECATED void setEncodedFragment(const QByteArray &value)
{ setFragment(QString::fromLatin1(value)); }
private:
// helper function for the encodedQuery and encodedFragment functions
static QByteArray toLatin1_helper(const QString &string)
{
if (string.isEmpty())
return string.isNull() ? QByteArray() : QByteArray("");
return string.toLatin1();
}
#endif
public:
static QString fromAce(const QByteArray &);
static QByteArray toAce(const QString &);
static QStringList idnWhitelist();
static void setIdnWhitelist(const QStringList &);
QString errorString() const;
#if QT_DEPRECATED_SINCE(5,0)
QT_DEPRECATED void setEncodedUrl(const QByteArray &u, ParsingMode mode = TolerantMode)
{ setUrl(QString::fromUtf8(u.constData(), u.size()), mode); }
QT_DEPRECATED static QUrl fromEncoded(const QByteArray &u, ParsingMode mode = TolerantMode)
{ return QUrl(QString::fromUtf8(u.constData(), u.size()), mode); }
#endif
friend Q_CORE_EXPORT uint qHash(const QUrl &url, uint seed = 0);
private:
QUrlPrivate *d;
friend class QUrlQuery;
public:
typedef QUrlPrivate * DataPtr;
inline DataPtr &data_ptr() { return d; }
};
inline uint qHash(const QUrl &url)
{
return qHash(url.toEncoded(QUrl::FormattingOption(0x100)));
}
Q_DECLARE_TYPEINFO(QUrl, Q_MOVABLE_TYPE);
Q_DECLARE_SHARED(QUrl)
Q_DECLARE_OPERATORS_FOR_FLAGS(QUrl::FormattingOptions)
Q_DECLARE_OPERATORS_FOR_FLAGS(QUrl::ComponentFormattingOptions)
//Q_DECLARE_OPERATORS_FOR_FLAGS(QUrl::FormattingOptions)
Q_DECL_CONSTEXPR inline QUrl::FormattingOptions operator|(QUrl::UrlFormattingOption f1, QUrl::UrlFormattingOption f2)
{ return QUrl::FormattingOptions(f1) | f2; }
Q_DECL_CONSTEXPR inline QUrl::FormattingOptions operator|(QUrl::UrlFormattingOption f1, QUrl::FormattingOptions f2)
{ return f2 | f1; }
inline QIncompatibleFlag operator|(QUrl::UrlFormattingOption f1, int f2)
{ return QIncompatibleFlag(int(f1) | f2); }
// add operators for OR'ing the two types of flags
inline QUrl::FormattingOptions &operator|=(QUrl::FormattingOptions &i, QUrl::ComponentFormattingOptions f)
{ i |= QUrl::UrlFormattingOption(int(f)); return i; }
Q_DECL_CONSTEXPR inline QUrl::FormattingOptions operator|(QUrl::UrlFormattingOption i, QUrl::ComponentFormattingOption f)
{ return i | QUrl::UrlFormattingOption(int(f)); }
Q_DECL_CONSTEXPR inline QUrl::FormattingOptions operator|(QUrl::UrlFormattingOption i, QUrl::ComponentFormattingOptions f)
{ return i | QUrl::UrlFormattingOption(int(f)); }
Q_DECL_CONSTEXPR inline QUrl::FormattingOptions operator|(QUrl::ComponentFormattingOption f, QUrl::UrlFormattingOption i)
{ return i | QUrl::UrlFormattingOption(int(f)); }
Q_DECL_CONSTEXPR inline QUrl::FormattingOptions operator|(QUrl::ComponentFormattingOptions f, QUrl::UrlFormattingOption i)
{ return i | QUrl::UrlFormattingOption(int(f)); }
Q_DECL_CONSTEXPR inline QUrl::FormattingOptions operator|(QUrl::FormattingOptions i, QUrl::ComponentFormattingOptions f)
{ return i | QUrl::UrlFormattingOption(int(f)); }
Q_DECL_CONSTEXPR inline QUrl::FormattingOptions operator|(QUrl::ComponentFormattingOption f, QUrl::FormattingOptions i)
{ return i | QUrl::UrlFormattingOption(int(f)); }
Q_DECL_CONSTEXPR inline QUrl::FormattingOptions operator|(QUrl::ComponentFormattingOptions f, QUrl::FormattingOptions i)
{ return i | QUrl::UrlFormattingOption(int(f)); }
//inline QUrl::UrlFormattingOption &operator=(const QUrl::UrlFormattingOption &i, QUrl::ComponentFormattingOptions f)
//{ i = int(f); f; }
#ifndef QT_NO_DATASTREAM
Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QUrl &);
@ -245,6 +371,10 @@ Q_CORE_EXPORT QDebug operator<<(QDebug, const QUrl &);
QT_END_NAMESPACE
#if QT_DEPRECATED_SINCE(5,0)
# include <QtCore/qurlquery.h>
#endif
QT_END_HEADER
#endif // QURL_H

189
src/corelib/io/qurl_p.h Normal file
View File

@ -0,0 +1,189 @@
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Copyright (C) 2012 Intel Corporation.
** Contact: http://www.qt-project.org/
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** 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.
**
** 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.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QURL_P_H
#define QURL_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience of
// qurl*.cpp This header file may change from version to version without
// notice, or even be removed.
//
// We mean it.
//
#include "qurl.h"
QT_BEGIN_NAMESPACE
class QUrlPrivate
{
public:
enum Section {
Scheme = 0x01,
UserName = 0x02,
Password = 0x04,
UserInfo = UserName | Password,
Host = 0x08,
Port = 0x10,
Authority = UserInfo | Host | Port,
Path = 0x20,
Hierarchy = Authority | Path,
Query = 0x40,
Fragment = 0x80,
FullUrl = 0xff
};
enum ErrorCode {
// the high byte of the error code matches the Section
InvalidSchemeError = Scheme << 8,
SchemeEmptyError,
InvalidUserNameError = UserName << 8,
InvalidPasswordError = Password << 8,
InvalidRegNameError = Host << 8,
InvalidIPv4AddressError,
InvalidIPv6AddressError,
InvalidIPvFutureError,
HostMissingEndBracket,
InvalidPortError = Port << 8,
PortEmptyError,
InvalidPathError = Path << 8,
PathContainsColonBeforeSlash,
InvalidQueryError = Query << 8,
InvalidFragmentError = Fragment << 8,
NoError = 0
};
QUrlPrivate();
QUrlPrivate(const QUrlPrivate &copy);
void parse(const QString &url, QUrl::ParsingMode parsingMode);
void clear();
bool isEmpty() const
{ return sectionIsPresent == 0 && port == -1 && path.isEmpty(); }
// no QString scheme() const;
void appendAuthority(QString &appendTo, QUrl::FormattingOptions options, Section appendingTo) const;
void appendUserInfo(QString &appendTo, QUrl::FormattingOptions options, Section appendingTo) const;
void appendUserName(QString &appendTo, QUrl::FormattingOptions options) const;
void appendPassword(QString &appendTo, QUrl::FormattingOptions options) const;
void appendHost(QString &appendTo, QUrl::FormattingOptions options) const;
void appendPath(QString &appendTo, QUrl::FormattingOptions options, Section appendingTo) const;
void appendQuery(QString &appendTo, QUrl::FormattingOptions options, Section appendingTo) const;
void appendFragment(QString &appendTo, QUrl::FormattingOptions options) const;
// the "end" parameters are like STL iterators: they point to one past the last valid element
bool setScheme(const QString &value, int len, bool decoded = false);
bool setAuthority(const QString &auth, int from, int end);
void setUserInfo(const QString &userInfo, int from, int end);
void setUserName(const QString &value, int from, int end);
void setPassword(const QString &value, int from, int end);
bool setHost(const QString &value, int from, int end, bool maybePercentEncoded = true);
void setPath(const QString &value, int from, int end);
void setQuery(const QString &value, int from, int end);
void setFragment(const QString &value, int from, int end);
inline bool hasScheme() const { return sectionIsPresent & Scheme; }
inline bool hasAuthority() const { return sectionIsPresent & Authority; }
inline bool hasUserInfo() const { return sectionIsPresent & UserInfo; }
inline bool hasUserName() const { return sectionIsPresent & UserName; }
inline bool hasPassword() const { return sectionIsPresent & Password; }
inline bool hasHost() const { return sectionIsPresent & Host; }
inline bool hasPort() const { return port != -1; }
inline bool hasPath() const { return !path.isEmpty(); }
inline bool hasQuery() const { return sectionIsPresent & Query; }
inline bool hasFragment() const { return sectionIsPresent & Fragment; }
QString mergePaths(const QString &relativePath) const;
QAtomicInt ref;
int port;
QString scheme;
QString userName;
QString password;
QString host;
QString path;
QString query;
QString fragment;
ushort errorCode;
ushort errorSupplement;
// not used for:
// - Port (port == -1 means absence)
// - Path (there's no path delimiter, so we optimize its use out of existence)
// Schemes are never supposed to be empty, but we keep the flag anyway
uchar sectionIsPresent;
// UserName, Password, Path, Query, and Fragment never contain errors in TolerantMode.
// Those flags are set only by the strict parser.
uchar sectionHasError;
};
// in qurlrecode.cpp
extern Q_AUTOTEST_EXPORT int qt_urlRecode(QString &appendTo, const QChar *begin, const QChar *end,
QUrl::ComponentFormattingOptions encoding, const ushort *tableModifications);
// in qurlidna.cpp
enum AceOperation { ToAceOnly, NormalizeAce };
extern QString qt_ACE_do(const QString &domain, AceOperation op);
extern Q_AUTOTEST_EXPORT void qt_nameprep(QString *source, int from);
extern Q_AUTOTEST_EXPORT bool qt_check_std3rules(const QChar *uc, int len);
extern Q_AUTOTEST_EXPORT void qt_punycodeEncoder(const QChar *s, int ucLength, QString *output);
extern Q_AUTOTEST_EXPORT QString qt_punycodeDecoder(const QString &pc);
QT_END_NAMESPACE
#endif // QURL_P_H

2592
src/corelib/io/qurlidna.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,729 @@
/****************************************************************************
**
** Copyright (C) 2012 Intel Corporation.
** Contact: http://www.qt-project.org/
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** 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.
**
** 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.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qurlquery.h"
#include "qurl_p.h"
QT_BEGIN_NAMESPACE
/*!
\class QUrlQuery
\brief The QUrlQuery class provides a way to manipulate a key-value pairs in
a URL's query.
\reentrant
\ingroup io
\ingroup network
\ingroup shared
It is used to parse the query strings found in URLs like the following:
\img qurl-querystring.png
Query strings like the above are used to transmit options in the URL and are
usually decoded into multiple key-value pairs. The one above would contain
two entries in its list, with keys "type" and "color". QUrlQuery can also be
used to create a query string suitable for use in QUrl::setQuery() from the
individual components of the query.
The most common way of parsing a query string is to initialize it in the
constructor by passing it the query string. Otherwise, the setQuery() method
can be used to set the query to be parsed. That method can also be used to
parse a query with non-standard delimiters, after having set them using the
setQueryDelimiters() function.
The encoded query string can be obtained again using query(). This will take
all the internally-stored items and encode the string using the delimiters.
\section1 Encoding
All of the getter methods in QUrlQuery support an optional parameter of type
QUrl::ComponentFormattingOptions, including query(), which dictate how to
encode the data in question. Regardless of the mode, the returned value must
still be considered a percent-encoded string, as there are certain values
which cannot be expressed in decoded form (like control characters, byte
sequences not decodable to UTF-8). For that reason, the percent character is
always represented by the string "%25".
\section2 Handling of spaces and plus ("+")
Web browsers usually encode spaces found in HTML FORM elements to a plus sign
("+") and plus signs to its percent-encoded form (%2B). However, the Internet
specifications governing URLs do not consider spaces and the plus character
equivalent.
For that reason, QUrlQuery never encodes the space character to "+" and will
never decode "+" to a space character. Instead, space characters will be
rendered "%20" in encoded form.
To support encoding like that of HTML forms, QUrlQuery also never decodes the
"%2B" sequence to a plus sign nor encode a plus sign. In fact, any "%2B" or
"+" sequences found in the keys, values, or query string are left exactly
like written (except for the uppercasing of "%2b" to "%2B").
\section1 Non-standard delimiters
By default, QUrlQuery uses an equal sign ("=") to separate a key from its
value, and an ampersand ("&") to separate key-value pairs from each other. It
is possible to change the delimiters that QUrlQuery uses for parsing and for
reconstructing the query by calling setQueryDelimiters().
Non-standard delimiters should be chosen from among what RFC 3986 calls
"sub-delimiters". They are:
\code
sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
/ "*" / "+" / "," / ";" / "="
\endcode
Use of other characters is not supported and may result in unexpected
behaviour. QUrlQuery does not verify that you passed a valid delimiter.
\sa QUrl
*/
typedef QList<QPair<QString, QString> > Map;
class QUrlQueryPrivate : public QSharedData
{
public:
QUrlQueryPrivate(const QString &query = QString())
: valueDelimiter(QUrlQuery::defaultQueryValueDelimiter()),
pairDelimiter(QUrlQuery::defaultQueryPairDelimiter())
{ if (!query.isEmpty()) setQuery(query); }
QString recodeFromUser(const QString &input) const;
QString recodeToUser(const QString &input, QUrl::ComponentFormattingOptions encoding) const;
void setQuery(const QString &query);
void addQueryItem(const QString &key, const QString &value)
{ itemList.append(qMakePair(recodeFromUser(key), recodeFromUser(value))); }
int findRecodedKey(const QString &key, int from = 0) const
{
for (int i = from; i < itemList.size(); ++i)
if (itemList.at(i).first == key)
return i;
return itemList.size();
}
Map::const_iterator findKey(const QString &key) const
{ return itemList.constBegin() + findRecodedKey(recodeFromUser(key)); }
Map::iterator findKey(const QString &key)
{ return itemList.begin() + findRecodedKey(recodeFromUser(key)); }
// use QMap so we end up sorting the items by key
Map itemList;
QChar valueDelimiter;
QChar pairDelimiter;
};
template<> void QSharedDataPointer<QUrlQueryPrivate>::detach()
{
if (d && d->ref.load() == 1)
return;
QUrlQueryPrivate *x = (d ? new QUrlQueryPrivate(*d)
: new QUrlQueryPrivate);
x->ref.ref();
if (d && !d->ref.deref())
delete d;
d = x;
}
// Here's how we do the encoding in QUrlQuery
// The RFC says these are the delimiters:
// gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
// sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
// / "*" / "+" / "," / ";" / "="
// And the definition of query is:
// query = *( pchar / "/" / "?" )
// pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
//
// The strict definition of query says that it can have unencoded any
// unreserved, sub-delim, ":", "@", "/" and "?". Or, by exclusion, excluded
// delimiters are "#", "[" and "]" -- if those are present, they must be
// percent-encoded. The fact that "[" and "]" should be encoded is probably a
// mistake in the spec, so we ignore it and leave the decoded.
//
// The internal storage in the Map is equivalent to PrettyDecoded. That means
// the getter methods, when called with the default encoding value, will not
// have to recode anything (except for toString()).
//
// The "+" sub-delimiter is always left untouched. We never encode "+" to "%2B"
// nor do we decode "%2B" to "+", no matter what the user asks.
//
// The rest of the delimiters are kept in their decoded forms and that's
// considered non-ambiguous. That includes the pair and value delimiters
// themselves.
//
// But when recreating the query string, in toString(), we must take care of
// the special delimiters: the pair and value delimiters, as well as the "#"
// character if unambiguous decoding is requested.
#define decode(x) ushort(x)
#define leave(x) ushort(0x100 | (x))
#define encode(x) ushort(0x200 | (x))
static const ushort prettyDecodedActions[] = { leave('+'), 0 };
inline QString QUrlQueryPrivate::recodeFromUser(const QString &input) const
{
// note: duplicated in setQuery()
QString output;
if (qt_urlRecode(output, input.constData(), input.constData() + input.length(),
QUrl::MostDecoded,
prettyDecodedActions))
return output;
return input;
}
inline bool idempotentRecodeToUser(QUrl::ComponentFormattingOptions encoding)
{
return encoding == QUrl::PrettyDecoded;
}
inline QString QUrlQueryPrivate::recodeToUser(const QString &input, QUrl::ComponentFormattingOptions encoding) const
{
// our internal formats are stored in "PrettyDecoded" form
// and there are no ambiguous characters
if (idempotentRecodeToUser(encoding))
return input;
if (!(encoding & QUrl::EncodeDelimiters)) {
QString output;
if (qt_urlRecode(output, input.constData(), input.constData() + input.length(),
encoding, prettyDecodedActions))
return output;
return input;
}
// re-encode the "#" character and the query delimiter pair
ushort actions[] = { encode(pairDelimiter.unicode()), encode(valueDelimiter.unicode()),
encode('#'), 0 };
QString output;
if (qt_urlRecode(output, input.constData(), input.constData() + input.length(), encoding, actions))
return output;
return input;
}
void QUrlQueryPrivate::setQuery(const QString &query)
{
itemList.clear();
const QChar *pos = query.constData();
const QChar *const end = pos + query.size();
while (pos != end) {
const QChar *begin = pos;
const QChar *delimiter = 0;
while (pos != end) {
// scan for the component parts of this pair
if (!delimiter && pos->unicode() == valueDelimiter)
delimiter = pos;
if (pos->unicode() == pairDelimiter)
break;
++pos;
}
if (!delimiter)
delimiter = pos;
// pos is the end of this pair (the end of the string or the pair delimiter)
// delimiter points to the value delimiter or to the end of this pair
QString key;
if (!qt_urlRecode(key, begin, delimiter,
QUrl::MostDecoded,
prettyDecodedActions))
key = QString(begin, delimiter - begin);
if (delimiter == pos) {
// the value delimiter wasn't found, store a null value
itemList.append(qMakePair(key, QString()));
} else if (delimiter + 1 == pos) {
// if the delimiter was found but the value is empty, store empty-but-not-null
itemList.append(qMakePair(key, QString(0, Qt::Uninitialized)));
} else {
QString value;
if (!qt_urlRecode(value, delimiter + 1, pos,
QUrl::MostDecoded,
prettyDecodedActions))
value = QString(delimiter + 1, pos - delimiter - 1);
itemList.append(qMakePair(key, value));
}
if (pos != end)
++pos;
}
}
// allow QUrlQueryPrivate to detach from null
template <> inline QUrlQueryPrivate *
QSharedDataPointer<QUrlQueryPrivate>::clone()
{
return d ? new QUrlQueryPrivate(*d) : new QUrlQueryPrivate;
}
/*!
Constructs an empty QUrlQuery object. A query can be set afterwards by
calling setQuery() or items can be added by using addQueryItem().
\sa setQuery(), addQueryItem()
*/
QUrlQuery::QUrlQuery()
: d(0)
{
}
/*!
Constructs a QUrlQuery object and parses the \a queryString query string,
using the default query delimiters. To parse a query string using other
delimiters, you should first set them using setQueryDelimiters() and then
set the query with setQuery().
*/
QUrlQuery::QUrlQuery(const QString &queryString)
: d(queryString.isEmpty() ? 0 : new QUrlQueryPrivate(queryString))
{
}
/*!
Constructs a QUrlQuery object and parses the query string found in the \a
url URL, using the default query delimiters. To parse a query string using
other delimiters, you should first set them using setQueryDelimiters() and
then set the query with setQuery().
\sa QUrl::query()
*/
QUrlQuery::QUrlQuery(const QUrl &url)
: d(0)
{
// use internals to avoid unnecessary recoding
// ### FIXME: actually do it
if (url.hasQuery())
d = new QUrlQueryPrivate(url.query());
}
/*!
Copies the contents of the \a other QUrlQuery object, including the query
delimiters.
*/
QUrlQuery::QUrlQuery(const QUrlQuery &other)
: d(other.d)
{
}
/*!
Copies the contents of the \a other QUrlQuery object, including the query
delimiters.
*/
QUrlQuery &QUrlQuery::operator =(const QUrlQuery &other)
{
d = other.d;
return *this;
}
/*!
Destroys this QUrlQuery object.
*/
QUrlQuery::~QUrlQuery()
{
// d auto-deletes
}
/*!
Returns true if this object and the \a other object contain the same
contents, in the same order, and use the same query delimiters.
*/
bool QUrlQuery::operator ==(const QUrlQuery &other) const
{
if (d == other.d)
return true;
if (d && other.d)
return d->valueDelimiter == other.d->valueDelimiter &&
d->pairDelimiter == other.d->pairDelimiter &&
d->itemList == other.d->itemList;
return false;
}
/*!
Returns true if this QUrlQUery object contains no key-value pairs, such as
after being default-constructed or after parsing an empty query string.
\sa setQuery(), clear()
*/
bool QUrlQuery::isEmpty() const
{
return d ? d->itemList.isEmpty() : true;
}
/*!
\internal
*/
bool QUrlQuery::isDetached() const
{
return d && d->ref.load() == 1;
}
/*!
Clears this QUrlQuery object by removing all of the key-value pairs
currently stored. If the query delimiters have been changed, this function
will leave them with their changed values.
\sa isEmpty(), setQueryDelimiters()
*/
void QUrlQuery::clear()
{
if (d.constData())
d->itemList.clear();
}
/*!
Parses the query string in \a queryString and sets the internal items to
the values found there. If any delimiters have been specified with
setQueryDelimiters(), this function will use them instead of the default
delimiters to parse the string.
*/
void QUrlQuery::setQuery(const QString &queryString)
{
d->setQuery(queryString);
}
static void recodeAndAppend(QString &to, const QString &input,
QUrl::ComponentFormattingOptions encoding, const ushort *tableModifications)
{
if (!qt_urlRecode(to, input.constData(), input.constData() + input.length(), encoding, tableModifications))
to += input;
}
/*!
Returns the reconstructed query string, formed from the key-value pairs
currently stored in this QUrlQuery object and separated by the query
delimiters chosen for this object. The keys and values are encoded using
the options given by the \a encoding paramter.
For this function, the only ambiguous delimiter is the hash ("#"), as in
URLs it is used to separate the query string from the fragment that may
follow.
The order of the key-value pairs in the returned string is exactly the same
as in the original query.
\sa setQuery(), QUrl::setQuery(), QUrl::fragment(), \l{#Encoding}{Encoding}
*/
QString QUrlQuery::query(QUrl::ComponentFormattingOptions encoding) const
{
if (!d)
return QString();
// unlike the component encoding, for the whole query we need to modify a little:
// - the "#" character is ambiguous, so we decode it only in DecodeAllDelimiters mode
// - the query delimiter pair must always be encoded
// - the non-delimiters vary on DecodeUnambiguousDelimiters
// so:
// - full encoding: encode the non-delimiters, the pair, "#", "[" and "]"
// - pretty decode: decode the non-delimiters, "[" and "]"; encode the pair and "#"
// - decode all: decode the non-delimiters, "[", "]", "#"; encode the pair
// start with what's always encoded
ushort tableActions[] = {
leave('+'), // 0
encode(d->pairDelimiter.unicode()), // 1
encode(d->valueDelimiter.unicode()), // 2
decode('#'), // 3
0
};
if (encoding & QUrl::EncodeDelimiters) {
tableActions[3] = encode('#');
}
QString result;
Map::const_iterator it = d->itemList.constBegin();
Map::const_iterator end = d->itemList.constEnd();
{
int size = 0;
for ( ; it != end; ++it)
size += it->first.length() + 1 + it->second.length() + 1;
result.reserve(size + size / 4);
}
for (it = d->itemList.constBegin(); it != end; ++it) {
if (!result.isEmpty())
result += QChar(d->pairDelimiter);
recodeAndAppend(result, it->first, encoding, tableActions);
if (!it->second.isNull()) {
result += QChar(d->valueDelimiter);
recodeAndAppend(result, it->second, encoding, tableActions);
}
}
return result;
}
/*!
Sets the characters used for delimiting between keys and values,
and between key-value pairs in the URL's query string. The default
value delimiter is '=' and the default pair delimiter is '&'.
\img qurl-querystring.png
\a valueDelimiter will be used for separating keys from values,
and \a pairDelimiter will be used to separate key-value pairs.
Any occurrences of these delimiting characters in the encoded
representation of the keys and values of the query string are
percent encoded when returned in query().
If \a valueDelimiter is set to '(' and \a pairDelimiter is ')',
the above query string would instead be represented like this:
\snippet doc/src/snippets/code/src_corelib_io_qurl.cpp 4
\note Non-standard delimiters should be chosen from among what RFC 3986 calls
"sub-delimiters". They are:
\code
sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
/ "*" / "+" / "," / ";" / "="
\endcode
Use of other characters is not supported and may result in unexpected
behaviour. This method does not verify that you passed a valid delimiter.
\sa queryValueDelimiter(), queryPairDelimiter()
*/
void QUrlQuery::setQueryDelimiters(QChar valueDelimiter, QChar pairDelimiter)
{
d->valueDelimiter = valueDelimiter.unicode();
d->pairDelimiter = pairDelimiter.unicode();
}
/*!
Returns the character used to delimit between keys and values when
reconstructing the query string in query() or when parsing in setQuery().
\sa setQueryDelimiters(), queryPairDelimiter()
*/
QChar QUrlQuery::queryValueDelimiter() const
{
return d ? d->valueDelimiter : defaultQueryValueDelimiter();
}
/*!
Returns the character used to delimit between keys-value pairs when
reconstructing the query string in query() or when parsing in setQuery().
\sa setQueryDelimiters(), queryValueDelimiter()
*/
QChar QUrlQuery::queryPairDelimiter() const
{
return d ? d->pairDelimiter : defaultQueryPairDelimiter();
}
/*!
Sets the items in this QUrlQuery object to \a query. The order of the
elements in \a query is preserved.
\note This method does not treat spaces (ASCII 0x20) and plus ("+") signs
as the same, like HTML forms do. If you need spaces to be represented as
plus signs, use actual plus signs.
\sa queryItems(), isEmpty()
*/
void QUrlQuery::setQueryItems(const QList<QPair<QString, QString> > &query)
{
clear();
if (query.isEmpty())
return;
QUrlQueryPrivate *dd = d;
QList<QPair<QString, QString> >::const_iterator it = query.constBegin(),
end = query.constEnd();
for ( ; it != end; ++it)
dd->addQueryItem(it->first, it->second);
}
/*!
Returns the query string of the URL, as a map of keys and values, using the
options specified in \a encoding to encode the items. The order of the
elements is the same as the one found in the query string or set with
setQueryItems().
\sa setQueryItems(), \l{#Encoding}{Encoding}
*/
QList<QPair<QString, QString> > QUrlQuery::queryItems(QUrl::ComponentFormattingOptions encoding) const
{
if (!d)
return QList<QPair<QString, QString> >();
if (idempotentRecodeToUser(encoding))
return d->itemList;
QList<QPair<QString, QString> > result;
Map::const_iterator it = d->itemList.constBegin();
Map::const_iterator end = d->itemList.constEnd();
for ( ; it != end; ++it)
result << qMakePair(d->recodeToUser(it->first, encoding),
d->recodeToUser(it->second, encoding));
return result;
}
/*!
Returns true if there is a query string pair whose key is equal
to \a key from the URL.
\sa addQueryItem(), queryItemValue()
*/
bool QUrlQuery::hasQueryItem(const QString &key) const
{
if (!d)
return false;
return d->findKey(key) != d->itemList.constEnd();
}
/*!
Appends the pair \a key = \a value to the end of the query string of the
URL. This method does not overwrite existing items that might exist with
the same key.
\note This method does not treat spaces (ASCII 0x20) and plus ("+") signs
as the same, like HTML forms do. If you need spaces to be represented as
plus signs, use actual plus signs.
\sa hasQueryItem(), queryItemValue()
*/
void QUrlQuery::addQueryItem(const QString &key, const QString &value)
{
d->addQueryItem(key, value);
}
/*!
Returns the query value associated with key \a key from the URL, using the
options specified in \a encoding to encode the return value. If the key \a
key is not found, this function returns an empty string. If you need to
distinguish between an empty value and a non-existent key, you should check
for the key's presence first using hasQueryItem().
If the key \a key is multiply defined, this function will return the first
one found, in the order they were present in the query string or added
using addQueryItem().
\sa addQueryItem(), allQueryItemValues(), \l{#Encoding}{Encoding}
*/
QString QUrlQuery::queryItemValue(const QString &key, QUrl::ComponentFormattingOptions encoding) const
{
QString result;
if (d) {
Map::const_iterator it = d->findKey(key);
if (it != d->itemList.constEnd())
result = d->recodeToUser(it->second, encoding);
}
return result;
}
/*!
Returns the a list of query string values whose key is equal to \a key from
the URL, using the options specified in \a encoding to encode the return
value. If the key \a key is not found, this function returns an empty list.
\sa queryItemValue(), addQueryItem()
*/
QStringList QUrlQuery::allQueryItemValues(const QString &key, QUrl::ComponentFormattingOptions encoding) const
{
QStringList result;
if (d) {
QString encodedKey = d->recodeFromUser(key);
int idx = d->findRecodedKey(encodedKey);
while (idx < d->itemList.size()) {
result << d->recodeToUser(d->itemList.at(idx).second, encoding);
idx = d->findRecodedKey(encodedKey, idx + 1);
}
}
return result;
}
/*!
Removes the query string pair whose key is equal to \a key from the URL. If
there are multiple items with a key equal to \a key, it removes the first
item in the order they were present in the query string or added with
addQueryItem().
\sa removeAllQueryItems()
*/
void QUrlQuery::removeQueryItem(const QString &key)
{
if (d) {
Map::iterator it = d->findKey(key);
if (it != d->itemList.end())
d->itemList.erase(it);
}
}
/*!
Removes all the query string pairs whose key is equal to \a key
from the URL.
\sa removeQueryItem()
*/
void QUrlQuery::removeAllQueryItems(const QString &key)
{
if (d.constData()) {
QString encodedKey = d->recodeFromUser(key);
Map::iterator it = d->itemList.begin();
while (it != d->itemList.end()) {
if (it->first == encodedKey)
it = d->itemList.erase(it);
else
++it;
}
}
}
/*!
\fn QChar QUrlQuery::defaultQueryValueDelimiter()
Returns the default character for separating keys from values in the query,
an equal sign ("=").
\sa setQueryDelimiters(), queryValueDelimiter(), defaultQueryPairDelimiter()
*/
/*!
\fn QChar QUrlQuery::defaultQueryPairDelimiter()
Returns the default character for separating keys-value pairs from each
other, an ampersand ("&").
\sa setQueryDelimiters(), queryPairDelimiter(), defaultQueryValueDelimiter()
*/
QT_END_NAMESPACE

179
src/corelib/io/qurlquery.h Normal file
View File

@ -0,0 +1,179 @@
/****************************************************************************
**
** Copyright (C) 2012 Intel Corporation.
** Contact: http://www.qt-project.org/
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** 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.
**
** 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.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QURLQUERY_H
#define QURLQUERY_H
#include <QtCore/qpair.h>
#include <QtCore/qshareddata.h>
#include <QtCore/qurl.h>
#if QT_DEPRECATED_SINCE(5,0)
#include <QtCore/qstringlist.h>
#endif
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class QUrlQueryPrivate;
class Q_CORE_EXPORT QUrlQuery
{
public:
QUrlQuery();
explicit QUrlQuery(const QUrl &url);
explicit QUrlQuery(const QString &queryString);
QUrlQuery(const QUrlQuery &other);
QUrlQuery &operator=(const QUrlQuery &other);
#ifdef Q_COMPILER_RVALUE_REFS
QUrlQuery &operator=(QUrlQuery &&other)
{ qSwap(d, other.d); return *this; }
#endif
~QUrlQuery();
bool operator==(const QUrlQuery &other) const;
bool operator!=(const QUrlQuery &other) const
{ return !(*this == other); }
void swap(QUrlQuery &other) { qSwap(d, other.d); }
bool isEmpty() const;
bool isDetached() const;
void clear();
QString query(QUrl::ComponentFormattingOptions encoding = QUrl::PrettyDecoded) const;
void setQuery(const QString &queryString);
QString toString(QUrl::ComponentFormattingOptions encoding = QUrl::PrettyDecoded) const
{ return query(encoding); }
void setQueryDelimiters(QChar valueDelimiter, QChar pairDelimiter);
QChar queryValueDelimiter() const;
QChar queryPairDelimiter() const;
void setQueryItems(const QList<QPair<QString, QString> > &query);
QList<QPair<QString, QString> > queryItems(QUrl::ComponentFormattingOptions encoding = QUrl::PrettyDecoded) const;
bool hasQueryItem(const QString &key) const;
void addQueryItem(const QString &key, const QString &value);
void removeQueryItem(const QString &key);
QString queryItemValue(const QString &key, QUrl::ComponentFormattingOptions encoding = QUrl::PrettyDecoded) const;
QStringList allQueryItemValues(const QString &key, QUrl::ComponentFormattingOptions encoding = QUrl::PrettyDecoded) const;
void removeAllQueryItems(const QString &key);
static QChar defaultQueryValueDelimiter()
{ return QChar(ushort('=')); }
static QChar defaultQueryPairDelimiter()
{ return QChar(ushort('&')); }
private:
friend class QUrl;
QSharedDataPointer<QUrlQueryPrivate> d;
public:
typedef QSharedDataPointer<QUrlQueryPrivate> DataPtr;
inline DataPtr &data_ptr() { return d; }
};
Q_DECLARE_TYPEINFO(QUrlQuery, Q_MOVABLE_TYPE);
Q_DECLARE_SHARED(QUrlQuery)
#if QT_DEPRECATED_SINCE(5,0)
inline void QUrl::setQueryItems(const QList<QPair<QString, QString> > &qry)
{ QUrlQuery q(*this); q.setQueryItems(qry); setQuery(q); }
inline void QUrl::addQueryItem(const QString &key, const QString &value)
{ QUrlQuery q(*this); q.addQueryItem(key, value); setQuery(q); }
inline QList<QPair<QString, QString> > QUrl::queryItems() const
{ return QUrlQuery(*this).queryItems(); }
inline bool QUrl::hasQueryItem(const QString &key) const
{ return QUrlQuery(*this).hasQueryItem(key); }
inline QString QUrl::queryItemValue(const QString &key) const
{ return QUrlQuery(*this).queryItemValue(key); }
inline QStringList QUrl::allQueryItemValues(const QString &key) const
{ return QUrlQuery(*this).allQueryItemValues(key); }
inline void QUrl::removeQueryItem(const QString &key)
{ QUrlQuery q(*this); q.removeQueryItem(key); setQuery(q); }
inline void QUrl::removeAllQueryItems(const QString &key)
{ QUrlQuery q(*this); q.removeAllQueryItems(key); }
inline void QUrl::addEncodedQueryItem(const QByteArray &key, const QByteArray &value)
{ QUrlQuery q(*this); q.addQueryItem(QString::fromUtf8(key), QString::fromUtf8(value)); setQuery(q); }
inline bool QUrl::hasEncodedQueryItem(const QByteArray &key) const
{ return QUrlQuery(*this).hasQueryItem(QString::fromUtf8(key)); }
inline QByteArray QUrl::encodedQueryItemValue(const QByteArray &key) const
{ return QUrlQuery(*this).queryItemValue(QString::fromUtf8(key), QUrl::FullyEncoded).toLatin1(); }
inline void QUrl::removeEncodedQueryItem(const QByteArray &key)
{ QUrlQuery q(*this); q.removeQueryItem(QString::fromUtf8(key)); setQuery(q); }
inline void QUrl::removeAllEncodedQueryItems(const QByteArray &key)
{ QUrlQuery q(*this); q.removeAllQueryItems(QString::fromUtf8(key)); }
inline void QUrl::setEncodedQueryItems(const QList<QPair<QByteArray, QByteArray> > &qry)
{
QUrlQuery q(*this);
QList<QPair<QByteArray, QByteArray> >::ConstIterator it = qry.constBegin();
for ( ; it != qry.constEnd(); ++it)
q.addQueryItem(QString::fromUtf8(it->first), QString::fromUtf8(it->second));
setQuery(q);
}
inline QList<QPair<QByteArray, QByteArray> > QUrl::encodedQueryItems() const
{
QList<QPair<QString, QString> > items = QUrlQuery(*this).queryItems(QUrl::FullyEncoded);
QList<QPair<QString, QString> >::ConstIterator it = items.constBegin();
QList<QPair<QByteArray, QByteArray> > result;
result.reserve(items.size());
for ( ; it != items.constEnd(); ++it)
result << qMakePair(it->first.toLatin1(), it->second.toLatin1());
return result;
}
inline QList<QByteArray> QUrl::allEncodedQueryItemValues(const QByteArray &key) const
{
QStringList items = QUrlQuery(*this).allQueryItemValues(QString::fromUtf8(key), QUrl::FullyEncoded);
QList<QByteArray> result;
result.reserve(items.size());
Q_FOREACH (const QString &item, items)
result << item.toLatin1();
return result;
}
#endif
QT_END_NAMESPACE
QT_END_HEADER
#endif // QURLQUERY_H

View File

@ -0,0 +1,644 @@
/****************************************************************************
**
** Copyright (C) 2012 Intel Corporation
** Contact: http://www.qt-project.org/
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** 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.
**
** 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.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qurl.h"
QT_BEGIN_NAMESPACE
// ### move to qurl_p.h
enum EncodingAction {
DecodeCharacter = 0,
LeaveCharacter = 1,
EncodeCharacter = 2
};
// From RFC 3896, Appendix A Collected ABNF for URI
// unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
// reserved = gen-delims / sub-delims
// gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
// sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
// / "*" / "+" / "," / ";" / "="
static const uchar defaultActionTable[96] = {
2, // space
1, // '!' (sub-delim)
2, // '"'
1, // '#' (gen-delim)
1, // '$' (gen-delim)
2, // '%' (percent)
1, // '&' (gen-delim)
1, // "'" (sub-delim)
1, // '(' (sub-delim)
1, // ')' (sub-delim)
1, // '*' (sub-delim)
1, // '+' (sub-delim)
1, // ',' (sub-delim)
0, // '-' (unreserved)
0, // '.' (unreserved)
1, // '/' (gen-delim)
0, 0, 0, 0, 0, // '0' to '4' (unreserved)
0, 0, 0, 0, 0, // '5' to '9' (unreserved)
1, // ':' (gen-delim)
1, // ';' (sub-delim)
2, // '<'
1, // '=' (sub-delim)
2, // '>'
1, // '?' (gen-delim)
1, // '@' (gen-delim)
0, 0, 0, 0, 0, // 'A' to 'E' (unreserved)
0, 0, 0, 0, 0, // 'F' to 'J' (unreserved)
0, 0, 0, 0, 0, // 'K' to 'O' (unreserved)
0, 0, 0, 0, 0, // 'P' to 'T' (unreserved)
0, 0, 0, 0, 0, 0, // 'U' to 'Z' (unreserved)
1, // '[' (gen-delim)
2, // '\'
1, // ']' (gen-delim)
2, // '^'
0, // '_' (unreserved)
2, // '`'
0, 0, 0, 0, 0, // 'a' to 'e' (unreserved)
0, 0, 0, 0, 0, // 'f' to 'j' (unreserved)
0, 0, 0, 0, 0, // 'k' to 'o' (unreserved)
0, 0, 0, 0, 0, // 'p' to 't' (unreserved)
0, 0, 0, 0, 0, 0, // 'u' to 'z' (unreserved)
2, // '{'
2, // '|'
2, // '}'
0, // '~' (unreserved)
2 // BSKP
};
// mask tables, in negative polarity
// 0x00 if it belongs to this category
// 0xff if it doesn't
static const uchar delimsMask[96] = {
0xff, // space
0x00, // '!' (sub-delim)
0xff, // '"'
0x00, // '#' (gen-delim)
0x00, // '$' (gen-delim)
0xff, // '%' (percent)
0x00, // '&' (gen-delim)
0x00, // "'" (sub-delim)
0x00, // '(' (sub-delim)
0x00, // ')' (sub-delim)
0x00, // '*' (sub-delim)
0x00, // '+' (sub-delim)
0x00, // ',' (sub-delim)
0xff, // '-' (unreserved)
0xff, // '.' (unreserved)
0x00, // '/' (gen-delim)
0xff, 0xff, 0xff, 0xff, 0xff, // '0' to '4' (unreserved)
0xff, 0xff, 0xff, 0xff, 0xff, // '5' to '9' (unreserved)
0x00, // ':' (gen-delim)
0x00, // ';' (sub-delim)
0xff, // '<'
0x00, // '=' (sub-delim)
0xff, // '>'
0x00, // '?' (gen-delim)
0x00, // '@' (gen-delim)
0xff, 0xff, 0xff, 0xff, 0xff, // 'A' to 'E' (unreserved)
0xff, 0xff, 0xff, 0xff, 0xff, // 'F' to 'J' (unreserved)
0xff, 0xff, 0xff, 0xff, 0xff, // 'K' to 'O' (unreserved)
0xff, 0xff, 0xff, 0xff, 0xff, // 'P' to 'T' (unreserved)
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 'U' to 'Z' (unreserved)
0x00, // '[' (gen-delim)
0xff, // '\'
0x00, // ']' (gen-delim)
0xff, // '^'
0xff, // '_' (unreserved)
0xff, // '`'
0xff, 0xff, 0xff, 0xff, 0xff, // 'a' to 'e' (unreserved)
0xff, 0xff, 0xff, 0xff, 0xff, // 'f' to 'j' (unreserved)
0xff, 0xff, 0xff, 0xff, 0xff, // 'k' to 'o' (unreserved)
0xff, 0xff, 0xff, 0xff, 0xff, // 'p' to 't' (unreserved)
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 'u' to 'z' (unreserved)
0xff, // '{'
0xff, // '|'
0xff, // '}'
0xff, // '~' (unreserved)
0xff // BSKP
};
static const uchar reservedMask[96] = {
0xff, // space
0xff, // '!' (sub-delim)
0x00, // '"'
0xff, // '#' (gen-delim)
0xff, // '$' (gen-delim)
0xff, // '%' (percent)
0xff, // '&' (gen-delim)
0xff, // "'" (sub-delim)
0xff, // '(' (sub-delim)
0xff, // ')' (sub-delim)
0xff, // '*' (sub-delim)
0xff, // '+' (sub-delim)
0xff, // ',' (sub-delim)
0xff, // '-' (unreserved)
0xff, // '.' (unreserved)
0xff, // '/' (gen-delim)
0xff, 0xff, 0xff, 0xff, 0xff, // '0' to '4' (unreserved)
0xff, 0xff, 0xff, 0xff, 0xff, // '5' to '9' (unreserved)
0xff, // ':' (gen-delim)
0xff, // ';' (sub-delim)
0x00, // '<'
0xff, // '=' (sub-delim)
0x00, // '>'
0xff, // '?' (gen-delim)
0xff, // '@' (gen-delim)
0xff, 0xff, 0xff, 0xff, 0xff, // 'A' to 'E' (unreserved)
0xff, 0xff, 0xff, 0xff, 0xff, // 'F' to 'J' (unreserved)
0xff, 0xff, 0xff, 0xff, 0xff, // 'K' to 'O' (unreserved)
0xff, 0xff, 0xff, 0xff, 0xff, // 'P' to 'T' (unreserved)
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 'U' to 'Z' (unreserved)
0xff, // '[' (gen-delim)
0x00, // '\'
0xff, // ']' (gen-delim)
0x00, // '^'
0xff, // '_' (unreserved)
0x00, // '`'
0xff, 0xff, 0xff, 0xff, 0xff, // 'a' to 'e' (unreserved)
0xff, 0xff, 0xff, 0xff, 0xff, // 'f' to 'j' (unreserved)
0xff, 0xff, 0xff, 0xff, 0xff, // 'k' to 'o' (unreserved)
0xff, 0xff, 0xff, 0xff, 0xff, // 'p' to 't' (unreserved)
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 'u' to 'z' (unreserved)
0x00, // '{'
0x00, // '|'
0x00, // '}'
0xff, // '~' (unreserved)
0xff // BSKP
};
static inline bool isHex(ushort c)
{
return (c >= 'a' && c <= 'f') ||
(c >= 'A' && c <= 'F') ||
(c >= '0' && c <= '9');
}
static inline bool isUpperHex(ushort c)
{
// undefined behaviour if c isn't an hex char!
return c < 0x60;
}
static inline ushort toUpperHex(ushort c)
{
return isUpperHex(c) ? c : c - 0x20;
}
static inline ushort decodeNibble(ushort c)
{
return c >= 'a' ? c - 'a' + 0xA :
c >= 'A' ? c - 'A' + 0xA : c - '0';
}
// if the sequence at input is 2*HEXDIG, returns its decoding
// returns -1 if it isn't.
// assumes that the range has been checked already
static inline ushort decodePercentEncoding(const ushort *input)
{
ushort c1 = input[1];
ushort c2 = input[2];
if (!isHex(c1) || !isHex(c2))
return ushort(-1);
return decodeNibble(c1) << 4 | decodeNibble(c2);
}
static inline ushort encodeNibble(ushort c)
{
static const uchar hexnumbers[] = "0123456789ABCDEF";
return hexnumbers[c & 0xf];
}
static void ensureDetached(QString &result, ushort *&output, const ushort *begin, const ushort *input, const ushort *end,
int add = 0)
{
if (!output) {
// now detach
// create enough space if the rest of the string needed to be percent-encoded
int charsProcessed = input - begin;
int charsRemaining = end - input;
int spaceNeeded = end - begin + 2 * charsRemaining + add;
int origSize = result.size();
result.resize(origSize + spaceNeeded);
// we know that resize() above detached, so we bypass the reference count check
output = const_cast<ushort *>(reinterpret_cast<const ushort *>(result.constData()))
+ origSize;
// copy the chars we've already processed
int i;
for (i = 0; i < charsProcessed; ++i)
output[i] = begin[i];
output += i;
}
}
static inline bool isUnicodeNonCharacter(uint ucs4)
{
// Unicode has a couple of "non-characters" that one can use internally,
// but are not allowed to be used for text interchange.
//
// Those are the last two entries each Unicode Plane (U+FFFE, U+FFFF,
// U+1FFFE, U+1FFFF, etc.) as well as the entries between U+FDD0 and
// U+FDEF (inclusive)
return (ucs4 & 0xfffe) == 0xfffe
|| (ucs4 - 0xfdd0U) < 16;
}
// returns true if we performed an UTF-8 decoding
static bool encodedUtf8ToUtf16(QString &result, ushort *&output, const ushort *begin, const ushort *&input,
const ushort *end, ushort decoded)
{
int charsNeeded;
uint min_uc;
uint uc;
if (decoded <= 0xC1) {
// an UTF-8 first character must be at least 0xC0
// however, all 0xC0 and 0xC1 first bytes can only produce overlong sequences
return false;
} else if (decoded < 0xe0) {
charsNeeded = 2;
min_uc = 0x80;
uc = decoded & 0x1f;
} else if (decoded < 0xf0) {
charsNeeded = 3;
min_uc = 0x800;
uc = decoded & 0x0f;
} else if (decoded < 0xf5) {
charsNeeded = 4;
min_uc = 0x10000;
uc = decoded & 0x07;
} else {
// the last Unicode character is U+10FFFF
// it's encoded in UTF-8 as "\xF4\x8F\xBF\xBF"
// therefore, a byte higher than 0xF4 is not the UTF-8 first byte
return false;
}
// are there enough remaining?
if (end - input < 3*charsNeeded)
return false;
if (input[3] != '%')
return false;
// first continuation character
decoded = decodePercentEncoding(input + 3);
if ((decoded & 0xc0) != 0x80)
return false;
uc <<= 6;
uc |= decoded & 0x3f;
if (charsNeeded > 2) {
if (input[6] != '%')
return false;
// second continuation character
decoded = decodePercentEncoding(input + 6);
if ((decoded & 0xc0) != 0x80)
return false;
uc <<= 6;
uc |= decoded & 0x3f;
if (charsNeeded > 3) {
if (input[9] != '%')
return false;
// third continuation character
decoded = decodePercentEncoding(input + 9);
if ((decoded & 0xc0) != 0x80)
return false;
uc <<= 6;
uc |= decoded & 0x3f;
}
}
// we've decoded something; safety-check it
if (uc < min_uc)
return false;
if (isUnicodeNonCharacter(uc) || (uc >= 0xD800 && uc <= 0xDFFF) || uc >= 0x110000)
return false;
if (!QChar::requiresSurrogates(uc)) {
// UTF-8 decoded and no surrogates are required
// detach if necessary
ensureDetached(result, output, begin, input, end, -9 * charsNeeded + 1);
*output++ = uc;
} else {
// UTF-8 decoded to something that requires a surrogate pair
ensureDetached(result, output, begin, input, end, -9 * charsNeeded + 2);
*output++ = QChar::highSurrogate(uc);
*output++ = QChar::lowSurrogate(uc);
}
input += charsNeeded * 3 - 1;
return true;
}
static void unicodeToEncodedUtf8(QString &result, ushort *&output, const ushort *begin,
const ushort *&input, const ushort *end, ushort decoded)
{
uint uc = decoded;
if (QChar::isHighSurrogate(uc)) {
if (input < end && QChar::isLowSurrogate(input[1]))
uc = QChar::surrogateToUcs4(uc, input[1]);
}
// note: we will encode bad UTF-16 to UTF-8
// but they don't get decoded back
// calculate the utf8 length
int utf8len = uc >= 0x10000 ? 4 : uc >= 0x800 ? 3 : 2;
// detach
if (!output) {
// we need 3 * utf8len for the encoded UTF-8 sequence
// but ensureDetached already adds 3 for the char we're processing
ensureDetached(result, output, begin, input, end, 3*utf8len - 3);
} else {
// verify that there's enough space or expand
int charsRemaining = end - input - 1; // not including this one
int pos = output - reinterpret_cast<const ushort *>(result.constData());
int spaceRemaining = result.size() - pos;
if (spaceRemaining < 3*charsRemaining + 3*utf8len) {
// must resize
result.resize(result.size() + 3*utf8len);
// we know that resize() above detached, so we bypass the reference count check
output = const_cast<ushort *>(reinterpret_cast<const ushort *>(result.constData()));
output += pos;
}
}
// write the sequence
if (uc < 0x800) {
// first of two bytes
uchar c = 0xc0 | uchar(uc >> 6);
*output++ = '%';
*output++ = encodeNibble(c >> 4);
*output++ = encodeNibble(c & 0xf);
} else {
uchar c;
if (uc > 0xFFFF) {
// first two of four bytes
c = 0xf0 | uchar(uc >> 18);
*output++ = '%';
*output++ = 'F';
*output++ = encodeNibble(c & 0xf);
// continuation byte
c = 0x80 | (uchar(uc >> 12) & 0x3f);
*output++ = '%';
*output++ = encodeNibble(c >> 4);
*output++ = encodeNibble(c & 0xf);
// this was a surrogate pair
++input;
} else {
// first of three bytes
c = 0xe0 | uchar(uc >> 12);
*output++ = '%';
*output++ = 'E';
*output++ = encodeNibble(c & 0xf);
}
// continuation byte
c = 0x80 | (uchar(uc >> 6) & 0x3f);
*output++ = '%';
*output++ = encodeNibble(c >> 4);
*output++ = encodeNibble(c & 0xf);
}
// continuation byte
uchar c = 0x80 | (uc & 0x3f);
*output++ = '%';
*output++ = encodeNibble(c >> 4);
*output++ = encodeNibble(c & 0xf);
}
static int recode(QString &result, const ushort *begin, const ushort *end, QUrl::ComponentFormattingOptions encoding,
const uchar *actionTable, bool retryBadEncoding)
{
const int origSize = result.size();
const ushort *input = begin;
ushort *output = 0;
for ( ; input != end; ++input) {
register ushort c;
EncodingAction action;
// try a run where no change is necessary
for ( ; input != end; ++input) {
c = *input;
if (c < 0x20U || c >= 0x80U) // also: (c - 0x20 < 0x60U)
goto non_trivial;
action = EncodingAction(actionTable[c - ' ']);
if (action == EncodeCharacter)
goto non_trivial;
if (output)
*output++ = c;
}
break;
non_trivial:
register uint decoded;
if (c == '%' && retryBadEncoding) {
// always write "%25"
ensureDetached(result, output, begin, input, end);
*output++ = '%';
*output++ = '2';
*output++ = '5';
continue;
} else if (c == '%') {
// check if the input is valid
if (input + 2 >= end || (decoded = decodePercentEncoding(input)) == ushort(-1)) {
// not valid, retry
result.resize(origSize);
return recode(result, begin, end, encoding, actionTable, true);
}
if (decoded >= 0x80) {
// decode the UTF-8 sequence
if (!(encoding & QUrl::EncodeUnicode) &&
encodedUtf8ToUtf16(result, output, begin, input, end, decoded))
continue;
// decoding the encoded UTF-8 failed
action = LeaveCharacter;
} else if (decoded >= 0x20) {
action = EncodingAction(actionTable[decoded - ' ']);
}
} else {
decoded = c;
if (decoded >= 0x80 && encoding & QUrl::EncodeUnicode) {
// encode the UTF-8 sequence
unicodeToEncodedUtf8(result, output, begin, input, end, decoded);
continue;
} else if (decoded >= 0x80) {
if (output)
*output++ = c;
continue;
}
}
if (decoded < 0x20)
action = EncodeCharacter;
// there are six possibilities:
// current \ action | DecodeCharacter | LeaveCharacter | EncodeCharacter
// decoded | 1:leave | 2:leave | 3:encode
// encoded | 4:decode | 5:leave | 6:leave
// cases 1 and 2 were handled before this section
if (c == '%' && action != DecodeCharacter) {
// cases 5 and 6: it's encoded and we're leaving it as it is
// except we're pedantic and we'll uppercase the hex
if (output || !isUpperHex(input[1]) || !isUpperHex(input[2])) {
ensureDetached(result, output, begin, input, end);
*output++ = '%';
*output++ = toUpperHex(*++input);
*output++ = toUpperHex(*++input);
}
} else if (c == '%' && action == DecodeCharacter) {
// case 4: we need to decode
ensureDetached(result, output, begin, input, end);
*output++ = decoded;
input += 2;
} else {
// must be case 3: we need to encode
ensureDetached(result, output, begin, input, end);
*output++ = '%';
*output++ = encodeNibble(c >> 4);
*output++ = encodeNibble(c & 0xf);
}
}
if (output) {
int len = output - reinterpret_cast<const ushort *>(result.constData());
result.truncate(len);
return len - origSize;
}
return 0;
}
template <size_t N>
static void maskTable(uchar (&table)[N], const uchar (&mask)[N])
{
for (size_t i = 0; i < N; ++i)
table[i] &= mask[i];
}
/*!
\internal
Recodes the string from \a begin to \a end. If any transformations are
done, append them to \a appendTo and return the number of characters added.
If no transformations were required, return 0.
The \a encoding option modifies the default behaviour:
\list
\li QUrl::EncodeDelimiters: if set, delimiters will be left untransformed (note: not encoded!);
if unset, delimiters will be decoded
\li QUrl::DecodeReserved: if set, reserved characters will be decoded;
if unset, reserved characters will be encoded
\li QUrl::EncodeSpaces: if set, spaces will be encoded to "%20"; if unset, they will be " "
\li QUrl::EncodeUnicode: if set, characters above U+0080 will be encoded to their UTF-8
percent-encoded form; if unset, they will be decoded to UTF-16
\endlist
Other flags are ignored (including QUrl::EncodeReserved).
The \a tableModifications argument can be used to supply extra
modifications to the tables, to be applied after the flags above are
handled. It consists of a sequence of 16-bit values, where the low 8 bits
indicate the character in question and the high 8 bits are either \c
EncodeCharacter, \c LeaveCharacter or \c DecodeCharacter.
*/
Q_AUTOTEST_EXPORT int
qt_urlRecode(QString &appendTo, const QChar *begin, const QChar *end,
QUrl::ComponentFormattingOptions encoding, const ushort *tableModifications)
{
uchar actionTable[sizeof defaultActionTable];
if (!(encoding & QUrl::EncodeDelimiters) && encoding & QUrl::DecodeReserved) {
// reset the table
memset(actionTable, DecodeCharacter, sizeof actionTable);
if (encoding & QUrl::EncodeSpaces)
actionTable[0] = EncodeCharacter;
// these are always encoded
actionTable['%' - ' '] = EncodeCharacter;
actionTable[0x7F - ' '] = EncodeCharacter;
} else {
memcpy(actionTable, defaultActionTable, sizeof actionTable);
if (!(encoding & QUrl::EncodeDelimiters))
maskTable(actionTable, delimsMask);
if (encoding & QUrl::DecodeReserved)
maskTable(actionTable, reservedMask);
if (!(encoding & QUrl::EncodeSpaces))
actionTable[0] = DecodeCharacter; // decode
}
if (tableModifications) {
for (const ushort *p = tableModifications; *p; ++p)
actionTable[uchar(*p) - ' '] = *p >> 8;
}
return recode(appendTo, reinterpret_cast<const ushort *>(begin), reinterpret_cast<const ushort *>(end),
encoding, actionTable, false);
}
QT_END_NAMESPACE

View File

@ -2096,7 +2096,9 @@ QModelIndex QAbstractItemModel::buddy(const QModelIndex &index) const
Returns a list of indexes for the items in the column of the \a start index
where data stored under the given \a role matches the specified \a value.
The way the search is performed is defined by the \a flags given. The list
that is returned may be empty.
that is returned may be empty. Note also that the order of results in the
list may not correspond to the order in the model, if for example a proxy
model is used. The order of the results can not be relied upon.
The search begins from the \a start index, and continues until the number
of matching data items equals \a hits, the search reaches the last row, or

View File

@ -59,7 +59,7 @@ class Q_CORE_EXPORT QAbstractProxyModel : public QAbstractItemModel
Q_OBJECT
public:
QAbstractProxyModel(QObject *parent = 0);
explicit QAbstractProxyModel(QObject *parent = 0);
~QAbstractProxyModel();
virtual void setSourceModel(QAbstractItemModel *sourceModel);

View File

@ -235,7 +235,7 @@ bool QItemSelectionRange::intersects(const QItemSelectionRange &other) const
both the selection range and the \a other selection range.
*/
QItemSelectionRange QItemSelectionRange::intersect(const QItemSelectionRange &other) const
QItemSelectionRange QItemSelectionRange::intersected(const QItemSelectionRange &other) const
{
if (model() == other.model() && parent() == other.parent()) {
QModelIndex topLeft = model()->index(qMax(top(), other.top()),

View File

@ -92,9 +92,12 @@ public:
}
bool intersects(const QItemSelectionRange &other) const;
QItemSelectionRange intersect(const QItemSelectionRange &other) const; // ### Qt 5: make QT4_SUPPORT
inline QItemSelectionRange intersected(const QItemSelectionRange &other) const
{ return intersect(other); }
#if QT_DEPRECATED_SINCE(5, 0)
inline QItemSelectionRange intersect(const QItemSelectionRange &other) const
{ return intersected(other); }
#endif
QItemSelectionRange intersected(const QItemSelectionRange &other) const;
inline bool operator==(const QItemSelectionRange &other) const
{ return (tl == other.tl && br == other.br); }

View File

@ -73,7 +73,7 @@ class Q_CORE_EXPORT QSortFilterProxyModel : public QAbstractProxyModel
Q_PROPERTY(int filterRole READ filterRole WRITE setFilterRole)
public:
QSortFilterProxyModel(QObject *parent = 0);
explicit QSortFilterProxyModel(QObject *parent = 0);
~QSortFilterProxyModel();
void setSourceModel(QAbstractItemModel *sourceModel);

View File

@ -57,7 +57,7 @@ class Q_CORE_EXPORT QStringListModel : public QAbstractListModel
Q_OBJECT
public:
explicit QStringListModel(QObject *parent = 0);
QStringListModel(const QStringList &strings, QObject *parent = 0);
explicit QStringListModel(const QStringList &strings, QObject *parent = 0);
int rowCount(const QModelIndex &parent = QModelIndex()) const;

View File

@ -400,7 +400,8 @@ QString QJsonValue::toString() const
if (t != String)
return QString();
stringData->ref.ref(); // the constructor below doesn't add a ref.
return QString(*(const QConstStringData<1> *)stringData);
QStringDataPtr holder = { stringData };
return QString(holder);
}
/*!

View File

@ -295,6 +295,16 @@ int QAbstractEventDispatcher::registerTimer(int interval, Qt::TimerType timerTyp
\sa Qt::TimerType
*/
/*!
\fn int QAbstractEventDispatcher::remainingTime(int timerId)
Returns the remaining time in milliseconds with the given \a timerId.
If the timer is inactive, the returned value will be -1. If the timer is
overdue, the returned value will be 0.
\sa Qt::TimerType
*/
/*! \fn void QAbstractEventDispatcher::wakeUp()
\threadsafe

View File

@ -93,6 +93,8 @@ public:
virtual bool unregisterTimers(QObject *object) = 0;
virtual QList<TimerInfo> registeredTimers(QObject *object) const = 0;
virtual int remainingTime(int timerId) = 0;
virtual void wakeUp() = 0;
virtual void interrupt() = 0;
virtual void flush() = 0;

View File

@ -1513,26 +1513,29 @@ void QCoreApplication::quit()
generated by \l{Qt Designer} provide a \c retranslateUi() function that can be
called.
The function returns true on success and false on failure.
\sa removeTranslator() translate() QTranslator::load() {Dynamic Translation}
*/
void QCoreApplication::installTranslator(QTranslator *translationFile)
bool QCoreApplication::installTranslator(QTranslator *translationFile)
{
if (!translationFile)
return;
return false;
if (!QCoreApplicationPrivate::checkInstance("installTranslator"))
return;
return false;
QCoreApplicationPrivate *d = self->d_func();
d->translators.prepend(translationFile);
#ifndef QT_NO_TRANSLATION_BUILDER
if (translationFile->isEmpty())
return;
return false;
#endif
QEvent ev(QEvent::LanguageChange);
QCoreApplication::sendEvent(self, &ev);
return true;
}
/*!
@ -1540,20 +1543,24 @@ void QCoreApplication::installTranslator(QTranslator *translationFile)
translation files used by this application. (It does not delete the
translation file from the file system.)
The function returns true on success and false on failure.
\sa installTranslator() translate(), QObject::tr()
*/
void QCoreApplication::removeTranslator(QTranslator *translationFile)
bool QCoreApplication::removeTranslator(QTranslator *translationFile)
{
if (!translationFile)
return;
return false;
if (!QCoreApplicationPrivate::checkInstance("removeTranslator"))
return;
return false;
QCoreApplicationPrivate *d = self->d_func();
if (d->translators.removeAll(translationFile) && !self->closingDown()) {
QEvent ev(QEvent::LanguageChange);
QCoreApplication::sendEvent(self, &ev);
return true;
}
return false;
}
static void replacePercentN(QString *result, int n)

View File

@ -134,8 +134,8 @@ public:
#endif // QT_NO_LIBRARY
#ifndef QT_NO_TRANSLATION
static void installTranslator(QTranslator * messageFile);
static void removeTranslator(QTranslator * messageFile);
static bool installTranslator(QTranslator * messageFile);
static bool removeTranslator(QTranslator * messageFile);
#endif
enum Encoding { UnicodeUTF8, Latin1, DefaultCodec = Latin1
#if QT_DEPRECATED_SINCE(5, 0)

View File

@ -170,7 +170,6 @@ QT_BEGIN_NAMESPACE
\value NonClientAreaMouseButtonRelease A mouse button release occurred outside the client area.
\value NonClientAreaMouseMove A mouse move occurred outside the client area.
\value MacSizeChange The user changed his widget sizes (Mac OS X only).
\value MenubarUpdated The window's menu bar has been updated.
\value MetaCall An asynchronous method invocation via QMetaObject::invokeMethod().
\value ModifiedChange Widgets modification state has been changed.
\value MouseButtonDblClick Mouse press again (QMouseEvent).

View File

@ -192,9 +192,6 @@ public:
#endif
AcceptDropsChange = 152,
MenubarUpdated = 153, // Support event for Q3MainWindow, which needs to
// knwow when QMenubar is updated.
ZeroTimerEvent = 154, // Used for Windows Zero timer events
GraphicsSceneMouseMove = 155, // GraphicsView
@ -269,17 +266,14 @@ public:
ScrollPrepare = 204,
Scroll = 205,
Map = 206,
Unmap = 207,
Expose = 206,
Expose = 208,
InputMethodQuery = 207,
OrientationChange = 208, // Screen orientation has changed
InputMethodQuery = 209,
OrientationChange = 210, // Screen orientation has changed
TouchCancel = 209,
TouchCancel = 211,
ThemeChange = 212,
ThemeChange = 210,
// 512 reserved for Qt Jambi's MetaCall event
// 513 reserved for Qt Jambi's DeleteOnMainThread event

View File

@ -567,6 +567,19 @@ QList<QEventDispatcherGlib::TimerInfo> QEventDispatcherGlib::registeredTimers(QO
return d->timerSource->timerList.registeredTimers(object);
}
int QEventDispatcherGlib::remainingTime(int timerId)
{
#ifndef QT_NO_DEBUG
if (timerId < 1) {
qWarning("QEventDispatcherGlib::remainingTimeTime: invalid argument");
return -1;
}
#endif
Q_D(QEventDispatcherGlib);
return d->timerSource->timerList.timerRemainingTime(timerId);
}
void QEventDispatcherGlib::interrupt()
{
wakeUp();

View File

@ -85,6 +85,8 @@ public:
bool unregisterTimers(QObject *object);
QList<TimerInfo> registeredTimers(QObject *object) const;
int remainingTime(int timerId);
void wakeUp();
void interrupt();
void flush();

View File

@ -628,6 +628,19 @@ bool QEventDispatcherUNIX::hasPendingEvents()
return qGlobalPostedEventsCount();
}
int QEventDispatcherUNIX::remainingTime(int timerId)
{
#ifndef QT_NO_DEBUG
if (timerId < 1) {
qWarning("QEventDispatcherUNIX::remainingTime: invalid argument");
return -1;
}
#endif
Q_D(QEventDispatcherUNIX);
return d->timerList.timerRemainingTime(timerId);
}
void QEventDispatcherUNIX::wakeUp()
{
Q_D(QEventDispatcherUNIX);

View File

@ -116,6 +116,8 @@ public:
bool unregisterTimers(QObject *object);
QList<TimerInfo> registeredTimers(QObject *object) const;
int remainingTime(int timerId);
void wakeUp();
void interrupt();
void flush();

View File

@ -50,6 +50,7 @@
#include "qvarlengtharray.h"
#include "qwineventnotifier.h"
#include "qelapsedtimer.h"
#include "qcoreapplication_p.h"
#include <private/qthread_p.h>
#include <private/qmutexpool_p.h>
@ -532,6 +533,8 @@ void QEventDispatcherWin32Private::registerTimer(WinTimerInfo *t)
ok = SetTimer(internalHwnd, t->timerId, interval, 0);
}
t->timeout = qt_msectime() + interval;
if (ok == 0)
qErrnoWarning("QEventDispatcherWin32::registerTimer: Failed to create a timer");
}
@ -998,6 +1001,42 @@ void QEventDispatcherWin32::activateEventNotifiers()
}
}
int QEventDispatcherWin32::remainingTime(int timerId)
{
#ifndef QT_NO_DEBUG
if (timerId < 1) {
qWarning("QEventDispatcherWin32::remainingTime: invalid argument");
return -1;
}
#endif
Q_D(QEventDispatcherWin32);
if (d->timerVec.isEmpty())
return -1;
quint64 currentTime = qt_msectime();
register WinTimerInfo *t;
for (int i=0; i<d->timerVec.size(); i++) {
t = d->timerVec.at(i);
if (t && t->timerId == timerId) { // timer found
if (currentTime < t->timeout) {
// time to wait
return t->timeout - currentTime;
} else {
return 0;
}
}
}
#ifndef QT_NO_DEBUG
qWarning("QEventDispatcherWin32::remainingTime: timer id %s not found", timerId);
#endif
return -1;
}
void QEventDispatcherWin32::wakeUp()
{
Q_D(QEventDispatcherWin32);

View File

@ -66,6 +66,7 @@ class QEventDispatcherWin32Private;
// forward declaration
LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp);
int qt_msectime();
class Q_CORE_EXPORT QEventDispatcherWin32 : public QAbstractEventDispatcher
{
@ -94,6 +95,8 @@ public:
void unregisterEventNotifier(QWinEventNotifier *notifier);
void activateEventNotifiers();
int remainingTime(int timerId);
void wakeUp();
void interrupt();
void flush();
@ -123,6 +126,7 @@ struct WinTimerInfo { // internal timer info
int timerId;
int interval;
Qt::TimerType timerType;
quint64 timeout; // - when to actually fire
QObject *obj; // - object to receive events
bool inTimerEvent;
int fastTimerId;

View File

@ -374,7 +374,7 @@ private:
\brief The QEventLoopLocker class provides a means to quit an event loop when it is no longer needed.
The QEventLoopLocker operates on particular objects - either a QCoreApplication
instance or a QEventLoop instance.
instance, a QEventLoop instance or a QThread instance.
This makes it possible to, for example, run a batch of jobs with an event loop
and exit that event loop after the last job is finished. That is accomplished
@ -388,7 +388,7 @@ private:
*/
/*!
Creates an event locker operating on the \p app.
Creates an event locker operating on the QCoreApplication.
The application will quit when there are no more QEventLoopLockers operating on it.
@ -401,7 +401,7 @@ QEventLoopLocker::QEventLoopLocker()
}
/*!
Creates an event locker operating on the \p app.
Creates an event locker operating on the \p loop.
This particular QEventLoop will quit when there are no more QEventLoopLockers operating on it.
@ -413,6 +413,13 @@ QEventLoopLocker::QEventLoopLocker(QEventLoop *loop)
}
/*!
Creates an event locker operating on the \p thread.
This particular QThread will quit when there are no more QEventLoopLockers operating on it.
\sa QThread::quit()
*/
QEventLoopLocker::QEventLoopLocker(QThread *thread)
: d_ptr(new QEventLoopLockerPrivate(static_cast<QThreadPrivate*>(QObjectPrivate::get(thread))))
{

File diff suppressed because it is too large Load Diff

View File

@ -57,8 +57,13 @@ class Q_CORE_EXPORT QMetaMethod
public:
inline QMetaMethod() : mobj(0),handle(0) {}
const char *signature() const;
QByteArray methodSignature() const;
QByteArray name() const;
const char *typeName() const;
int returnType() const;
int parameterCount() const;
int parameterType(int index) const;
void getParameterTypes(int *types) const;
QList<QByteArray> parameterTypes() const;
QList<QByteArray> parameterNames() const;
const char *tag() const;
@ -137,8 +142,16 @@ public:
inline bool isValid() const { return mobj != 0; }
private:
#if QT_DEPRECATED_SINCE(5,0)
// signature() has been renamed to methodSignature() in Qt 5.
// Warning, that function returns a QByteArray; check the life time if
// you convert to char*.
char *signature(struct renamedInQt5_warning_checkTheLifeTime * = 0) Q_DECL_EQ_DELETE;
#endif
const QMetaObject *mobj;
uint handle;
friend class QMetaMethodPrivate;
friend struct QMetaObject;
friend struct QMetaObjectPrivate;
friend class QObject;

View File

@ -105,11 +105,64 @@ enum MetaObjectFlags {
RequiresVariantMetaObject = 0x02
};
enum MetaDataFlags {
IsUnresolvedType = 0x80000000,
TypeNameIndexMask = 0x7FFFFFFF
};
class QArgumentType
{
public:
QArgumentType(int type)
: _type(type)
{}
QArgumentType(const QByteArray &name)
: _type(QMetaType::type(name.constData())), _name(name)
{}
QArgumentType()
: _type(0)
{}
int type() const
{ return _type; }
QByteArray name() const
{
if (_type && _name.isEmpty())
const_cast<QArgumentType *>(this)->_name = QMetaType::typeName(_type);
return _name;
}
bool operator==(const QArgumentType &other) const
{
if (_type)
return _type == other._type;
else if (other._type)
return false;
else
return _name == other._name;
}
bool operator!=(const QArgumentType &other) const
{
if (_type)
return _type != other._type;
else if (other._type)
return true;
else
return _name != other._name;
}
private:
int _type;
QByteArray _name;
};
template <class T, int> class QVarLengthArray;
typedef QVarLengthArray<QArgumentType, 10> QArgumentTypeArray;
class QMetaMethodPrivate;
class QMutex;
struct QMetaObjectPrivate
{
enum { OutputRevision = 6 }; // Used by moc and qmetaobjectbuilder
enum { OutputRevision = 7 }; // Used by moc, qmetaobjectbuilder and qdbus
int revision;
int className;
@ -122,18 +175,34 @@ struct QMetaObjectPrivate
int signalCount; //since revision 4
// revision 5 introduces changes in normalized signatures, no new members
// revision 6 added qt_static_metacall as a member of each Q_OBJECT and inside QMetaObject itself
// revision 7 is Qt 5
static inline const QMetaObjectPrivate *get(const QMetaObject *metaobject)
{ return reinterpret_cast<const QMetaObjectPrivate*>(metaobject->d.data); }
static int indexOfSignalRelative(const QMetaObject **baseObject,
const char* name,
bool normalizeStringData);
static int indexOfSlotRelative(const QMetaObject **m,
const char *slot,
bool normalizeStringData);
static int originalClone(const QMetaObject *obj, int local_method_index);
static QByteArray decodeMethodSignature(const char *signature,
QArgumentTypeArray &types);
static int indexOfSignalRelative(const QMetaObject **baseObject,
const QByteArray &name, int argc,
const QArgumentType *types);
static int indexOfSlotRelative(const QMetaObject **m,
const QByteArray &name, int argc,
const QArgumentType *types);
static int indexOfSignal(const QMetaObject *m, const QByteArray &name,
int argc, const QArgumentType *types);
static int indexOfSlot(const QMetaObject *m, const QByteArray &name,
int argc, const QArgumentType *types);
static int indexOfMethod(const QMetaObject *m, const QByteArray &name,
int argc, const QArgumentType *types);
static int indexOfConstructor(const QMetaObject *m, const QByteArray &name,
int argc, const QArgumentType *types);
static bool checkConnectArgs(int signalArgc, const QArgumentType *signalTypes,
int methodArgc, const QArgumentType *methodTypes);
static bool checkConnectArgs(const QMetaMethodPrivate *signal,
const QMetaMethodPrivate *method);
static QList<QByteArray> parameterTypeNamesFromSignature(const char *signature);
#ifndef QT_NO_QOBJECT

View File

@ -78,26 +78,17 @@ QT_BEGIN_NAMESPACE
*/
// copied from moc's generator.cpp
uint qvariant_nameToType(const char* name)
bool isBuiltinType(const QByteArray &type)
{
if (!name)
return 0;
uint tp = QMetaType::type(name);
return tp < QMetaType::User ? tp : 0;
}
/*
Returns true if the type is a QVariant types.
*/
bool isVariantType(const char* type)
{
return qvariant_nameToType(type) != 0;
int id = QMetaType::type(type);
if (!id && !type.isEmpty() && type != "void")
return false;
return (id < QMetaType::User);
}
// copied from qmetaobject.cpp
static inline const QMetaObjectPrivate *priv(const uint* data)
{ return reinterpret_cast<const QMetaObjectPrivate*>(data); }
// end of copied lines from qmetaobject.cpp
class QMetaMethodBuilderPrivate
{
@ -105,7 +96,7 @@ public:
QMetaMethodBuilderPrivate
(QMetaMethod::MethodType _methodType,
const QByteArray& _signature,
const QByteArray& _returnType = QByteArray(),
const QByteArray& _returnType = QByteArray("void"),
QMetaMethod::Access _access = QMetaMethod::Public,
int _revision = 0)
: signature(QMetaObject::normalizedSignature(_signature.constData())),
@ -113,6 +104,7 @@ public:
attributes(((int)_access) | (((int)_methodType) << 2)),
revision(_revision)
{
Q_ASSERT((_methodType == QMetaMethod::Constructor) == returnType.isNull());
}
QByteArray signature;
@ -136,6 +128,21 @@ public:
{
attributes = ((attributes & ~AccessMask) | (int)value);
}
QList<QByteArray> parameterTypes() const
{
return QMetaObjectPrivate::parameterTypeNamesFromSignature(signature);
}
int parameterCount() const
{
return parameterTypes().size();
}
QByteArray name() const
{
return signature.left(qMax(signature.indexOf('('), 0));
}
};
class QMetaPropertyBuilderPrivate
@ -429,8 +436,7 @@ QMetaMethodBuilder QMetaObjectBuilder::addMethod(const QByteArray& signature)
\a signature and \a returnType. Returns an object that can be
used to adjust the other attributes of the method. The \a signature
and \a returnType will be normalized before they are added to
the class. If \a returnType is empty, then it indicates that
the method has \c{void} as its return type.
the class.
\sa method(), methodCount(), removeMethod(), indexOfMethod()
*/
@ -458,13 +464,13 @@ QMetaMethodBuilder QMetaObjectBuilder::addMethod(const QMetaMethod& prototype)
{
QMetaMethodBuilder method;
if (prototype.methodType() == QMetaMethod::Method)
method = addMethod(prototype.signature());
method = addMethod(prototype.methodSignature());
else if (prototype.methodType() == QMetaMethod::Signal)
method = addSignal(prototype.signature());
method = addSignal(prototype.methodSignature());
else if (prototype.methodType() == QMetaMethod::Slot)
method = addSlot(prototype.signature());
method = addSlot(prototype.methodSignature());
else if (prototype.methodType() == QMetaMethod::Constructor)
method = addConstructor(prototype.signature());
method = addConstructor(prototype.methodSignature());
method.setReturnType(prototype.typeName());
method.setParameterNames(prototype.parameterNames());
method.setTag(prototype.tag());
@ -501,7 +507,7 @@ QMetaMethodBuilder QMetaObjectBuilder::addSignal(const QByteArray& signature)
{
int index = d->methods.size();
d->methods.append(QMetaMethodBuilderPrivate
(QMetaMethod::Signal, signature, QByteArray(), QMetaMethod::Protected));
(QMetaMethod::Signal, signature, QByteArray("void"), QMetaMethod::Protected));
return QMetaMethodBuilder(this, index);
}
@ -517,7 +523,8 @@ QMetaMethodBuilder QMetaObjectBuilder::addSignal(const QByteArray& signature)
QMetaMethodBuilder QMetaObjectBuilder::addConstructor(const QByteArray& signature)
{
int index = d->constructors.size();
d->constructors.append(QMetaMethodBuilderPrivate(QMetaMethod::Constructor, signature));
d->constructors.append(QMetaMethodBuilderPrivate(QMetaMethod::Constructor, signature,
/*returnType=*/QByteArray()));
return QMetaMethodBuilder(this, -(index + 1));
}
@ -535,7 +542,7 @@ QMetaMethodBuilder QMetaObjectBuilder::addConstructor(const QByteArray& signatur
QMetaMethodBuilder QMetaObjectBuilder::addConstructor(const QMetaMethod& prototype)
{
Q_ASSERT(prototype.methodType() == QMetaMethod::Constructor);
QMetaMethodBuilder ctor = addConstructor(prototype.signature());
QMetaMethodBuilder ctor = addConstructor(prototype.methodSignature());
ctor.setReturnType(prototype.typeName());
ctor.setParameterNames(prototype.parameterNames());
ctor.setTag(prototype.tag());
@ -588,7 +595,7 @@ QMetaPropertyBuilder QMetaObjectBuilder::addProperty(const QMetaProperty& protot
if (prototype.hasNotifySignal()) {
// Find an existing method for the notify signal, or add a new one.
QMetaMethod method = prototype.notifySignal();
int index = indexOfMethod(method.signature());
int index = indexOfMethod(method.methodSignature());
if (index == -1)
index = addMethod(method).index();
d->properties[property._index].notifySignal = index;
@ -731,16 +738,12 @@ void QMetaObjectBuilder::addMetaObject
if ((members & RelatedMetaObjects) != 0) {
const QMetaObject **objects;
if (priv(prototype->d.data)->revision < 2) {
objects = (const QMetaObject **)(prototype->d.extradata);
} else
{
const QMetaObjectExtraData *extra = (const QMetaObjectExtraData *)(prototype->d.extradata);
if (extra)
objects = extra->objects;
else
objects = 0;
}
Q_ASSERT(priv(prototype->d.data)->revision >= 2);
const QMetaObjectExtraData *extra = (const QMetaObjectExtraData *)(prototype->d.extradata);
if (extra)
objects = extra->objects;
else
objects = 0;
if (objects) {
while (*objects != 0) {
addRelatedMetaObject(*objects);
@ -750,12 +753,11 @@ void QMetaObjectBuilder::addMetaObject
}
if ((members & StaticMetacall) != 0) {
if (priv(prototype->d.data)->revision >= 6) {
const QMetaObjectExtraData *extra =
(const QMetaObjectExtraData *)(prototype->d.extradata);
if (extra && extra->static_metacall)
setStaticMetacallFunction(extra->static_metacall);
}
Q_ASSERT(priv(prototype->d.data)->revision >= 6);
const QMetaObjectExtraData *extra =
(const QMetaObjectExtraData *)(prototype->d.extradata);
if (extra && extra->static_metacall)
setStaticMetacallFunction(extra->static_metacall);
}
}
@ -1070,75 +1072,79 @@ int QMetaObjectBuilder::indexOfClassInfo(const QByteArray& name)
#define ALIGN(size,type) \
(size) = ((size) + sizeof(type) - 1) & ~(sizeof(type) - 1)
class MetaStringTable
/*!
\class QMetaStringTable
\internal
\brief The QMetaStringTable class can generate a meta-object string table at runtime.
*/
QMetaStringTable::QMetaStringTable()
: m_index(0) {}
// Enters the given value into the string table (if it hasn't already been
// entered). Returns the index of the string.
int QMetaStringTable::enter(const QByteArray &value)
{
public:
typedef QHash<QByteArray, int> Entries; // string --> offset mapping
typedef Entries::const_iterator const_iterator;
Entries::const_iterator constBegin() const
{ return m_entries.constBegin(); }
Entries::const_iterator constEnd() const
{ return m_entries.constEnd(); }
Entries::iterator it = m_entries.find(value);
if (it != m_entries.end())
return it.value();
int pos = m_index;
m_entries.insert(value, pos);
++m_index;
return pos;
}
MetaStringTable() : m_offset(0) {}
int enter(const QByteArray &value)
{
Entries::iterator it = m_entries.find(value);
if (it != m_entries.end())
return it.value();
int pos = m_offset;
m_entries.insert(value, pos);
m_offset += value.size() + 1;
return pos;
}
int arraySize() const { return m_offset; }
private:
Entries m_entries;
int m_offset;
};
// Build the parameter array string for a method.
static QByteArray buildParameterNames
(const QByteArray& signature, const QList<QByteArray>& parameterNames)
int QMetaStringTable::preferredAlignment()
{
// If the parameter name list is specified, then concatenate them.
if (!parameterNames.isEmpty()) {
QByteArray names;
bool first = true;
foreach (const QByteArray &name, parameterNames) {
if (first)
first = false;
else
names += (char)',';
names += name;
}
return names;
}
return Q_ALIGNOF(QByteArrayData);
}
// Count commas in the signature, excluding those inside template arguments.
int index = signature.indexOf('(');
if (index < 0)
return QByteArray();
++index;
if (index >= signature.size())
return QByteArray();
if (signature[index] == ')')
return QByteArray();
int count = 1;
int brackets = 0;
while (index < signature.size() && signature[index] != ',') {
char ch = signature[index++];
if (ch == '<')
++brackets;
else if (ch == '>')
--brackets;
else if (ch == ',' && brackets <= 0)
++count;
// Returns the size (in bytes) required for serializing this string table.
int QMetaStringTable::blobSize() const
{
int size = m_entries.size() * sizeof(QByteArrayData);
Entries::const_iterator it;
for (it = m_entries.constBegin(); it != m_entries.constEnd(); ++it)
size += it.key().size() + 1;
return size;
}
// Writes strings to string data struct.
// The struct consists of an array of QByteArrayData, followed by a char array
// containing the actual strings. This format must match the one produced by
// moc (see generator.cpp).
void QMetaStringTable::writeBlob(char *out)
{
Q_ASSERT(!(reinterpret_cast<quintptr>(out) & (preferredAlignment()-1)));
int offsetOfStringdataMember = m_entries.size() * sizeof(QByteArrayData);
int stringdataOffset = 0;
for (int i = 0; i < m_entries.size(); ++i) {
const QByteArray &str = m_entries.key(i);
int size = str.size();
qptrdiff offset = offsetOfStringdataMember + stringdataOffset
- i * sizeof(QByteArrayData);
const QByteArrayData data =
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(size, offset);
memcpy(out + i * sizeof(QByteArrayData), &data, sizeof(QByteArrayData));
memcpy(out + offsetOfStringdataMember + stringdataOffset, str.constData(), size);
out[offsetOfStringdataMember + stringdataOffset + size] = '\0';
stringdataOffset += size + 1;
}
return QByteArray(count - 1, ',');
}
// Returns the sum of all parameters (including return type) for the given
// \a methods. This is needed for calculating the size of the methods'
// parameter type/name meta-data.
static int aggregateParameterCount(const QList<QMetaMethodBuilderPrivate> &methods)
{
int sum = 0;
for (int i = 0; i < methods.size(); ++i)
sum += methods.at(i).parameterCount() + 1; // +1 for return type
return sum;
}
// Build a QMetaObject in "buf" based on the information in "d".
@ -1151,6 +1157,7 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
Q_UNUSED(expectedSize); // Avoid warning in release mode
int size = 0;
int dataIndex;
int paramsIndex;
int enumIndex;
int index;
bool hasRevisionedMethods = d->hasRevisionedMethods();
@ -1181,8 +1188,13 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
break;
}
}
int methodParametersDataSize =
((aggregateParameterCount(d->methods)
+ aggregateParameterCount(d->constructors)) * 2) // types and parameter names
- d->methods.size() // return "parameters" don't have names
- d->constructors.size(); // "this" parameters don't have names
if (buf) {
Q_STATIC_ASSERT_X(QMetaObjectPrivate::OutputRevision == 6, "QMetaObjectBuilder should generate the same version as moc");
Q_STATIC_ASSERT_X(QMetaObjectPrivate::OutputRevision == 7, "QMetaObjectBuilder should generate the same version as moc");
pmeta->revision = QMetaObjectPrivate::OutputRevision;
pmeta->flags = d->flags;
pmeta->className = 0; // Class name is always the first string.
@ -1197,6 +1209,8 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
dataIndex += 5 * d->methods.size();
if (hasRevisionedMethods)
dataIndex += d->methods.size();
paramsIndex = dataIndex;
dataIndex += methodParametersDataSize;
pmeta->propertyCount = d->properties.size();
pmeta->propertyData = dataIndex;
@ -1218,6 +1232,8 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
dataIndex += 5 * d->methods.size();
if (hasRevisionedMethods)
dataIndex += d->methods.size();
paramsIndex = dataIndex;
dataIndex += methodParametersDataSize;
dataIndex += 3 * d->properties.size();
if (hasNotifySignals)
dataIndex += d->properties.size();
@ -1240,13 +1256,14 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
// Find the start of the data and string tables.
int *data = reinterpret_cast<int *>(pmeta);
size += dataIndex * sizeof(int);
ALIGN(size, void *);
char *str = reinterpret_cast<char *>(buf + size);
if (buf) {
if (relocatable) {
meta->d.stringdata = reinterpret_cast<const char *>((quintptr)size);
meta->d.stringdata = reinterpret_cast<const QByteArrayData *>((quintptr)size);
meta->d.data = reinterpret_cast<uint *>((quintptr)pmetaSize);
} else {
meta->d.stringdata = str;
meta->d.stringdata = reinterpret_cast<const QByteArrayData *>(str);
meta->d.data = reinterpret_cast<uint *>(data);
}
}
@ -1254,7 +1271,7 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
// Reset the current data position to just past the QMetaObjectPrivate.
dataIndex = MetaObjectPrivateFieldCount;
MetaStringTable strings;
QMetaStringTable strings;
strings.enter(d->className);
// Output the class infos,
@ -1273,24 +1290,21 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
Q_ASSERT(!buf || dataIndex == pmeta->methodData);
for (index = 0; index < d->methods.size(); ++index) {
QMetaMethodBuilderPrivate *method = &(d->methods[index]);
int sig = strings.enter(method->signature);
int params;
QByteArray names = buildParameterNames
(method->signature, method->parameterNames);
params = strings.enter(names);
int ret = strings.enter(method->returnType);
int name = strings.enter(method->name());
int argc = method->parameterCount();
int tag = strings.enter(method->tag);
int attrs = method->attributes;
if (buf) {
data[dataIndex] = sig;
data[dataIndex + 1] = params;
data[dataIndex + 2] = ret;
data[dataIndex] = name;
data[dataIndex + 1] = argc;
data[dataIndex + 2] = paramsIndex;
data[dataIndex + 3] = tag;
data[dataIndex + 4] = attrs;
if (method->methodType() == QMetaMethod::Signal)
pmeta->signalCount++;
}
dataIndex += 5;
paramsIndex += 1 + argc * 2;
}
if (hasRevisionedMethods) {
for (index = 0; index < d->methods.size(); ++index) {
@ -1301,23 +1315,59 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
}
}
// Output the method parameters in the class.
Q_ASSERT(!buf || dataIndex == pmeta->methodData + d->methods.size() * 5
+ (hasRevisionedMethods ? d->methods.size() : 0));
for (int x = 0; x < 2; ++x) {
QList<QMetaMethodBuilderPrivate> &methods = (x == 0) ? d->methods : d->constructors;
for (index = 0; index < methods.size(); ++index) {
QMetaMethodBuilderPrivate *method = &(methods[index]);
QList<QByteArray> paramTypeNames = method->parameterTypes();
int paramCount = paramTypeNames.size();
for (int i = -1; i < paramCount; ++i) {
const QByteArray &typeName = (i < 0) ? method->returnType : paramTypeNames.at(i);
int typeInfo;
if (isBuiltinType(typeName))
typeInfo = QMetaType::type(typeName);
else
typeInfo = IsUnresolvedType | strings.enter(typeName);
if (buf)
data[dataIndex] = typeInfo;
++dataIndex;
}
QList<QByteArray> paramNames = method->parameterNames;
while (paramNames.size() < paramCount)
paramNames.append(QByteArray());
for (int i = 0; i < paramCount; ++i) {
int stringIndex = strings.enter(paramNames.at(i));
if (buf)
data[dataIndex] = stringIndex;
++dataIndex;
}
}
}
// Output the properties in the class.
Q_ASSERT(!buf || dataIndex == pmeta->propertyData);
for (index = 0; index < d->properties.size(); ++index) {
QMetaPropertyBuilderPrivate *prop = &(d->properties[index]);
int name = strings.enter(prop->name);
int type = strings.enter(prop->type);
int typeInfo;
if (isBuiltinType(prop->type))
typeInfo = QMetaType::type(prop->type);
else
typeInfo = IsUnresolvedType | strings.enter(prop->type);
int flags = prop->flags;
if (!isVariantType(prop->type)) {
if (!isBuiltinType(prop->type))
flags |= EnumOrFlag;
} else {
flags |= qvariant_nameToType(prop->type) << 24;
}
if (buf) {
data[dataIndex] = name;
data[dataIndex + 1] = type;
data[dataIndex + 1] = typeInfo;
data[dataIndex + 2] = flags;
}
dataIndex += 3;
@ -1372,34 +1422,25 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
Q_ASSERT(!buf || dataIndex == pmeta->constructorData);
for (index = 0; index < d->constructors.size(); ++index) {
QMetaMethodBuilderPrivate *method = &(d->constructors[index]);
int sig = strings.enter(method->signature);
int params;
QByteArray names = buildParameterNames
(method->signature, method->parameterNames);
params = strings.enter(names);
int ret = strings.enter(method->returnType);
int name = strings.enter(method->name());
int argc = method->parameterCount();
int tag = strings.enter(method->tag);
int attrs = method->attributes;
if (buf) {
data[dataIndex] = sig;
data[dataIndex + 1] = params;
data[dataIndex + 2] = ret;
data[dataIndex] = name;
data[dataIndex + 1] = argc;
data[dataIndex + 2] = paramsIndex;
data[dataIndex + 3] = tag;
data[dataIndex + 4] = attrs;
}
dataIndex += 5;
paramsIndex += 1 + argc * 2;
}
size += strings.arraySize();
size += strings.blobSize();
if (buf) {
// Write strings to string data array.
MetaStringTable::const_iterator it;
for (it = strings.constBegin(); it != strings.constEnd(); ++it) {
memcpy(str + it.value(), it.key().constData(), it.key().size());
str[it.value() + it.key().size()] = '\0';
}
}
if (buf)
strings.writeBlob(str);
// Output the zero terminator in the data array.
if (buf)
@ -1508,7 +1549,7 @@ void QMetaObjectBuilder::fromRelocatableData(QMetaObject *output,
quintptr dataOffset = (quintptr)dataMo->d.data;
output->d.superdata = superclass;
output->d.stringdata = buf + stringdataOffset;
output->d.stringdata = reinterpret_cast<const QByteArrayData *>(buf + stringdataOffset);
output->d.data = reinterpret_cast<const uint *>(buf + dataOffset);
output->d.extradata = 0;
}
@ -1896,7 +1937,7 @@ QByteArray QMetaMethodBuilder::returnType() const
is empty, then the method's return type is \c{void}. The \a value
will be normalized before it is added to the method.
\sa returnType(), signature()
\sa returnType(), parameterTypes(), signature()
*/
void QMetaMethodBuilder::setReturnType(const QByteArray& value)
{
@ -1905,6 +1946,20 @@ void QMetaMethodBuilder::setReturnType(const QByteArray& value)
d->returnType = QMetaObject::normalizedType(value);
}
/*!
Returns the list of parameter types for this method.
\sa returnType(), parameterNames()
*/
QList<QByteArray> QMetaMethodBuilder::parameterTypes() const
{
QMetaMethodBuilderPrivate *d = d_func();
if (d)
return d->parameterTypes();
else
return QList<QByteArray>();
}
/*!
Returns the list of parameter names for this method.

Some files were not shown because too many files have changed in this diff Show More