diff options
author | Thomas Zander <t.zander@nokia.com> | 2010-09-28 11:44:45 (GMT) |
---|---|---|
committer | Thomas Zander <t.zander@nokia.com> | 2010-09-28 11:44:45 (GMT) |
commit | 5c08412285f14d89174aef1190a1de1c35fd62bd (patch) | |
tree | 2e9bef2fdf0af18db76b011cd9c4ed4b456f507c /src/corelib | |
parent | 2645784f05db7b1e631621c511e94c88fc5cd211 (diff) | |
parent | 2868302626b8a31f44df1068514485a89ec27171 (diff) | |
download | Qt-5c08412285f14d89174aef1190a1de1c35fd62bd.zip Qt-5c08412285f14d89174aef1190a1de1c35fd62bd.tar.gz Qt-5c08412285f14d89174aef1190a1de1c35fd62bd.tar.bz2 |
Merge commit 'origin/master' into fileEnginesOn47
Conflicts:
qmake/Makefile.win32
qmake/qmake.pri
src/corelib/io/qdir.cpp
src/corelib/io/qfileinfo.cpp
src/corelib/io/qfileinfo_p.h
src/corelib/io/qfsfileengine_win.cpp
src/s60installs/bwins/QtGuiu.def
src/s60installs/eabi/QtCoreu.def
src/s60installs/eabi/QtGuiu.def
src/tools/bootstrap/bootstrap.pro
tests/auto/qfileinfo/tst_qfileinfo.cpp
Diffstat (limited to 'src/corelib')
79 files changed, 2587 insertions, 966 deletions
diff --git a/src/corelib/arch/arch.pri b/src/corelib/arch/arch.pri index 57bc80a..971069f 100644 --- a/src/corelib/arch/arch.pri +++ b/src/corelib/arch/arch.pri @@ -21,7 +21,9 @@ vxworks:HEADERS += arch/qatomic_vxworks.h arch/qatomic_generic.h \ arch/qatomic_powerpc.h \ arch/qatomic_arm.h \ + arch/qatomic_armv5.h \ arch/qatomic_armv6.h \ + arch/qatomic_armv7.h \ arch/qatomic_i386.h \ arch/qatomic_mips.h \ arch/qatomic_s390.h \ diff --git a/src/corelib/arch/armv6/arch.pri b/src/corelib/arch/armv6/arch.pri deleted file mode 100644 index fd0cce1..0000000 --- a/src/corelib/arch/armv6/arch.pri +++ /dev/null @@ -1,3 +0,0 @@ -# -# ARMv6 -# diff --git a/src/corelib/arch/qatomic_arm.h b/src/corelib/arch/qatomic_arm.h index 9df02a2..1c1c8a5 100644 --- a/src/corelib/arch/qatomic_arm.h +++ b/src/corelib/arch/qatomic_arm.h @@ -44,387 +44,32 @@ QT_BEGIN_HEADER -QT_BEGIN_NAMESPACE - -#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_NOT_NATIVE - -inline bool QBasicAtomicInt::isReferenceCountingNative() -{ return false; } -inline bool QBasicAtomicInt::isReferenceCountingWaitFree() -{ return false; } - -#define Q_ATOMIC_INT_TEST_AND_SET_IS_NOT_NATIVE - -inline bool QBasicAtomicInt::isTestAndSetNative() -{ return false; } -inline bool QBasicAtomicInt::isTestAndSetWaitFree() -{ return false; } - -#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_WAIT_FREE - -inline bool QBasicAtomicInt::isFetchAndStoreNative() -{ return true; } -inline bool QBasicAtomicInt::isFetchAndStoreWaitFree() -{ return true; } - -#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_NOT_NATIVE - -inline bool QBasicAtomicInt::isFetchAndAddNative() -{ return false; } -inline bool QBasicAtomicInt::isFetchAndAddWaitFree() -{ return false; } - -#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_NOT_NATIVE - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative() -{ return false; } -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree() -{ return false; } - -#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE -#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_WAIT_FREE - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative() -{ return true; } -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree() -{ return true; } - -#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_NOT_NATIVE - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative() -{ return false; } -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree() -{ return false; } - -#ifndef QT_NO_ARM_EABI - -// kernel places a restartable cmpxchg implementation at a fixed address -extern "C" typedef int (qt_atomic_eabi_cmpxchg_int_t)(int oldval, int newval, volatile int *ptr); -extern "C" typedef int (qt_atomic_eabi_cmpxchg_ptr_t)(void *oldval, void *newval, volatile void *ptr); -#define qt_atomic_eabi_cmpxchg_int (*reinterpret_cast<qt_atomic_eabi_cmpxchg_int_t *>(0xffff0fc0)) -#define qt_atomic_eabi_cmpxchg_ptr (*reinterpret_cast<qt_atomic_eabi_cmpxchg_ptr_t *>(0xffff0fc0)) - -#else - -extern Q_CORE_EXPORT char q_atomic_lock; -Q_CORE_EXPORT void qt_atomic_yield(int *); - -#ifdef Q_CC_RVCT - -Q_CORE_EXPORT __asm char q_atomic_swp(volatile char *ptr, char newval); - -#else - -inline char q_atomic_swp(volatile char *ptr, char newval) -{ - register char ret; - asm volatile("swpb %0,%2,[%3]" - : "=&r"(ret), "=m" (*ptr) - : "r"(newval), "r"(ptr) - : "cc", "memory"); - return ret; -} - -#endif // Q_CC_RVCT - -#endif // QT_NO_ARM_EABI - -// Reference counting - -inline bool QBasicAtomicInt::ref() -{ -#ifndef QT_NO_ARM_EABI - register int originalValue; - register int newValue; - do { - originalValue = _q_value; - newValue = originalValue + 1; - } while (qt_atomic_eabi_cmpxchg_int(originalValue, newValue, &_q_value) != 0); - return newValue != 0; -#else - int count = 0; - while (q_atomic_swp(&q_atomic_lock, ~0) != 0) - qt_atomic_yield(&count); - int originalValue = _q_value++; - q_atomic_swp(&q_atomic_lock, 0); - return originalValue != -1; -#endif -} - -inline bool QBasicAtomicInt::deref() -{ -#ifndef QT_NO_ARM_EABI - register int originalValue; - register int newValue; - do { - originalValue = _q_value; - newValue = originalValue - 1; - } while (qt_atomic_eabi_cmpxchg_int(originalValue, newValue, &_q_value) != 0); - return newValue != 0; -#else - int count = 0; - while (q_atomic_swp(&q_atomic_lock, ~0) != 0) - qt_atomic_yield(&count); - int originalValue = _q_value--; - q_atomic_swp(&q_atomic_lock, 0); - return originalValue != 1; -#endif -} - -// Test and set for integers - -inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) -{ -#ifndef QT_NO_ARM_EABI - register int originalValue; - do { - originalValue = _q_value; - if (originalValue != expectedValue) - return false; - } while (qt_atomic_eabi_cmpxchg_int(expectedValue, newValue, &_q_value) != 0); - return true; -#else - bool returnValue = false; - int count = 0; - while (q_atomic_swp(&q_atomic_lock, ~0) != 0) - qt_atomic_yield(&count); - if (_q_value == expectedValue) { - _q_value = newValue; - returnValue = true; - } - q_atomic_swp(&q_atomic_lock, 0); - return returnValue; -#endif -} - -inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) -{ - return testAndSetOrdered(expectedValue, newValue); -} - -inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue) -{ - return testAndSetOrdered(expectedValue, newValue); -} - -inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue) -{ - return testAndSetOrdered(expectedValue, newValue); -} - -// Fetch and store for integers - -#ifndef Q_CC_RVCT - -inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) -{ - int originalValue; - asm volatile("swp %0,%2,[%3]" - : "=&r"(originalValue), "=m" (_q_value) - : "r"(newValue), "r"(&_q_value) - : "cc", "memory"); - return originalValue; -} - -#endif - -inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue) -{ - return fetchAndStoreOrdered(newValue); -} - -inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue) -{ - return fetchAndStoreOrdered(newValue); -} - -inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue) -{ - return fetchAndStoreOrdered(newValue); -} - -// Fetch and add for integers - -inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) -{ -#ifndef QT_NO_ARM_EABI - register int originalValue; - register int newValue; - do { - originalValue = _q_value; - newValue = originalValue + valueToAdd; - } while (qt_atomic_eabi_cmpxchg_int(originalValue, newValue, &_q_value) != 0); - return originalValue; -#else - int count = 0; - while (q_atomic_swp(&q_atomic_lock, ~0) != 0) - qt_atomic_yield(&count); - int originalValue = _q_value; - _q_value += valueToAdd; - q_atomic_swp(&q_atomic_lock, 0); - return originalValue; -#endif -} - -inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd) -{ - return fetchAndAddOrdered(valueToAdd); -} - -inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd) -{ - return fetchAndAddOrdered(valueToAdd); -} - -inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd) -{ - return fetchAndAddOrdered(valueToAdd); -} - -// Test and set for pointers - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) -{ -#ifndef QT_NO_ARM_EABI - register T *originalValue; - do { - originalValue = _q_value; - if (originalValue != expectedValue) - return false; - } while (qt_atomic_eabi_cmpxchg_ptr(expectedValue, newValue, &_q_value) != 0); - return true; +#if defined(__ARM_ARCH_7__) \ + || defined(__ARM_ARCH_7A__) \ + || defined(__ARM_ARCH_7R__) \ + || defined(__ARM_ARCH_7M__) +# define QT_ARCH_ARMV7 +QT_BEGIN_INCLUDE_HEADER +# include "QtCore/qatomic_armv7.h" +QT_END_INCLUDE_HEADER +#elif defined(__ARM_ARCH_6__) \ + || defined(__ARM_ARCH_6J__) \ + || defined(__ARM_ARCH_6T2__) \ + || defined(__ARM_ARCH_6Z__) \ + || defined(__ARM_ARCH_6K__) \ + || defined(__ARM_ARCH_6ZK__) \ + || defined(__ARM_ARCH_6M__) \ + || (__TARGET_ARCH_ARM-0 >= 6) +# define QT_ARCH_ARMV6 +QT_BEGIN_INCLUDE_HEADER +# include "QtCore/qatomic_armv6.h" +QT_END_INCLUDE_HEADER #else - bool returnValue = false; - int count = 0; - while (q_atomic_swp(&q_atomic_lock, ~0) != 0) - qt_atomic_yield(&count); - if (_q_value == expectedValue) { - _q_value = newValue; - returnValue = true; - } - q_atomic_swp(&q_atomic_lock, 0); - return returnValue; +# define QT_ARCH_ARMV5 +QT_BEGIN_INCLUDE_HEADER +# include "QtCore/qatomic_armv5.h" +QT_END_INCLUDE_HEADER #endif -} - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue) -{ - return testAndSetOrdered(expectedValue, newValue); -} - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue) -{ - return testAndSetOrdered(expectedValue, newValue); -} - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue) -{ - return testAndSetOrdered(expectedValue, newValue); -} - -// Fetch and store for pointers - -#ifdef Q_CC_RVCT - -template <typename T> -__asm T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) -{ - add r2, pc, #0 - bx r2 - arm - swp r2,r1,[r0] - mov r0, r2 - bx lr - thumb -} - -#else - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) -{ - T *originalValue; - asm volatile("swp %0,%2,[%3]" - : "=&r"(originalValue), "=m" (_q_value) - : "r"(newValue), "r"(&_q_value) - : "cc", "memory"); - return originalValue; -} - -#endif // Q_CC_RVCT - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue) -{ - return fetchAndStoreOrdered(newValue); -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue) -{ - return fetchAndStoreOrdered(newValue); -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue) -{ - return fetchAndStoreOrdered(newValue); -} - -// Fetch and add for pointers - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) -{ -#ifndef QT_NO_ARM_EABI - register T *originalValue; - register T *newValue; - do { - originalValue = _q_value; - newValue = originalValue + valueToAdd; - } while (qt_atomic_eabi_cmpxchg_ptr(originalValue, newValue, &_q_value) != 0); - return originalValue; -#else - int count = 0; - while (q_atomic_swp(&q_atomic_lock, ~0) != 0) - qt_atomic_yield(&count); - T *originalValue = (_q_value); - _q_value += valueToAdd; - q_atomic_swp(&q_atomic_lock, 0); - return originalValue; -#endif -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd) -{ - return fetchAndAddOrdered(valueToAdd); -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd) -{ - return fetchAndAddOrdered(valueToAdd); -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd) -{ - return fetchAndAddOrdered(valueToAdd); -} - -QT_END_NAMESPACE QT_END_HEADER diff --git a/src/corelib/arch/qatomic_armv5.h b/src/corelib/arch/qatomic_armv5.h new file mode 100644 index 0000000..ab48380 --- /dev/null +++ b/src/corelib/arch/qatomic_armv5.h @@ -0,0 +1,431 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QATOMIC_ARMV5_H +#define QATOMIC_ARMV5_H + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_NOT_NATIVE + +inline bool QBasicAtomicInt::isReferenceCountingNative() +{ return false; } +inline bool QBasicAtomicInt::isReferenceCountingWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_TEST_AND_SET_IS_NOT_NATIVE + +inline bool QBasicAtomicInt::isTestAndSetNative() +{ return false; } +inline bool QBasicAtomicInt::isTestAndSetWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE +#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_WAIT_FREE + +inline bool QBasicAtomicInt::isFetchAndStoreNative() +{ return true; } +inline bool QBasicAtomicInt::isFetchAndStoreWaitFree() +{ return true; } + +#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_NOT_NATIVE + +inline bool QBasicAtomicInt::isFetchAndAddNative() +{ return false; } +inline bool QBasicAtomicInt::isFetchAndAddWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_NOT_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative() +{ return false; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE +#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_WAIT_FREE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative() +{ return true; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree() +{ return true; } + +#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_NOT_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative() +{ return false; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree() +{ return false; } + +#ifndef QT_NO_ARM_EABI + +// kernel places a restartable cmpxchg implementation at a fixed address +extern "C" typedef int (qt_atomic_eabi_cmpxchg_int_t)(int oldval, int newval, volatile int *ptr); +extern "C" typedef int (qt_atomic_eabi_cmpxchg_ptr_t)(void *oldval, void *newval, volatile void *ptr); +#define qt_atomic_eabi_cmpxchg_int (*reinterpret_cast<qt_atomic_eabi_cmpxchg_int_t *>(0xffff0fc0)) +#define qt_atomic_eabi_cmpxchg_ptr (*reinterpret_cast<qt_atomic_eabi_cmpxchg_ptr_t *>(0xffff0fc0)) + +#else + +extern Q_CORE_EXPORT char q_atomic_lock; +Q_CORE_EXPORT void qt_atomic_yield(int *); + +#ifdef Q_CC_RVCT + +Q_CORE_EXPORT __asm char q_atomic_swp(volatile char *ptr, char newval); + +#else + +inline char q_atomic_swp(volatile char *ptr, char newval) +{ + register char ret; + asm volatile("swpb %0,%2,[%3]" + : "=&r"(ret), "=m" (*ptr) + : "r"(newval), "r"(ptr) + : "cc", "memory"); + return ret; +} + +#endif // Q_CC_RVCT + +#endif // QT_NO_ARM_EABI + +// Reference counting + +inline bool QBasicAtomicInt::ref() +{ +#ifndef QT_NO_ARM_EABI + register int originalValue; + register int newValue; + do { + originalValue = _q_value; + newValue = originalValue + 1; + } while (qt_atomic_eabi_cmpxchg_int(originalValue, newValue, &_q_value) != 0); + return newValue != 0; +#else + int count = 0; + while (q_atomic_swp(&q_atomic_lock, ~0) != 0) + qt_atomic_yield(&count); + int originalValue = _q_value++; + q_atomic_swp(&q_atomic_lock, 0); + return originalValue != -1; +#endif +} + +inline bool QBasicAtomicInt::deref() +{ +#ifndef QT_NO_ARM_EABI + register int originalValue; + register int newValue; + do { + originalValue = _q_value; + newValue = originalValue - 1; + } while (qt_atomic_eabi_cmpxchg_int(originalValue, newValue, &_q_value) != 0); + return newValue != 0; +#else + int count = 0; + while (q_atomic_swp(&q_atomic_lock, ~0) != 0) + qt_atomic_yield(&count); + int originalValue = _q_value--; + q_atomic_swp(&q_atomic_lock, 0); + return originalValue != 1; +#endif +} + +// Test and set for integers + +inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) +{ +#ifndef QT_NO_ARM_EABI + register int originalValue; + do { + originalValue = _q_value; + if (originalValue != expectedValue) + return false; + } while (qt_atomic_eabi_cmpxchg_int(expectedValue, newValue, &_q_value) != 0); + return true; +#else + bool returnValue = false; + int count = 0; + while (q_atomic_swp(&q_atomic_lock, ~0) != 0) + qt_atomic_yield(&count); + if (_q_value == expectedValue) { + _q_value = newValue; + returnValue = true; + } + q_atomic_swp(&q_atomic_lock, 0); + return returnValue; +#endif +} + +inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +// Fetch and store for integers + +#ifndef Q_CC_RVCT + +inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) +{ + int originalValue; + asm volatile("swp %0,%2,[%3]" + : "=&r"(originalValue), "=m" (_q_value) + : "r"(newValue), "r"(&_q_value) + : "cc", "memory"); + return originalValue; +} + +#endif + +inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +// Fetch and add for integers + +inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) +{ +#ifndef QT_NO_ARM_EABI + register int originalValue; + register int newValue; + do { + originalValue = _q_value; + newValue = originalValue + valueToAdd; + } while (qt_atomic_eabi_cmpxchg_int(originalValue, newValue, &_q_value) != 0); + return originalValue; +#else + int count = 0; + while (q_atomic_swp(&q_atomic_lock, ~0) != 0) + qt_atomic_yield(&count); + int originalValue = _q_value; + _q_value += valueToAdd; + q_atomic_swp(&q_atomic_lock, 0); + return originalValue; +#endif +} + +inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +// Test and set for pointers + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) +{ +#ifndef QT_NO_ARM_EABI + register T *originalValue; + do { + originalValue = _q_value; + if (originalValue != expectedValue) + return false; + } while (qt_atomic_eabi_cmpxchg_ptr(expectedValue, newValue, &_q_value) != 0); + return true; +#else + bool returnValue = false; + int count = 0; + while (q_atomic_swp(&q_atomic_lock, ~0) != 0) + qt_atomic_yield(&count); + if (_q_value == expectedValue) { + _q_value = newValue; + returnValue = true; + } + q_atomic_swp(&q_atomic_lock, 0); + return returnValue; +#endif +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +// Fetch and store for pointers + +#ifdef Q_CC_RVCT + +template <typename T> +__asm T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) +{ + add r2, pc, #0 + bx r2 + arm + swp r2,r1,[r0] + mov r0, r2 + bx lr + thumb +} + +#else + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) +{ + T *originalValue; + asm volatile("swp %0,%2,[%3]" + : "=&r"(originalValue), "=m" (_q_value) + : "r"(newValue), "r"(&_q_value) + : "cc", "memory"); + return originalValue; +} + +#endif // Q_CC_RVCT + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +// Fetch and add for pointers + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) +{ +#ifndef QT_NO_ARM_EABI + register T *originalValue; + register T *newValue; + do { + originalValue = _q_value; + newValue = originalValue + valueToAdd; + } while (qt_atomic_eabi_cmpxchg_ptr(originalValue, newValue, &_q_value) != 0); + return originalValue; +#else + int count = 0; + while (q_atomic_swp(&q_atomic_lock, ~0) != 0) + qt_atomic_yield(&count); + T *originalValue = (_q_value); + _q_value += valueToAdd; + q_atomic_swp(&q_atomic_lock, 0); + return originalValue; +#endif +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QATOMIC_ARMV5_H diff --git a/src/corelib/arch/qatomic_armv6.h b/src/corelib/arch/qatomic_armv6.h index 38b7069..1aa3b88 100644 --- a/src/corelib/arch/qatomic_armv6.h +++ b/src/corelib/arch/qatomic_armv6.h @@ -45,6 +45,7 @@ QT_BEGIN_HEADER QT_BEGIN_NAMESPACE + #define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE inline bool QBasicAtomicInt::isReferenceCountingNative() @@ -102,6 +103,13 @@ Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree() #ifndef Q_CC_RVCT +#ifndef Q_DATA_MEMORY_BARRIER +# define Q_DATA_MEMORY_BARRIER asm volatile("":::"memory") +#endif +#ifndef Q_COMPILER_MEMORY_BARRIER +# define Q_COMPILER_MEMORY_BARRIER asm volatile("":::"memory") +#endif + inline bool QBasicAtomicInt::ref() { register int newValue; @@ -138,7 +146,7 @@ inline bool QBasicAtomicInt::deref() return newValue != 0; } -inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) +inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) { register int result; asm volatile("0:\n" @@ -152,11 +160,11 @@ inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) : [expectedValue] "r" (expectedValue), [newValue] "r" (newValue), [_q_value] "r" (&_q_value) - : "cc", "memory"); + : "cc"); return result == 0; } -inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) +inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue) { register int originalValue; register int result; @@ -170,11 +178,11 @@ inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) "+m" (_q_value) : [newValue] "r" (newValue), [_q_value] "r" (&_q_value) - : "cc", "memory"); + : "cc"); return originalValue; } -inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) +inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd) { register int originalValue; register int newValue; @@ -191,12 +199,12 @@ inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) "+m" (_q_value) : [valueToAdd] "r" (valueToAdd), [_q_value] "r" (&_q_value) - : "cc", "memory"); + : "cc"); return originalValue; } template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue) { register T *result; asm volatile("0:\n" @@ -210,12 +218,12 @@ Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValu : [expectedValue] "r" (expectedValue), [newValue] "r" (newValue), [_q_value] "r" (&_q_value) - : "cc", "memory"); + : "cc"); return result == 0; } template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue) { register T *originalValue; register int result; @@ -229,12 +237,12 @@ Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) "+m" (_q_value) : [newValue] "r" (newValue), [_q_value] "r" (&_q_value) - : "cc", "memory"); + : "cc"); return originalValue; } template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd) { register T *originalValue; register T *newValue; @@ -251,7 +259,7 @@ Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueTo "+m" (_q_value) : [valueToAdd] "r" (valueToAdd * sizeof(T)), [_q_value] "r" (&_q_value) - : "cc", "memory"); + : "cc"); return originalValue; } @@ -263,9 +271,18 @@ Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueTo // RVCT embedded assembly documentation: // http://www.keil.com/support/man/docs/armcc/armcc_chddbeib.htm -// save our pragma state and switch to ARM mode -#pragma push -#pragma arm +#if __TARGET_ARCH_THUMB-0 < 4 +// save our pragma state and switch to ARM mode (unless using Thumb2) +# pragma push +# pragma arm +#endif + +#ifndef Q_DATA_MEMORY_BARRIER +# define Q_DATA_MEMORY_BARRIER __schedule_barrier() +#endif +#ifndef Q_COMPILER_MEMORY_BARRIER +# define Q_COMPILER_MEMORY_BARRIER __schedule_barrier() +#endif inline bool QBasicAtomicInt::ref() { @@ -297,7 +314,7 @@ inline bool QBasicAtomicInt::deref() return newValue != 0; } -inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) +inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) { register int result; retry: @@ -311,7 +328,7 @@ inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) return result == 0; } -inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) +inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue) { register int originalValue; register int result; @@ -325,7 +342,7 @@ inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) return originalValue; } -inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) +inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd) { register int originalValue; register int newValue; @@ -342,7 +359,7 @@ inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) } template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue) { register T *result; retry: @@ -357,7 +374,7 @@ Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValu } template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue) { register T *originalValue; register int result; @@ -372,7 +389,7 @@ Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) } template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd) { register T *originalValue; register T *newValue; @@ -388,111 +405,153 @@ Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueTo return originalValue; } -// go back to the previous pragma state (probably Thumb mode) -#pragma pop +#if __TARGET_ARCH_THUMB-0 < 4 +# pragma pop #endif -// common code +#endif -inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) -{ - return testAndSetOrdered(expectedValue, newValue); -} +// common code inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue) { - return testAndSetOrdered(expectedValue, newValue); + bool returnValue = testAndSetRelaxed(expectedValue, newValue); + Q_DATA_MEMORY_BARRIER; + return returnValue; } inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue) { - return testAndSetOrdered(expectedValue, newValue); + Q_DATA_MEMORY_BARRIER; + return testAndSetRelaxed(expectedValue, newValue); } -inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue) +inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) { - return fetchAndStoreOrdered(newValue); + Q_DATA_MEMORY_BARRIER; + bool returnValue = testAndSetRelaxed(expectedValue, newValue); + Q_COMPILER_MEMORY_BARRIER; + return returnValue; } inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue) { - return fetchAndStoreOrdered(newValue); + int returnValue = fetchAndStoreRelaxed(newValue); + Q_DATA_MEMORY_BARRIER; + return returnValue; } inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue) { - return fetchAndStoreOrdered(newValue); + Q_DATA_MEMORY_BARRIER; + return fetchAndStoreRelaxed(newValue); } -inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd) +inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) { - return fetchAndAddOrdered(valueToAdd); + Q_DATA_MEMORY_BARRIER; + int returnValue = fetchAndStoreRelaxed(newValue); + Q_COMPILER_MEMORY_BARRIER; + return returnValue; } + inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd) { - return fetchAndAddOrdered(valueToAdd); + int returnValue = fetchAndAddRelaxed(valueToAdd); + Q_DATA_MEMORY_BARRIER; + return returnValue; } inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd) { - return fetchAndAddOrdered(valueToAdd); + Q_DATA_MEMORY_BARRIER; + return fetchAndAddRelaxed(valueToAdd); } -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue) +inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) { - return testAndSetOrdered(expectedValue, newValue); + Q_DATA_MEMORY_BARRIER; + int returnValue = fetchAndAddRelaxed(valueToAdd); + Q_COMPILER_MEMORY_BARRIER; + return returnValue; } template <typename T> Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue) { - return testAndSetOrdered(expectedValue, newValue); + bool returnValue = testAndSetRelaxed(expectedValue, newValue); + Q_DATA_MEMORY_BARRIER; + return returnValue; } template <typename T> Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue) { - return testAndSetOrdered(expectedValue, newValue); + Q_DATA_MEMORY_BARRIER; + return testAndSetRelaxed(expectedValue, newValue); } template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue) +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) { - return fetchAndStoreOrdered(newValue); + Q_DATA_MEMORY_BARRIER; + bool returnValue = testAndSetAcquire(expectedValue, newValue); + Q_COMPILER_MEMORY_BARRIER; + return returnValue; } template <typename T> Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue) { - return fetchAndStoreOrdered(newValue); + T *returnValue = fetchAndStoreRelaxed(newValue); + Q_DATA_MEMORY_BARRIER; + return returnValue; } template <typename T> Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue) { - return fetchAndStoreOrdered(newValue); + Q_DATA_MEMORY_BARRIER; + return fetchAndStoreRelaxed(newValue); } template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd) +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) { - return fetchAndAddOrdered(valueToAdd); + Q_DATA_MEMORY_BARRIER; + T *returnValue = fetchAndStoreRelaxed(newValue); + Q_COMPILER_MEMORY_BARRIER; + return returnValue; } template <typename T> Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd) { - return fetchAndAddOrdered(valueToAdd); + T *returnValue = fetchAndAddRelaxed(valueToAdd); + Q_DATA_MEMORY_BARRIER; + return returnValue; } template <typename T> Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd) { - return fetchAndAddOrdered(valueToAdd); + Q_DATA_MEMORY_BARRIER; + return fetchAndAddRelaxed(valueToAdd); } +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) +{ + Q_DATA_MEMORY_BARRIER; + T *returnValue = fetchAndAddRelaxed(valueToAdd); + Q_COMPILER_MEMORY_BARRIER; + return returnValue; +} + +#undef Q_DATA_MEMORY_BARRIER +#undef Q_COMPILER_MEMORY_BARRIER + QT_END_NAMESPACE QT_END_HEADER diff --git a/src/corelib/arch/qatomic_armv7.h b/src/corelib/arch/qatomic_armv7.h new file mode 100644 index 0000000..a95c4ea --- /dev/null +++ b/src/corelib/arch/qatomic_armv7.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QATOMIC_ARMV7_H +#define QATOMIC_ARMV7_H + +QT_BEGIN_HEADER + +// use the DMB instruction when compiling for ARMv7, ... +#ifndef Q_CC_RCVT +# define Q_DATA_MEMORY_BARRIER asm volatile("dmb\n":::"memory") +#else +# define Q_DATA_MEMORY_BARRIER do{__asm { dmb } __schedule_barrier();}while(0) +#endif + +// ... but the implementation is otherwise identical to that for ARMv6 +QT_BEGIN_INCLUDE_HEADER +#include "QtCore/qatomic_armv6.h" +QT_END_INCLUDE_HEADER + +QT_END_HEADER + +#endif // QATOMIC_ARMV7_H diff --git a/src/corelib/arch/symbian/arch.pri b/src/corelib/arch/symbian/arch.pri index 3ef1c9e..84a4984 100644 --- a/src/corelib/arch/symbian/arch.pri +++ b/src/corelib/arch/symbian/arch.pri @@ -2,4 +2,4 @@ # Symbian architecture # SOURCES += $$QT_ARCH_CPP/qatomic_symbian.cpp \ - $$QT_ARCH_CPP/../armv6/qatomic_generic_armv6.cpp + $$QT_ARCH_CPP/qatomic_generic_armv6.cpp diff --git a/src/corelib/arch/armv6/qatomic_generic_armv6.cpp b/src/corelib/arch/symbian/qatomic_generic_armv6.cpp index 39d966a..39d966a 100644 --- a/src/corelib/arch/armv6/qatomic_generic_armv6.cpp +++ b/src/corelib/arch/symbian/qatomic_generic_armv6.cpp diff --git a/src/corelib/codecs/qtextcodec_symbian.cpp b/src/corelib/codecs/qtextcodec_symbian.cpp index e4db9d7..9d7e856 100644 --- a/src/corelib/codecs/qtextcodec_symbian.cpp +++ b/src/corelib/codecs/qtextcodec_symbian.cpp @@ -53,12 +53,14 @@ struct QSymbianCodecInitData { const char *aliases; }; -/* This table contains the known Symbian codecs aliases. It is ordered by charsetId. - It is required as symbian does not provide have aliases. +/* This table contains the known Symbian codecs aliases. + It is required because symbian does not provide aliases for codecs. + It is also faster to have a name here than asking the system. + It is ordered by charsetId to allow binary search lookup */ static const QSymbianCodecInitData codecsData[] = { - { /*268439485*/ KCharacterSetIdentifierShiftJis, 17, "Shift_JIS\0MS_Kanji\0csShiftJIS\0MS_KANJI\0SJIS\0" }, - { /*268439486*/ KCharacterSetIdentifierGb2312, 57, "GB2312\0csGB2312\0CN-GB\0EUC-CN\0" }, + { /*268439485*/ KCharacterSetIdentifierShiftJis, 17, "Shift_JIS\0MS_Kanji\0csShiftJIS\0SJIS\0" }, + { /*268439486*/ KCharacterSetIdentifierGb2312, 57, "GB2312\0csGB2312\0CN-GB\0EUC-CN\0" }, // Note: ConvertCharacterSetIdentifierToMibEnumL returns Mib 0 instaead of 57 { /*268439487*/ KCharacterSetIdentifierBig5, 2026, "Big5\0csBig5\0Big5-ETen\0CP950\0BIG-FIVE\0CN-BIG5\0" }, { /*268440246*/ KCharacterSetIdentifierCodePage1252, 2252, "windows-1252\0Code Page 1252\0CP1252\0MS-ANSI\0" }, // { /*268450576*/ KCharacterSetIdentifierIso88591, 4, "ISO-8859-1\0ISO_8859-1:1987\0iso-ir-100\0ISO_8859-1\0latin1\0l1\0IBM819\0CP819\0csISOLatin1\0ISO-IR-100\0ISO8859-1\0L1\0LATIN1\0CSISOLATIN1\0" }, @@ -108,15 +110,20 @@ static const QSymbianCodecInitData codecsData[] = { { /*270562232*/ 270562232, 2258, "Windows-1258\0CP1258\0WINDOWS-1258\0" }, { /*270586888*/ 270586888, 0, "J5\0" }, { /*271011982*/ 271011982, 0, "ISCII\0" }, - { /*271066541*/ 271066541, 2009, "CP850\0IBM850\0""850\0csPC850Multilingual\0" }, + { /*271066541*/ 271066541, 2009, "CP850\0IBM850\0""850\0csPC850Multilingual\0" }, // Note: ConvertCharacterSetIdentifierToMibEnumL returns Mib 0 instead of 2009 { /*271082493*/ 271082493, 0, "EXTENDED_SMS_7BIT\0" }, { /*271082494*/ 271082494, 0, "gsm7_turkish_single\0" }, { /*271082495*/ 271082495, 0, "turkish_locking_gsm7ext\0" }, { /*271082496*/ 271082496, 0, "turkish_locking_single\0" }, + { /*271082503*/ 271082503, 0, "portuguese_gsm7_single\0" }, + { /*271082504*/ 271082504, 0, "portuguese_locking_gsm7ext\0" }, + { /*271082505*/ 271082505, 0, "portuguese_locking_single\0" }, + { /*271082506*/ 271082506, 0, "spanish_gsm7_single\0" }, + { /*271085624*/ 271085624, 114, "GB18030\0" }, { /*536929574*/ 536929574, 38, "EUC-KR\0" }, { /*536936703*/ 536936703, 0, "CP949\0" }, - { /*536936705*/ 536936705, 37, "ISO-2022-KR\0" }, - { /*536941517*/ 536941517, 36, "KS_C_5601-1987\0" } + { /*536936705*/ 536936705, 37, "ISO-2022-KR\0csISO2022KR\0" }, + { /*536941517*/ 536941517, 36, "KS_C_5601-1987\0iso-ir-149\0KS_C_5601-1989\0KSC_5601\0Korean\0csKSC56011987\0" } }; @@ -657,6 +664,10 @@ QSymbianTextCodec *QSymbianTextCodec::init() if (charsetId == localeMapperId) localeMapper = c; } else { + // We did not find the charsetId in our codecsData[], therefore we ask + // the OS for the codec name. We first try to get a "standard name" and fall + // back to array->At(i).Name(), if really needed. array->At(i).Name() is not + // guaranteed to be a correct name for QTextCodec::codecFromName(). QScopedPointer<HBufC8> buf; QT_TRAP_THROWING(buf.reset(converter->ConvertCharacterSetIdentifierToStandardNameL(charsetId, qt_s60GetRFs()))) QByteArray name; diff --git a/src/corelib/concurrent/qfuturewatcher.cpp b/src/corelib/concurrent/qfuturewatcher.cpp index d4573c6..21b0789 100644 --- a/src/corelib/concurrent/qfuturewatcher.cpp +++ b/src/corelib/concurrent/qfuturewatcher.cpp @@ -359,6 +359,15 @@ void QFutureWatcherBase::connectNotify(const char * signal) Q_D(QFutureWatcherBase); if (qstrcmp(signal, SIGNAL(resultReadyAt(int))) == 0) d->resultAtConnected.ref(); +#ifndef QT_NO_DEBUG + if (qstrcmp(signal, SIGNAL(finished())) == 0) { + if (futureInterface().isRunning()) { + //connections should be established before calling stFuture to avoid race. + // (The future could finish before the connection is made.) + qWarning("QFutureWatcher::connect: connecting after calling setFuture() is likely to produce race"); + } + } +#endif } void QFutureWatcherBase::disconnectNotify(const char * signal) diff --git a/src/corelib/concurrent/qtconcurrentrun.cpp b/src/corelib/concurrent/qtconcurrentrun.cpp index 5a9c755..e80a204 100644 --- a/src/corelib/concurrent/qtconcurrentrun.cpp +++ b/src/corelib/concurrent/qtconcurrentrun.cpp @@ -99,7 +99,7 @@ functions; passing by pointer is useful for calling non-const member functions that modify the instance. - For example, calling QString::split() (a const member function) in a + For example, calling QByteArray::split() (a const member function) in a separate thread is done like this: \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentrun.cpp 4 diff --git a/src/corelib/concurrent/qthreadpool.cpp b/src/corelib/concurrent/qthreadpool.cpp index f25a494..265de33 100644 --- a/src/corelib/concurrent/qthreadpool.cpp +++ b/src/corelib/concurrent/qthreadpool.cpp @@ -250,6 +250,7 @@ bool QThreadPoolPrivate::tooManyThreadsActive() const void QThreadPoolPrivate::startThread(QRunnable *runnable) { QScopedPointer <QThreadPoolThread> thread(new QThreadPoolThread(this)); + thread->setObjectName(QLatin1String("Thread (pooled)")); allThreads.insert(thread.data()); ++activeThreads; diff --git a/src/corelib/global/global.pri b/src/corelib/global/global.pri index b916b4d..260ed59 100644 --- a/src/corelib/global/global.pri +++ b/src/corelib/global/global.pri @@ -19,7 +19,7 @@ INCLUDEPATH += $$QT_BUILD_TREE/src/corelib/global # Only used on platforms with CONFIG += precompile_header PRECOMPILED_HEADER = global/qt_pch.h -linux*-g++*:!static { +linux*:!static:!linux-armcc:!linux-gcce { QMAKE_LFLAGS += -Wl,-e,qt_core_boilerplate prog=$$quote(if (/program interpreter: (.*)]/) { print $1; }) DEFINES += ELF_INTERPRETER=\\\"$$system(readelf -l /bin/ls | perl -n -e \'$$prog\')\\\" diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index a59a74f..c992735 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -1828,6 +1828,7 @@ QSysInfo::S60Version QSysInfo::s60Version() CDir* contents; TInt err = fileFinder.FindWildByDir(qt_S60Filter, qt_S60SystemInstallDir, contents); if (err == KErrNone) { + QScopedPointer<CDir> contentsDeleter(contents); err = contents->Sort(EDescending|ESortByName); if (err == KErrNone && contents->Count() > 0 && (*contents)[0].iName.Length() >= 12) { TInt major = (*contents)[0].iName[9] - '0'; @@ -1850,7 +1851,6 @@ QSysInfo::S60Version QSysInfo::s60Version() } } } - delete contents; } # ifdef Q_CC_NOKIAX86 diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index a8758cf..986b5c5 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -400,6 +400,19 @@ namespace QT_NAMESPACE {} # undef QT_HAVE_3DNOW # endif +#if defined(Q_CC_MSVC) && _MSC_VER >= 1600 +# define Q_COMPILER_RVALUE_REFS +# define Q_COMPILER_INITIALIZER_LISTS +# define Q_COMPILER_AUTO_TYPE +# define Q_COMPILER_LAMBDA +//# define Q_COMPILER_VARIADIC_TEMPLATES +//# define Q_COMPILER_CLASS_ENUM +//# define Q_COMPILER_DEFAULT_DELETE_MEMBERS +//# define Q_COMPILER_UNICODE_STRINGS +//# define Q_COMPILER_EXTERN_TEMPLATES +# endif + + #elif defined(__BORLANDC__) || defined(__TURBOC__) # define Q_CC_BOR # define Q_INLINE_TEMPLATE @@ -474,6 +487,26 @@ namespace QT_NAMESPACE {} # define QT_NO_ARM_EABI # endif # endif +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 403 + /* C++0x features supported in GCC 4.3: */ +# define Q_COMPILER_RVALUE_REFS +# endif +# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 + /* C++0x features supported in GCC 4.4: */ +# define Q_COMPILER_VARIADIC_TEMPLATES +# define Q_COMPILER_AUTO_TYPE +# define Q_COMPILER_EXTERN_TEMPLATES +# define Q_COMPILER_DEFAULT_DELETE_MEMBERS +# define Q_COMPILER_CLASS_ENUM +# define Q_COMPILER_INITIALIZER_LISTS +# endif +# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405 + /* C++0x features supported in GCC 4.5: */ +# define Q_COMPILER_LAMBDA +# define Q_COMPILER_UNICODE_STRINGS +# endif +# endif /* IBM compiler versions are a bit messy. There are actually two products: the C product, and the C++ product. The C++ compiler is always packaged @@ -1058,7 +1091,7 @@ redefine to built-in booleans to make autotests work properly */ typedef int QNoImplicitBoolCast; -#if defined(QT_ARCH_ARM) || defined(QT_ARCH_ARMV6) || defined(QT_ARCH_AVR32) || (defined(QT_ARCH_MIPS) && (defined(Q_WS_QWS) || defined(Q_OS_WINCE))) || defined(QT_ARCH_SH) || defined(QT_ARCH_SH4A) +#if defined(QT_ARCH_ARM) || defined(QT_ARCH_AVR32) || (defined(QT_ARCH_MIPS) && (defined(Q_WS_QWS) || defined(Q_OS_WINCE))) || defined(QT_ARCH_SH) || defined(QT_ARCH_SH4A) #define QT_NO_FPU #endif @@ -2612,6 +2645,12 @@ QT_LICENSED_MODULE(DBus) # define QT_NO_PROCESS #endif +#if defined (__ELF__) +# if defined (Q_OS_LINUX) || defined (Q_OS_SOLARIS) || defined (Q_OS_FREEBSD) || defined (Q_OS_OPENBSD) || defined (Q_OS_IRIX) +# define Q_OF_ELF +# endif +#endif + QT_END_NAMESPACE QT_END_HEADER diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp index ea7e2e4..d493390 100644 --- a/src/corelib/global/qlibraryinfo.cpp +++ b/src/corelib/global/qlibraryinfo.cpp @@ -66,6 +66,8 @@ QT_END_NAMESPACE QT_BEGIN_NAMESPACE +extern void qDumpCPUFeatures(); // in qsimd.cpp + #ifndef QT_NO_SETTINGS struct QLibrarySettings @@ -508,6 +510,17 @@ void qt_core_boilerplate() "Contact: Nokia Corporation (qt-info@nokia.com)\n" "\n" "Build key: " QT_BUILD_KEY "\n" + "Compat build key: " +#ifdef QT_BUILD_KEY_COMPAT + "| " QT_BUILD_KEY_COMPAT " " +#endif +#ifdef QT_BUILD_KEY_COMPAT2 + "| " QT_BUILD_KEY_COMPAT2 " " +#endif +#ifdef QT_BUILD_KEY_COMPAT3 + "| " QT_BUILD_KEY_COMPAT3 " " +#endif + "|\n" "Build date: %s\n" "Installation prefix: %s\n" "Library path: %s\n" @@ -517,6 +530,8 @@ void qt_core_boilerplate() qt_configure_libraries_path_str + 12, qt_configure_headers_path_str + 12); + QT_PREPEND_NAMESPACE(qDumpCPUFeatures)(); + #ifdef QT_EVAL extern void qt_core_eval_init(uint); qt_core_eval_init(1); diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index c66813a..a531009 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -92,6 +92,7 @@ Qt { Q_ENUMS(ConnectionType) #ifndef QT_NO_GESTURES Q_ENUMS(GestureState) + Q_ENUMS(GestureType) #endif #endif // (defined(Q_MOC_RUN) || defined(QT_JAMBI_RUN)) diff --git a/src/corelib/global/qnumeric.cpp b/src/corelib/global/qnumeric.cpp index 75fd31e..7ddb9e2 100644 --- a/src/corelib/global/qnumeric.cpp +++ b/src/corelib/global/qnumeric.cpp @@ -44,14 +44,49 @@ QT_BEGIN_NAMESPACE +/*! + Returns true if the double \a {d} is equivalent to infinity. +*/ Q_CORE_EXPORT bool qIsInf(double d) { return qt_is_inf(d); } + +/*! + Returns true if the double \a {d} is not a number (NaN). +*/ Q_CORE_EXPORT bool qIsNaN(double d) { return qt_is_nan(d); } + +/*! + Returns true if the double \a {d} is a finite number. +*/ Q_CORE_EXPORT bool qIsFinite(double d) { return qt_is_finite(d); } + +/*! + Returns true if the float \a {f} is equivalent to infinity. +*/ Q_CORE_EXPORT bool qIsInf(float f) { return qt_is_inf(f); } + +/*! + Returns true if the float \a {f} is not a number (NaN). +*/ Q_CORE_EXPORT bool qIsNaN(float f) { return qt_is_nan(f); } + +/*! + Returns true if the float \a {f} is a finite number. +*/ Q_CORE_EXPORT bool qIsFinite(float f) { return qt_is_finite(f); } + +/*! + Returns the bit pattern of a signalling NaN as a double. +*/ Q_CORE_EXPORT double qSNaN() { return qt_snan(); } + +/*! + Returns the bit pattern of a quiet NaN as a double. +*/ Q_CORE_EXPORT double qQNaN() { return qt_qnan(); } + +/*! + Returns the bit pattern for an infinite number as a double. +*/ Q_CORE_EXPORT double qInf() { return qt_inf(); } diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp index c7cf87f..bbe9226 100644 --- a/src/corelib/io/qdir.cpp +++ b/src/corelib/io/qdir.cpp @@ -767,6 +767,7 @@ QString QDir::relativeFilePath(const QString &fileName) const return result; } +#ifndef QT_NO_DEPRECATED /*! \obsolete @@ -776,6 +777,7 @@ QString QDir::convertSeparators(const QString &pathName) { return toNativeSeparators(pathName); } +#endif /*! \since 4.2 diff --git a/src/corelib/io/qdir.h b/src/corelib/io/qdir.h index 7e5fbac..9eab24f 100644 --- a/src/corelib/io/qdir.h +++ b/src/corelib/io/qdir.h @@ -128,6 +128,10 @@ public: QDir &operator=(const QDir &); QDir &operator=(const QString &path); +#ifdef Q_COMPILER_RVALUE_REFS + inline QDir &operator=(QDir &&other) + { qSwap(d_ptr, other.d_ptr); return *this; } +#endif void setPath(const QString &path); QString path() const; diff --git a/src/corelib/io/qfileinfo.h b/src/corelib/io/qfileinfo.h index 92bea5e..3eff208 100644 --- a/src/corelib/io/qfileinfo.h +++ b/src/corelib/io/qfileinfo.h @@ -71,6 +71,10 @@ public: ~QFileInfo(); QFileInfo &operator=(const QFileInfo &fileinfo); +#ifdef Q_COMPILER_RVALUE_REFS + inline QFileInfo&operator=(QFileInfo &&other) + { qSwap(d_ptr, other.d_ptr); return *this; } +#endif bool operator==(const QFileInfo &fileinfo); // 5.0 - remove me bool operator==(const QFileInfo &fileinfo) const; inline bool operator!=(const QFileInfo &fileinfo) { return !(operator==(fileinfo)); } // 5.0 - remove me diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp index 1aba4a7..8fd0919 100644 --- a/src/corelib/io/qfilesystemengine_win.cpp +++ b/src/corelib/io/qfilesystemengine_win.cpp @@ -180,7 +180,7 @@ static void resolveLibs() triedResolve = true; #if !defined(Q_OS_WINCE) - HINSTANCE advapiHnd = LoadLibrary(L"advapi32"); + HINSTANCE advapiHnd = QSystemLibrary::load(L"advapi32"); if (advapiHnd) { ptrGetNamedSecurityInfoW = (PtrGetNamedSecurityInfoW)GetProcAddress(advapiHnd, "GetNamedSecurityInfoW"); ptrLookupAccountSidW = (PtrLookupAccountSidW)GetProcAddress(advapiHnd, "LookupAccountSidW"); @@ -212,7 +212,7 @@ static void resolveLibs() ptrFreeSid(pWorld); } } - HINSTANCE userenvHnd = LoadLibrary(L"userenv"); + HINSTANCE userenvHnd = QSystemLibrary::load(L"userenv"); if (userenvHnd) ptrGetUserProfileDirectoryW = (PtrGetUserProfileDirectoryW)GetProcAddress(userenvHnd, "GetUserProfileDirectoryW"); HINSTANCE kernel32 = LoadLibrary(L"kernel32"); @@ -246,7 +246,7 @@ static bool resolveUNCLibs() #endif triedResolve = true; #if !defined(Q_OS_WINCE) - HINSTANCE hLib = LoadLibrary(L"netapi32"); + HINSTANCE hLib = QSystemLibrary::load(L"Netapi32"); if (hLib) { ptrNetShareEnum = (PtrNetShareEnum)GetProcAddress(hLib, "NetShareEnum"); if (ptrNetShareEnum) diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp index 26e587d..8544fba 100644 --- a/src/corelib/io/qiodevice.cpp +++ b/src/corelib/io/qiodevice.cpp @@ -1633,6 +1633,12 @@ QString QIODevice::errorString() const This function is called by QIODevice. Reimplement this function when creating a subclass of QIODevice. + When reimplementing this function it is important that this function + reads all the required data before returning. This is required in order + for QDataStream to be able to operate on the class. QDataStream assumes + all the requested information was read and therefore does not retry reading + if there was a problem. + \sa read() readLine() writeData() */ @@ -1645,6 +1651,12 @@ QString QIODevice::errorString() const This function is called by QIODevice. Reimplement this function when creating a subclass of QIODevice. + When reimplementing this function it is important that this function + writes all the data available before returning. This is required in order + for QDataStream to be able to operate on the class. QDataStream assumes + all the information was written and therefore does not retry writing if + there was a problem. + \sa read() write() */ diff --git a/src/corelib/io/qprocess_symbian.cpp b/src/corelib/io/qprocess_symbian.cpp index af657b2..003e781 100644 --- a/src/corelib/io/qprocess_symbian.cpp +++ b/src/corelib/io/qprocess_symbian.cpp @@ -375,10 +375,9 @@ QProcessActive::QProcessActive() // Nothing to do } -// Called from ProcessManagerThread +// Called from main thread QProcessActive::~QProcessActive() { - Cancel(); process = NULL; pproc = NULL; } @@ -482,10 +481,9 @@ QProcessManagerMediator::QProcessManagerMediator() // Nothing to do } -// Called from ProcessManagerThread +// Called from main thread QProcessManagerMediator::~QProcessManagerMediator() { - Cancel(); processManagerThread.Close(); currentCommand = ENoCommand; currentObserver = NULL; @@ -648,25 +646,36 @@ QProcessManager::QProcessManager() QProcessManager::~QProcessManager() { QPROCESS_DEBUG_PRINT("QProcessManager::~QProcessManager()"); - // Cancel death listening for all child processes - if (mediator) { - QMap<int, QProcessActive *>::Iterator it = children.begin(); - while (it != children.end()) { - // Remove all monitors - QProcessActive *active = it.value(); - mediator->remove(active); - - QPROCESS_DEBUG_PRINT("QProcessManager::~QProcessManager() removed listening for a process"); - ++it; + + // Check if manager thread is still alive. If this destructor is ran as part of global + // static cleanup, manager thread will most likely be terminated by kernel at this point, + // so trying to delete QProcessActives and QProcessMediators will panic as they + // will still be active. They can also no longer be canceled as the thread is already gone. + // In case manager thread has already died, we simply do nothing and let the deletion of + // the main heap at process exit take care of stray objects. + + if (managerThread.Handle() && managerThread.ExitType() == EExitPending) { + // Cancel death listening for all child processes + if (mediator) { + QMap<int, QProcessActive *>::Iterator it = children.begin(); + while (it != children.end()) { + // Remove all monitors + QProcessActive *active = it.value(); + mediator->remove(active); + + QPROCESS_DEBUG_PRINT("QProcessManager::~QProcessManager() removed listening for a process"); + ++it; + } + + // Terminate process manager thread. + mediator->terminate(); + delete mediator; } - // Terminate process manager thread. - mediator->terminate(); - delete mediator; + qDeleteAll(children.values()); + children.clear(); } - qDeleteAll(children.values()); - children.clear(); managerThread.Close(); managerMutex.Close(); } diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp index 384804a..f25c272 100644 --- a/src/corelib/io/qsettings.cpp +++ b/src/corelib/io/qsettings.cpp @@ -69,7 +69,7 @@ #ifdef Q_OS_WIN // for homedirpath reading from registry #include "qt_windows.h" -#include "qlibrary.h" +#include <private/qsystemlibrary_p.h> #endif // Q_OS_WIN #endif // QT_NO_QOBJECT @@ -1044,9 +1044,9 @@ static QString windowsConfigPath(int type) // We can't use QLibrary if there is QT_NO_QOBJECT is defined // This only happens when bootstrapping qmake. #ifndef Q_OS_WINCE - QLibrary library(QLatin1String("shell32")); + QSystemLibrary library(QLatin1String("shell32")); #else - QLibrary library(QLatin1String("coredll")); + QSystemLibrary library(QLatin1String("coredll")); #endif // Q_OS_WINCE typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, LPWSTR, int, BOOL); GetSpecialFolderPath SHGetSpecialFolderPath = (GetSpecialFolderPath)library.resolve("SHGetSpecialFolderPathW"); diff --git a/src/corelib/io/qsettings_win.cpp b/src/corelib/io/qsettings_win.cpp index de96e06..b3fe734 100644 --- a/src/corelib/io/qsettings_win.cpp +++ b/src/corelib/io/qsettings_win.cpp @@ -535,6 +535,15 @@ bool QWinSettingsPrivate::readKey(HKEY parentHandle, const QString &rSubKey, QVa break; } + case REG_QWORD: { + Q_ASSERT(data.size() == sizeof(qint64)); + qint64 i; + memcpy((char*)&i, data.constData(), sizeof(qint64)); + if (value != 0) + *value = i; + break; + } + default: qWarning("QSettings: Unknown data %d type in Windows registry", static_cast<int>(dataType)); if (value != 0) @@ -683,10 +692,19 @@ void QWinSettingsPrivate::set(const QString &uKey, const QVariant &value) break; } - case QVariant::Int: { + case QVariant::Int: + case QVariant::UInt: { type = REG_DWORD; - int i = value.toInt(); - regValueBuff = QByteArray((const char*)&i, sizeof(int)); + qint32 i = value.toInt(); + regValueBuff = QByteArray((const char*)&i, sizeof(qint32)); + break; + } + + case QVariant::LongLong: + case QVariant::ULongLong: { + type = REG_QWORD; + qint64 i = value.toLongLong(); + regValueBuff = QByteArray((const char*)&i, sizeof(qint64)); break; } diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp index 20ec995..6452c0f 100644 --- a/src/corelib/io/qurl.cpp +++ b/src/corelib/io/qurl.cpp @@ -176,7 +176,6 @@ */ #include "qplatformdefs.h" #include "qurl.h" -#include "private/qunicodetables_p.h" #include "qatomic.h" #include "qbytearray.h" #include "qdir.h" @@ -3446,23 +3445,26 @@ QString QUrlPrivate::canonicalHost() const if (host.contains(QLatin1Char(':'))) { // This is an IP Literal, use _IPLiteral to validate QByteArray ba = host.toLatin1(); + bool needsBraces = false; if (!ba.startsWith('[')) { // surround the IP Literal with [ ] if it's not already done so ba.reserve(ba.length() + 2); ba.prepend('['); ba.append(']'); + needsBraces = true; } const char *ptr = ba.constData(); if (!_IPLiteral(&ptr)) that->host.clear(); + else if (needsBraces) + that->host = QString::fromLatin1(ba.toLower()); else that->host = host.toLower(); } else { that->host = qt_ACE_do(host, NormalizeAce); - if (that->host.isNull()) - that->isHostValid = false; } + that->isHostValid = !that->host.isNull(); return that->host; } @@ -3777,6 +3779,10 @@ void QUrlPrivate::validate() const QString auth = authority(); // causes the non-encoded forms to be valid + // authority() calls canonicalHost() which sets this + if (!isHostValid) + return; + if (scheme == QLatin1String("mailto")) { if (!host.isEmpty() || port != -1 || !userName.isEmpty() || !password.isEmpty()) { that->isValid = false; @@ -3950,9 +3956,10 @@ QByteArray QUrlPrivate::toEncoded(QUrl::FormattingOptions options) const url += scheme.toLatin1(); url += ':'; } + QString savedHost = host; // pre-validation, may be invalid! QString auth = authority(); bool doFileScheme = scheme == QLatin1String("file") && encodedPath.startsWith('/'); - if ((options & QUrl::RemoveAuthority) != QUrl::RemoveAuthority && (!auth.isEmpty() || doFileScheme)) { + if ((options & QUrl::RemoveAuthority) != QUrl::RemoveAuthority && (!auth.isEmpty() || doFileScheme || !savedHost.isEmpty())) { if (doFileScheme && !encodedPath.startsWith('/')) url += '/'; url += "//"; @@ -3978,6 +3985,12 @@ QByteArray QUrlPrivate::toEncoded(QUrl::FormattingOptions options) const url += '['; url += host.toLatin1(); url += ']'; + } else if (host.isEmpty() && !savedHost.isEmpty()) { + // this case is only possible with an invalid URL + // it's here only so that we can keep the original, invalid hostname + // in encodedOriginal. + // QUrl::isValid() will return false, so toEncoded() can be anything (it's not valid) + url += savedHost.toUtf8(); } else { url += QUrl::toAce(host); } @@ -4097,7 +4110,7 @@ const QByteArray &QUrlPrivate::normalized() const QString QUrlPrivate::createErrorString() { - if (isValid) + if (isValid && isHostValid) return QString(); QString errorString(QLatin1String(QT_TRANSLATE_NOOP(QUrl, "Invalid URL \""))); @@ -4121,7 +4134,10 @@ QString QUrlPrivate::createErrorString() errorString += QLatin1String(QT_TRANSLATE_NOOP(QUrl, "\'")); } else { errorString += QLatin1String(QT_TRANSLATE_NOOP(QUrl, ": ")); - errorString += QLatin1String(errorInfo._message); + if (isHostValid) + errorString += QLatin1String(errorInfo._message); + else + errorString += QLatin1String(QT_TRANSLATE_NOOP(QUrl, "invalid hostname")); } if (errorInfo._found) { errorString += QLatin1String(QT_TRANSLATE_NOOP(QUrl, ", but found \'")); @@ -4484,7 +4500,7 @@ void QUrl::setAuthority(const QString &authority) if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); detach(); - QURL_UNSETFLAG(d->stateFlags, QUrlPrivate::Validated | QUrlPrivate::Normalized); + QURL_UNSETFLAG(d->stateFlags, QUrlPrivate::Validated | QUrlPrivate::Normalized | QUrlPrivate::HostCanonicalized); d->setAuthority(authority); } @@ -5005,6 +5021,10 @@ void QUrl::setEncodedQuery(const QByteArray &query) pairDelimiter(), and the key and value are delimited by valueDelimiter(). + \note This method does not encode spaces (ASCII 0x20) as plus (+) signs, + like HTML forms do. If you need that kind of encoding, you must encode + the value yourself and use QUrl::setEncodedQueryItems. + \sa setQueryDelimiters(), queryItems(), setEncodedQueryItems() */ void QUrl::setQueryItems(const QList<QPair<QString, QString> > &query) @@ -5075,6 +5095,10 @@ void QUrl::setEncodedQueryItems(const QList<QPair<QByteArray, QByteArray> > &que character returned by valueDelimiter(). Each key/value pair is delimited by the character returned by pairDelimiter(). + \note This method does not encode spaces (ASCII 0x20) as plus (+) signs, + like HTML forms do. If you need that kind of encoding, you must encode + the value yourself and use QUrl::addEncodedQueryItem. + \sa addEncodedQueryItem() */ void QUrl::addQueryItem(const QString &key, const QString &value) @@ -5131,6 +5155,10 @@ void QUrl::addEncodedQueryItem(const QByteArray &key, const QByteArray &value) /*! Returns the query string of the URL, as a map of keys and values. + \note This method does not decode spaces plus (+) signs as spaces (ASCII + 0x20), like HTML forms do. If you need that kind of decoding, you must + use QUrl::encodedQueryItems and decode the data yourself. + \sa setQueryItems(), setEncodedQuery() */ QList<QPair<QString, QString> > QUrl::queryItems() const @@ -5235,6 +5263,10 @@ bool QUrl::hasEncodedQueryItem(const QByteArray &key) const Returns the first query string value whose key is equal to \a key from the URL. + \note This method does not decode spaces plus (+) signs as spaces (ASCII + 0x20), like HTML forms do. If you need that kind of decoding, you must + use QUrl::encodedQueryItemValue and decode the data yourself. + \sa allQueryItemValues() */ QString QUrl::queryItemValue(const QString &key) const @@ -5279,6 +5311,10 @@ QByteArray QUrl::encodedQueryItemValue(const QByteArray &key) const Returns the a list of query string values whose key is equal to \a key from the URL. + \note This method does not decode spaces plus (+) signs as spaces (ASCII + 0x20), like HTML forms do. If you need that kind of decoding, you must + use QUrl::allEncodedQueryItemValues and decode the data yourself. + \sa queryItemValue() */ QStringList QUrl::allQueryItemValues(const QString &key) const @@ -5657,7 +5693,7 @@ QString QUrl::toString(FormattingOptions options) const if ((options & QUrl::RemoveAuthority) != QUrl::RemoveAuthority) { bool doFileScheme = d->scheme == QLatin1String("file") && ourPath.startsWith(QLatin1Char('/')); QString tmp = d->authority(options); - if (!tmp.isEmpty() || doFileScheme) { + if (!tmp.isNull() || doFileScheme) { if (doFileScheme && !ourPath.startsWith(QLatin1Char('/'))) url += QLatin1Char('/'); url += QLatin1String("//"); diff --git a/src/corelib/io/qurl.h b/src/corelib/io/qurl.h index 162aa7c..563be5f 100644 --- a/src/corelib/io/qurl.h +++ b/src/corelib/io/qurl.h @@ -94,6 +94,10 @@ public: #ifndef QT_NO_URL_CAST_FROM_STRING QUrl &operator =(const QString &url); #endif +#ifdef Q_COMPILER_RVALUE_REFS + inline QUrl &operator=(QUrl &&other) + { qSwap(d, other.d); return *this; } +#endif ~QUrl(); void setUrl(const QString &url); diff --git a/src/corelib/kernel/qabstractitemmodel.cpp b/src/corelib/kernel/qabstractitemmodel.cpp index 3a6395b..4fc9792 100644 --- a/src/corelib/kernel/qabstractitemmodel.cpp +++ b/src/corelib/kernel/qabstractitemmodel.cpp @@ -2603,9 +2603,13 @@ bool QAbstractItemModel::beginMoveRows(const QModelIndex &sourceParent, int sour return false; } - d->changes.push(QAbstractItemModelPrivate::Change(sourceParent, sourceFirst, sourceLast)); + QAbstractItemModelPrivate::Change sourceChange(sourceParent, sourceFirst, sourceLast); + sourceChange.needsAdjust = sourceParent.isValid() && sourceParent.row() >= destinationChild && sourceParent.parent() == destinationParent; + d->changes.push(sourceChange); int destinationLast = destinationChild + (sourceLast - sourceFirst); - d->changes.push(QAbstractItemModelPrivate::Change(destinationParent, destinationChild, destinationLast)); + QAbstractItemModelPrivate::Change destinationChange(destinationParent, destinationChild, destinationLast); + destinationChange.needsAdjust = destinationParent.isValid() && destinationParent.row() >= sourceLast && destinationParent.parent() == sourceParent; + d->changes.push(destinationChange); emit rowsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild); emit layoutAboutToBeChanged(); @@ -2635,7 +2639,17 @@ void QAbstractItemModel::endMoveRows() d->itemsMoved(removeChange.parent, removeChange.first, removeChange.last, insertChange.parent, insertChange.first, Qt::Vertical); - emit rowsMoved(removeChange.parent, removeChange.first, removeChange.last, insertChange.parent, insertChange.first); + QModelIndex adjustedSource = removeChange.parent; + QModelIndex adjustedDestination = insertChange.parent; + + const int numMoved = removeChange.last - removeChange.first + 1; + if (insertChange.needsAdjust) + adjustedDestination = createIndex(adjustedDestination.row() - numMoved, adjustedDestination.column(), adjustedDestination.internalPointer()); + + if (removeChange.needsAdjust) + adjustedSource = createIndex(adjustedSource.row() + numMoved, adjustedSource.column(), adjustedSource.internalPointer()); + + emit rowsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first); emit layoutChanged(); } @@ -2812,9 +2826,13 @@ bool QAbstractItemModel::beginMoveColumns(const QModelIndex &sourceParent, int s return false; } - d->changes.push(QAbstractItemModelPrivate::Change(sourceParent, sourceFirst, sourceLast)); + QAbstractItemModelPrivate::Change sourceChange(sourceParent, sourceFirst, sourceLast); + sourceChange.needsAdjust = sourceParent.isValid() && sourceParent.row() >= destinationChild && sourceParent.parent() == destinationParent; + d->changes.push(sourceChange); int destinationLast = destinationChild + (sourceLast - sourceFirst); - d->changes.push(QAbstractItemModelPrivate::Change(destinationParent, destinationChild, destinationLast)); + QAbstractItemModelPrivate::Change destinationChange(destinationParent, destinationChild, destinationLast); + destinationChange.needsAdjust = destinationParent.isValid() && destinationParent.row() >= sourceLast && destinationParent.parent() == sourceParent; + d->changes.push(destinationChange); d->itemsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Horizontal); @@ -2845,7 +2863,17 @@ void QAbstractItemModel::endMoveColumns() d->itemsMoved(removeChange.parent, removeChange.first, removeChange.last, insertChange.parent, insertChange.first, Qt::Horizontal); - emit columnsMoved(removeChange.parent, removeChange.first, removeChange.last, insertChange.parent, insertChange.first); + QModelIndex adjustedSource = removeChange.parent; + QModelIndex adjustedDestination = insertChange.parent; + + const int numMoved = removeChange.last - removeChange.first + 1; + if (insertChange.needsAdjust) + adjustedDestination = createIndex(adjustedDestination.row(), adjustedDestination.column() - numMoved, adjustedDestination.internalPointer()); + + if (removeChange.needsAdjust) + adjustedSource = createIndex(adjustedSource.row(), adjustedSource.column() + numMoved, adjustedSource.internalPointer()); + + emit columnsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first); emit layoutChanged(); } diff --git a/src/corelib/kernel/qabstractitemmodel_p.h b/src/corelib/kernel/qabstractitemmodel_p.h index 7844a10..3113dff 100644 --- a/src/corelib/kernel/qabstractitemmodel_p.h +++ b/src/corelib/kernel/qabstractitemmodel_p.h @@ -133,11 +133,26 @@ public: struct Change { Change() : first(-1), last(-1) {} - Change(const Change &c) : parent(c.parent), first(c.first), last(c.last) {} - Change(const QModelIndex &p, int f, int l) : parent(p), first(f), last(l) {} + Change(const Change &c) : parent(c.parent), first(c.first), last(c.last), needsAdjust(c.needsAdjust) {} + Change(const QModelIndex &p, int f, int l) : parent(p), first(f), last(l), needsAdjust(false) {} QModelIndex parent; int first, last; + + // In cases such as this: + // - A + // - B + // - C + // - - D + // - - E + // - - F + // + // If B is moved to above E, C is the source parent in the signal and its row is 2. When the move is + // completed however, C is at row 1 and there is no row 2 at the same level in the model at all. + // The QModelIndex is adjusted to correct that in those cases before reporting it though the + // rowsMoved signal. + bool needsAdjust; + bool isValid() { return first >= 0 && last >= 0; } }; QStack<Change> changes; diff --git a/src/corelib/kernel/qcore_symbian_p.cpp b/src/corelib/kernel/qcore_symbian_p.cpp index 073ed6b..df1c1ef 100644 --- a/src/corelib/kernel/qcore_symbian_p.cpp +++ b/src/corelib/kernel/qcore_symbian_p.cpp @@ -133,7 +133,6 @@ public: private: void init() { -#ifdef Q_OS_SYMBIAN _LIT(KLibName_3_1, "qts60plugin_3_1" QT_LIBINFIX_UNICODE L".dll"); _LIT(KLibName_3_2, "qts60plugin_3_2" QT_LIBINFIX_UNICODE L".dll"); _LIT(KLibName_5_0, "qts60plugin_5_0" QT_LIBINFIX_UNICODE L".dll"); @@ -159,7 +158,12 @@ private: TUidType libUid(KDynamicLibraryUid, KSharedLibraryUid, TUid::Uid(uidValue)); lib.Load(libName, libUid); -#endif + + // Duplicate lib handle to enable process wide access to it. Since Duplicate overwrites + // existing handle without closing it, store original for subsequent closing. + RLibrary origHandleCloser = lib; + lib.Duplicate(RThread(), EOwnerProcess); + origHandleCloser.Close(); } RLibrary lib; diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index d94cf6d..4abe0ae 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -2122,7 +2122,8 @@ QStringList QCoreApplication::arguments() l1arg == "-stylesheet" || l1arg == "-widgetcount") ; - else if (l1arg.startsWith("-style=")) + else if (l1arg.startsWith("-style=") || + l1arg.startsWith("-qmljsdebugger=")) ; else if (l1arg == "-style" || l1arg == "-session" || diff --git a/src/corelib/kernel/qeventdispatcher_symbian.cpp b/src/corelib/kernel/qeventdispatcher_symbian.cpp index 5ab867f..02736dd 100644 --- a/src/corelib/kernel/qeventdispatcher_symbian.cpp +++ b/src/corelib/kernel/qeventdispatcher_symbian.cpp @@ -232,8 +232,12 @@ void QTimerActiveObject::DoCancel() void QTimerActiveObject::RunL() { - int error; - QT_TRYCATCH_ERROR(error, Run()); + int error = KErrNone; + if (iStatus == KErrNone) { + QT_TRYCATCH_ERROR(error, Run()); + } else { + error = iStatus.Int(); + } // All Symbian error codes are negative. if (error < 0) { CActiveScheduler::Current()->Error(error); // stop and report here, as this timer will be deleted on scope exit diff --git a/src/corelib/kernel/qeventdispatcher_unix.cpp b/src/corelib/kernel/qeventdispatcher_unix.cpp index 9dadd82..f50994c 100644 --- a/src/corelib/kernel/qeventdispatcher_unix.cpp +++ b/src/corelib/kernel/qeventdispatcher_unix.cpp @@ -549,18 +549,22 @@ int QTimerInfoList::activateTimers() if (qt_disable_lowpriority_timers || isEmpty()) return 0; // nothing to do - bool firstTime = true; - timeval currentTime; - int n_act = 0, maxCount = count(); + int n_act = 0, maxCount = 0; firstTimerInfo = 0; - while (maxCount--) { - currentTime = updateCurrentTime(); - if (firstTime) { - repairTimersIfNeeded(); - firstTime = false; - } + timeval currentTime = updateCurrentTime(); + repairTimersIfNeeded(); + + // Find out how many timer have expired + for (QTimerInfoList::const_iterator it = constBegin(); it != constEnd(); ++it) { + if (currentTime < (*it)->timeout) + break; + maxCount++; + } + + //fire the timers. + while (maxCount--) { if (isEmpty()) break; diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index e3f537f..153ccdf 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -43,7 +43,7 @@ #include "qcoreapplication.h" #include "qhash.h" -#include "qlibrary.h" +#include <private/qsystemlibrary_p.h> #include "qpair.h" #include "qset.h" #include "qsocketnotifier.h" @@ -65,7 +65,11 @@ extern uint qGlobalPostedEventsCount(); #endif #ifndef QS_RAWINPUT +# ifdef Q_OS_WINCE +# define QS_RAWINPUT 0x0000 +# else # define QS_RAWINPUT 0x0400 +# endif #endif #ifndef WM_TOUCH @@ -80,8 +84,7 @@ extern uint qGlobalPostedEventsCount(); enum { WM_QT_SOCKETNOTIFIER = WM_USER, - WM_QT_SENDPOSTEDEVENTS = WM_USER + 1, - SendPostedEventsTimerId = ~1u + WM_QT_SENDPOSTEDEVENTS = WM_USER + 1 }; #if defined(Q_OS_WINCE) @@ -323,11 +326,11 @@ static void resolveTimerAPI() #endif triedResolve = true; #if !defined(Q_OS_WINCE) - qtimeSetEvent = (ptimeSetEvent)QLibrary::resolve(QLatin1String("winmm"), "timeSetEvent"); - qtimeKillEvent = (ptimeKillEvent)QLibrary::resolve(QLatin1String("winmm"), "timeKillEvent"); + qtimeSetEvent = (ptimeSetEvent)QSystemLibrary::resolve(QLatin1String("winmm"), "timeSetEvent"); + qtimeKillEvent = (ptimeKillEvent)QSystemLibrary::resolve(QLatin1String("winmm"), "timeKillEvent"); #else - qtimeSetEvent = (ptimeSetEvent)QLibrary::resolve(QLatin1String("Mmtimer"), "timeSetEvent"); - qtimeKillEvent = (ptimeKillEvent)QLibrary::resolve(QLatin1String("Mmtimer"), "timeKillEvent"); + qtimeSetEvent = (ptimeSetEvent)QSystemLibrary::resolve(QLatin1String("Mmtimer"), "timeSetEvent"); + qtimeKillEvent = (ptimeKillEvent)QSystemLibrary::resolve(QLatin1String("Mmtimer"), "timeKillEvent"); #endif } } @@ -516,12 +519,10 @@ LRESULT QT_WIN_CALLBACK qt_GetMessageHook(int code, WPARAM wp, LPARAM lp) if (q) { QEventDispatcherWin32Private *d = q->d_func(); int localSerialNumber = d->serialNumber; -#ifdef Q_OS_WINCE - MSG dummyMsg; - if (HIWORD(GetQueueStatus(QS_INPUT)) == 0 - && PeekMessage(&dummyMsg, 0, WM_TIMER, WM_TIMER, PM_NOREMOVE) == 0 -#else - if (HIWORD(GetQueueStatus(QS_INPUT | QS_RAWINPUT | QS_TIMER)) == 0 + MSG unused; + if ((HIWORD(GetQueueStatus(QS_INPUT | QS_RAWINPUT)) == 0 + && PeekMessage(&unused, 0, WM_TIMER, WM_TIMER, PM_NOREMOVE) == 0) +#ifndef Q_OS_WINCE || GetMessageTime() - d->lastMessageTime >= 10 #endif ) { @@ -824,7 +825,7 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags) pHandles[i] = d->winEventNotifierList.at(i)->handle(); emit aboutToBlock(); - waitRet = MsgWaitForMultipleObjectsEx(nCount, pHandles, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE); + waitRet = MsgWaitForMultipleObjectsEx(nCount, pHandles, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE | MWMO_INPUTAVAILABLE); emit awake(); if (waitRet >= WAIT_OBJECT_0 && waitRet < WAIT_OBJECT_0 + nCount) { d->activateEventNotifier(d->winEventNotifierList.at(waitRet - WAIT_OBJECT_0)); diff --git a/src/corelib/kernel/qmath.qdoc b/src/corelib/kernel/qmath.qdoc new file mode 100644 index 0000000..48f74b6 --- /dev/null +++ b/src/corelib/kernel/qmath.qdoc @@ -0,0 +1,155 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in a +** written agreement between you and Nokia. +** +** GNU Free Documentation License +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of this +** file. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \headerfile <QtCore/qmath.h> + \title Math Functions + \ingroup funclists + \brief The <QtCore/qmath.h> header provides various math functions. + \pagekeywords math trigonometry qmath floor ceiling absolute sine cosine tangent inverse tan exponent power natural logarithm +*/ + +/*! + \fn int qCeil(qreal v) + Return the ceiling of the value \a v. + + The ceiling is the smallest integer that is not less than \a v. + For example, if \a v is 41.2, then the ceiling is 42. + + \relates <QtCore/qmath.h> + \sa qFloor() +*/ + +/*! + \fn int qFloor(qreal v) + Return the floor of the value \a v. + + The floor is the largest integer that is not greater than \a v. + For example, if \a v is 41.2, then the floor is 41. + + \relates <QtCore/qmath.h> + \sa qCeil() +*/ + +/*! + \fn qreal qFabs(qreal v) + Returns the absolute value of \a v as a qreal. +*/ + +/*! + \fn qreal qSin(qreal v) + Returns the sine of the angle \a v in radians. + + \relates <QtCore/qmath.h> + \sa qCos(), qTan() +*/ + +/*! + \fn qreal qCos(qreal v) + Returns the cosine of an angle \a v in radians. + + \relates <QtCore/qmath.h> + \sa qSin(), qTan() +*/ + +/*! + \fn qreal qTan(qreal v) + Returns the tangent of an angle \a v in radians. + + \relates <QtCore/qmath.h> + \sa qSin(), qCos() +*/ + +/*! + \fn qreal qAcos(qreal v) + Returns the arccosine of \a v as an angle in radians. + Arccosine is the inverse operation of cosine. + + \relates <QtCore/qmath.h> + \sa qAtan(), qAsin(), qCos() +*/ + +/*! + \fn qreal qAsin(qreal v) + Returns the arcsine of \a v as an angle in radians. + Arcsine is the inverse operation of sine. + + \relates <QtCore/qmath.h> + \sa qSin(), qAtan(), qAcos() +*/ + +/*! + \fn qreal qAtan(qreal v) + Returns the arctangent of \a v as an angle in radians. + Arctangent is the inverse operation of tangent. + + \relates <QtCore/qmath.h> + \sa qTan(), qAcos(), qAsin() +*/ + +/*! + \fn qreal qAtan2(qreal x, qreal y) + Returns the arctangent of a point specified by the coordinates \a x and \a y. + This function will return the angle and its direction. + + \relates <QtCore/qmath.h> + \sa qAtan() +*/ + +/*! + \fn qreal qSqrt(qreal v) + Returns the square root of \a v. + This function returns a NaN if \a v is a negative number. + + \relates <QtCore/qmath.h> + \sa qPow() +*/ + +/*! + \fn qreal qLn(qreal v) + Returns the natural logarithm of \a v. Natural logarithm uses base e. + + \relates <QtCore/qmath.h> + \sa qExp() +*/ + +/*! + \fn qreal qExp(qreal v) + Returns the exponential function of \c e to the power of \a v. + + \relates <QtCore/qmath.h> + \sa qLn() +*/ + +/*! + \fn qreal qPow(qreal x, qreal y) + Returns the value of \a x raised to the power of \a y. + That is, \a x is the base and \a y is the exponent. + + \relates <QtCore/qmath.h> + \sa qSqrt() +*/ diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index a70772f..ceb2a9c 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -266,7 +266,25 @@ QObject *QMetaObject::cast(QObject *obj) const const QMetaObject *m = obj->metaObject(); do { if (m == this) - return const_cast<QObject*>(obj); + return obj; + } while ((m = m->d.superdata)); + } + return 0; +} + +/*! + \internal + + Returns \a obj if object \a obj inherits from this + meta-object; otherwise returns 0. +*/ +const QObject *QMetaObject::cast(const QObject *obj) const +{ + if (obj) { + const QMetaObject *m = obj->metaObject(); + do { + if (m == this) + return obj; } while ((m = m->d.superdata)); } return 0; diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index 52efcd0..eebb3db 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -156,7 +156,18 @@ void qMetaTypeLoadHelper(QDataStream &stream, T *t) } #endif // QT_NO_DATASTREAM -template <typename T> struct QMetaTypeId2; +template <typename T> +struct QMetaTypeId +{ + enum { Defined = 0 }; +}; + +template <typename T> +struct QMetaTypeId2 +{ + enum { Defined = QMetaTypeId<T>::Defined }; + static inline int qt_metatype_id() { return QMetaTypeId<T>::qt_metatype_id(); } +}; namespace QtPrivate { template <typename T, bool Defined = QMetaTypeId2<T>::Defined> @@ -210,19 +221,6 @@ void qRegisterMetaTypeStreamOperators(const char *typeName #endif // QT_NO_DATASTREAM template <typename T> -struct QMetaTypeId -{ - enum { Defined = 0 }; -}; - -template <typename T> -struct QMetaTypeId2 -{ - enum { Defined = QMetaTypeId<T>::Defined }; - static inline int qt_metatype_id() { return QMetaTypeId<T>::qt_metatype_id(); } -}; - -template <typename T> inline int qMetaTypeId( #ifndef qdoc T * /* dummy */ = 0 diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index b5db936..63fdf76 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -351,7 +351,7 @@ inline QT_DEPRECATED T qFindChild(const QObject *o, const QString &name = QStrin { return o->findChild<T>(name); } template<typename T> -inline QList<T> qFindChildren(const QObject *o, const QString &name = QString()) +inline QT_DEPRECATED QList<T> qFindChildren(const QObject *o, const QString &name = QString()) { return o->findChildren<T>(name); } @@ -378,14 +378,10 @@ inline T qobject_cast(QObject *object) template <class T> inline T qobject_cast(const QObject *object) { - // this will cause a compilation error if T is not const - register T ptr = static_cast<T>(object); - Q_UNUSED(ptr); - #if !defined(QT_NO_QOBJECT_CHECK) reinterpret_cast<T>(0)->qt_check_for_QOBJECT_macro(*reinterpret_cast<T>(const_cast<QObject *>(object))); #endif - return static_cast<T>(const_cast<QObject *>(reinterpret_cast<T>(0)->staticMetaObject.cast(const_cast<QObject *>(object)))); + return static_cast<T>(reinterpret_cast<T>(0)->staticMetaObject.cast(object)); } diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h index 996fce2..db46ba5 100644 --- a/src/corelib/kernel/qobjectdefs.h +++ b/src/corelib/kernel/qobjectdefs.h @@ -298,6 +298,7 @@ struct Q_CORE_EXPORT QMetaObject const QMetaObject *superClass() const; QObject *cast(QObject *obj) const; + const QObject *cast(const QObject *obj) const; #ifndef QT_NO_TRANSLATION // ### Qt 4: Merge overloads diff --git a/src/corelib/kernel/qpointer.cpp b/src/corelib/kernel/qpointer.cpp index 5cd0220..fbfb961 100644 --- a/src/corelib/kernel/qpointer.cpp +++ b/src/corelib/kernel/qpointer.cpp @@ -41,7 +41,7 @@ /*! \class QPointer - \brief The QPointer class is a template class that provides guarded pointers to QObjects. + \brief The QPointer class is a template class that provides guarded pointers to QObject. \ingroup objectmodel diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index a4d45f6..b267954 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -219,6 +219,10 @@ class Q_CORE_EXPORT QVariant QVariant(Qt::GlobalColor color); QVariant& operator=(const QVariant &other); +#ifdef Q_COMPILER_RVALUE_REFS + inline QVariant &operator=(QVariant &&other) + { qSwap(d, other.d); return *this; } +#endif Type type() const; int userType() const; diff --git a/src/corelib/plugin/plugin.pri b/src/corelib/plugin/plugin.pri index c05ff48..50b005d 100644 --- a/src/corelib/plugin/plugin.pri +++ b/src/corelib/plugin/plugin.pri @@ -7,16 +7,21 @@ HEADERS += \ plugin/qlibrary_p.h \ plugin/qplugin.h \ plugin/quuid.h \ - plugin/qfactoryloader_p.h + plugin/qfactoryloader_p.h \ + plugin/qsystemlibrary_p.h \ + plugin/qelfparser_p.h SOURCES += \ plugin/qpluginloader.cpp \ plugin/qfactoryloader.cpp \ plugin/quuid.cpp \ - plugin/qlibrary.cpp + plugin/qlibrary.cpp \ + plugin/qelfparser_p.cpp win32 { - SOURCES += plugin/qlibrary_win.cpp + SOURCES += \ + plugin/qlibrary_win.cpp \ + plugin/qsystemlibrary.cpp } unix { diff --git a/src/corelib/plugin/qelfparser_p.cpp b/src/corelib/plugin/qelfparser_p.cpp new file mode 100644 index 0000000..2e77ae7 --- /dev/null +++ b/src/corelib/plugin/qelfparser_p.cpp @@ -0,0 +1,234 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qlibrary_p.h" +#include "qelfparser_p.h" +#include <qdebug.h> + +QT_BEGIN_NAMESPACE + +// #define QELFPARSER_DEBUG 1 + +const char *QElfParser::parseSectionHeader(const char *data, ElfSectionHeader *sh) +{ + sh->name = read<qelfword_t>(data); + data += sizeof(qelfword_t); // sh_name + sh->type = read<qelfword_t>(data); + data += sizeof(qelfword_t) // sh_type + + sizeof(qelfaddr_t) // sh_flags + + sizeof(qelfaddr_t); // sh_addr + sh->offset = read<qelfoff_t>(data); + data += sizeof(qelfoff_t); // sh_offset + sh->size = read<qelfword_t>(data); + data += sizeof(qelfword_t); // sh_size + return data; +} + +int QElfParser::parse(const char *dataStart, ulong fdlen, const QString &library, QLibraryPrivate *lib, long *pos, ulong *sectionlen) +{ +#if defined(QELFPARSER_DEBUG) + qDebug() << "QElfParser::parse " << library; +#endif + + if (fdlen < 64){ + if (lib) + lib->errorString = QLibrary::tr("'%1' is not an ELF object (%2)").arg(library).arg(QLatin1String("file too small")); + return NotElf; + } + const char *data = dataStart; + if (qstrncmp(data, "\177ELF", 4) != 0) { + if (lib) + lib->errorString = QLibrary::tr("'%1' is not an ELF object").arg(library); + return NotElf; + } + // 32 or 64 bit + if (data[4] != 1 && data[4] != 2) { + if (lib) + lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library).arg(QLatin1String("odd cpu architecture")); + return Corrupt; + } + m_bits = (data[4] << 5); + + /* If you remove this check, to read ELF objects of a different arch, please make sure you modify the typedefs + to match the _plugin_ architecture. + */ + if ((sizeof(void*) == 4 && m_bits != 32) || (sizeof(void*) == 8 && m_bits != 64)) { + if (lib) + lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library).arg(QLatin1String("wrong cpu architecture")); + return Corrupt; + } + // endian + if (data[5] == 0) { + if (lib) + lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library).arg(QLatin1String("odd endianess")); + return Corrupt; + } + m_endian = (data[5] == 1 ? ElfLittleEndian : ElfBigEndian); + + data += 16 // e_ident + + sizeof(qelfhalf_t) // e_type + + sizeof(qelfhalf_t) // e_machine + + sizeof(qelfword_t) // e_version + + sizeof(qelfaddr_t) // e_entry + + sizeof(qelfoff_t); // e_phoff + + qelfoff_t e_shoff = read<qelfoff_t> (data); + data += sizeof(qelfoff_t) // e_shoff + + sizeof(qelfword_t); // e_flags + + qelfhalf_t e_shsize = read<qelfhalf_t> (data); + + if (e_shsize > fdlen) { + if (lib) + lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library).arg(QLatin1String("unexpected e_shsize")); + return Corrupt; + } + + data += sizeof(qelfhalf_t) // e_ehsize + + sizeof(qelfhalf_t) // e_phentsize + + sizeof(qelfhalf_t); // e_phnum + + qelfhalf_t e_shentsize = read<qelfhalf_t> (data); + + if (e_shentsize % 4){ + if (lib) + lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library).arg(QLatin1String("unexpected e_shentsize")); + return Corrupt; + } + data += sizeof(qelfhalf_t); // e_shentsize + qelfhalf_t e_shnum = read<qelfhalf_t> (data); + data += sizeof(qelfhalf_t); // e_shnum + qelfhalf_t e_shtrndx = read<qelfhalf_t> (data); + data += sizeof(qelfhalf_t); // e_shtrndx + + if ((e_shnum * e_shentsize) > fdlen) { + if (lib) + lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library) + .arg(QLatin1String("announced %2 sections, each %3 bytes, exceed file size")) + .arg(e_shnum).arg(e_shentsize); + return Corrupt; + } + +#if defined(QELFPARSER_DEBUG) + qDebug() << e_shnum << "sections starting at " << ("0x" + QByteArray::number(e_shoff, 16)).data() << "each" << e_shentsize << "bytes"; +#endif + + ElfSectionHeader strtab; + qulonglong soff = e_shoff + e_shentsize * (e_shtrndx); + + if ((soff + e_shentsize) > fdlen || soff % 4 || soff == 0) { + if (lib) + lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library) + .arg(QLatin1String("shstrtab section header seems to be at %1")) + .arg(QString::number(soff, 16)); + return Corrupt; + } + + parseSectionHeader(dataStart + soff, &strtab); + m_stringTableFileOffset = strtab.offset; + + if ((m_stringTableFileOffset + e_shentsize) >= fdlen || m_stringTableFileOffset == 0) { + if (lib) + lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library) + .arg(QLatin1String("string table seems to be at %1")) + .arg(QString::number(soff, 16)); + return Corrupt; + } + +#if defined(QELFPARSER_DEBUG) + qDebug(".shstrtab at 0x%s", QByteArray::number(m_stringTableFileOffset, 16).data()); +#endif + + const char *s = dataStart + e_shoff; + for (int i = 0; i < e_shnum; ++i) { + ElfSectionHeader sh; + parseSectionHeader(s, &sh); + if (sh.name == 0) { + s += e_shentsize; + continue; + } + const char *shnam = dataStart + m_stringTableFileOffset + sh.name; + + if (m_stringTableFileOffset + sh.name > fdlen) { + if (lib) + lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library) + .arg(QLatin1String("section name %2 of %3 behind end of file")) + .arg(i).arg(e_shnum); + return Corrupt; + } + +#if defined(QELFPARSER_DEBUG) + qDebug() << "++++" << i << shnam; +#endif + + if (qstrcmp(shnam, ".qtplugin") == 0 || qstrcmp(shnam, ".rodata") == 0) { + if (!(sh.type & 0x1)) { + if (shnam[1] == 'r') { + if (lib) + lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library) + .arg(QLatin1String("empty .rodata. not a library.")); + return Corrupt; + } +#if defined(QELFPARSER_DEBUG) + qDebug()<<"section is not program data. skipped."; +#endif + s += e_shentsize; + continue; + } + + if (sh.offset == 0 || (sh.offset + sh.size) > fdlen) { + if (lib) + lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library) + .arg(QLatin1String("missing section data. This is not a library.")); + return Corrupt; + } + *pos = sh.offset; + *sectionlen = sh.size - 1; + if (shnam[1] == 'q') + return Ok; + } + s += e_shentsize; + } + return NoQtSection; +} + +QT_END_NAMESPACE + diff --git a/src/corelib/plugin/qelfparser_p.h b/src/corelib/plugin/qelfparser_p.h new file mode 100644 index 0000000..380d5a1 --- /dev/null +++ b/src/corelib/plugin/qelfparser_p.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QELFPARSER_P_H +#define QELFPARSER_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 <qendian.h> +#include <qglobal.h> + +QT_BEGIN_NAMESPACE + +class QString; +class QLibraryPrivate; + +typedef quint16 qelfhalf_t; +typedef quint32 qelfword_t; +typedef quintptr qelfoff_t; +typedef quintptr qelfaddr_t; + +class QElfParser +{ +public: + enum {Ok = 0, NotElf = 1, NoQtSection = 2, Corrupt = 3}; + enum {ElfLittleEndian = 0, ElfBigEndian = 1}; + + struct ElfSectionHeader + { + qelfword_t name; + qelfword_t type; + qelfoff_t offset; + qelfword_t size; + }; + + int m_endian; + int m_bits; + int m_stringTableFileOffset; + + template <typename T> + T read(const char *s) + { + if (m_endian == ElfBigEndian) + return qFromBigEndian<T>(reinterpret_cast<const uchar *>(s)); + else + return qFromLittleEndian<T>(reinterpret_cast<const uchar *>(s)); + } + + const char *parseSectionHeader(const char* s, ElfSectionHeader *sh); + int parse(const char *m_s, ulong fdlen, const QString &library, QLibraryPrivate *lib, long *pos, ulong *sectionlen); +}; + +QT_END_NAMESPACE + +#endif // QELFPARSER_P_H + diff --git a/src/corelib/plugin/qfactoryloader.cpp b/src/corelib/plugin/qfactoryloader.cpp index 62d565a..a26dcd8 100644 --- a/src/corelib/plugin/qfactoryloader.cpp +++ b/src/corelib/plugin/qfactoryloader.cpp @@ -244,6 +244,14 @@ QObject *QFactoryLoader::instance(const QString &key) const return 0; } +#ifdef Q_WS_X11 +QLibraryPrivate *QFactoryLoader::library(const QString &key) const +{ + Q_D(const QFactoryLoader); + return d->keyMap.value(d->cs ? key : key.toLower()); +} +#endif + void QFactoryLoader::refreshAll() { QMutexLocker locker(qt_factoryloader_mutex()); diff --git a/src/corelib/plugin/qfactoryloader_p.h b/src/corelib/plugin/qfactoryloader_p.h index 10e6e2a..068c6c7 100644 --- a/src/corelib/plugin/qfactoryloader_p.h +++ b/src/corelib/plugin/qfactoryloader_p.h @@ -77,6 +77,10 @@ public: QStringList keys() const; QObject *instance(const QString &key) const; +#ifdef Q_WS_X11 + QLibraryPrivate *library(const QString &key) const; +#endif + void update(); static void refreshAll(); diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp index f6ae038..f812275 100644 --- a/src/corelib/plugin/qlibrary.cpp +++ b/src/corelib/plugin/qlibrary.cpp @@ -38,7 +38,6 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ - #include "qplatformdefs.h" #include "qlibrary.h" @@ -61,11 +60,10 @@ #include <qdebug.h> #include <qvector.h> #include <qdir.h> +#include "qelfparser_p.h" QT_BEGIN_NAMESPACE -//#define QT_DEBUG_COMPONENT - #ifdef QT_NO_DEBUG # define QLIBRARY_AS_DEBUG false #else @@ -295,14 +293,6 @@ static bool qt_parse_pattern(const char *s, uint *version, bool *debug, QByteArr #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) && !defined(Q_OS_SYMBIAN) && !defined(QT_NO_PLUGIN_CHECK) -#if defined(Q_OS_FREEBSD) || defined(Q_OS_LINUX) -# define USE_MMAP -QT_BEGIN_INCLUDE_NAMESPACE -# include <sys/types.h> -# include <sys/mman.h> -QT_END_INCLUDE_NAMESPACE -#endif // Q_OS_FREEBSD || Q_OS_LINUX - static long qt_find_pattern(const char *s, ulong s_len, const char *pattern, ulong p_len) { @@ -363,57 +353,51 @@ static bool qt_unix_query(const QString &library, uint *version, bool *debug, QB } QByteArray data; - char *filedata = 0; - ulong fdlen = 0; - -# ifdef USE_MMAP - char *mapaddr = 0; - size_t maplen = file.size(); - mapaddr = (char *) mmap(mapaddr, maplen, PROT_READ, MAP_PRIVATE, file.handle(), 0); - if (mapaddr != MAP_FAILED) { - // mmap succeeded - filedata = mapaddr; - fdlen = maplen; - } else { - // mmap failed - if (qt_debug_component()) { - qWarning("mmap: %s", qPrintable(qt_error_string(errno))); - } - if (lib) - lib->errorString = QLibrary::tr("Could not mmap '%1': %2") - .arg(library) - .arg(qt_error_string()); -# endif // USE_MMAP + const char *filedata = 0; + ulong fdlen = file.size(); + filedata = (char *) file.map(0, fdlen); + if (filedata == 0) { // try reading the data into memory instead data = file.readAll(); - filedata = data.data(); + filedata = data.constData(); fdlen = data.size(); -# ifdef USE_MMAP } -# endif // USE_MMAP - // verify that the pattern is present in the plugin + /* + ELF binaries on GNU, have .qplugin sections. + */ + long pos = 0; const char pattern[] = "pattern=QT_PLUGIN_VERIFICATION_DATA"; const ulong plen = qstrlen(pattern); - long pos = qt_find_pattern(filedata, fdlen, pattern, plen); - +#if defined (Q_OF_ELF) && defined(Q_CC_GNU) + int r = QElfParser().parse(filedata, fdlen, library, lib, &pos, &fdlen); + if (r == QElfParser::NoQtSection) { + if (pos > 0) { + // find inside .rodata + long rel = qt_find_pattern(filedata + pos, fdlen, pattern, plen); + if (rel < 0) { + pos = -1; + } else { + pos += rel; + } + } else { + pos = qt_find_pattern(filedata, fdlen, pattern, plen); + } + } else if (r != QElfParser::Ok) { + if (lib && qt_debug_component()) { + qWarning(qPrintable(lib->errorString)); + } + return false; + } +#else + pos = qt_find_pattern(filedata, fdlen, pattern, plen); +#endif // defined(Q_OF_ELF) && defined(Q_CC_GNU) bool ret = false; if (pos >= 0) ret = qt_parse_pattern(filedata + pos, version, debug, key); if (!ret && lib) lib->errorString = QLibrary::tr("Plugin verification data mismatch in '%1'").arg(library); -# ifdef USE_MMAP - if (mapaddr != MAP_FAILED && munmap(mapaddr, maplen) != 0) { - if (qt_debug_component()) - qWarning("munmap: %s", qPrintable(qt_error_string(errno))); - if (lib) - lib->errorString = QLibrary::tr("Could not unmap '%1': %2") - .arg(library) - .arg( qt_error_string() ); - } -# endif // USE_MMAP - file.close(); return ret; } @@ -863,10 +847,16 @@ bool QLibraryPrivate::isPlugin(QSettings *settings) .arg(qt_version&0xff) .arg(debug ? QLatin1String("debug") : QLatin1String("release")); } else if (key != QT_BUILD_KEY + // we may have some compatibility keys, try them too: #ifdef QT_BUILD_KEY_COMPAT - // be sure to load plugins using an older but compatible build key && key != QT_BUILD_KEY_COMPAT #endif +#ifdef QT_BUILD_KEY_COMPAT2 + && key != QT_BUILD_KEY_COMPAT2 +#endif +#ifdef QT_BUILD_KEY_COMPAT3 + && key != QT_BUILD_KEY_COMPAT3 +#endif ) { if (qt_debug_component()) { qWarning("In %s:\n" @@ -1290,15 +1280,11 @@ QLibrary::LoadHints QLibrary::loadHints() const /* Internal, for debugging */ bool qt_debug_component() { -#if defined(QT_DEBUG_COMPONENT) - return true; //compatibility? -#else static int debug_env = -1; if (debug_env == -1) debug_env = QT_PREPEND_NAMESPACE(qgetenv)("QT_DEBUG_PLUGINS").toInt(); return debug_env != 0; -#endif } QT_END_NAMESPACE diff --git a/src/corelib/plugin/qplugin.h b/src/corelib/plugin/qplugin.h index 7f541f1..bd49b15 100644 --- a/src/corelib/plugin/qplugin.h +++ b/src/corelib/plugin/qplugin.h @@ -101,13 +101,17 @@ void Q_CORE_EXPORT qRegisterStaticPluginInstanceFunction(QtPluginInstanceFunctio // NOTE: if you change pattern, you MUST change the pattern in // qlibrary.cpp as well. changing the pattern will break all // backwards compatibility as well (no old plugins will be loaded). +// QT5: should probably remove the entire pattern thing and do the section +// trick for all platforms. for now, keep it and fallback to scan for it. # ifdef QPLUGIN_DEBUG_STR # undef QPLUGIN_DEBUG_STR # endif # ifdef QT_NO_DEBUG # define QPLUGIN_DEBUG_STR "false" +# define QPLUGIN_SECTION_DEBUG_STR "" # else # define QPLUGIN_DEBUG_STR "true" +# define QPLUGIN_SECTION_DEBUG_STR ".debug" # endif # define Q_PLUGIN_VERIFICATION_DATA \ static const char qt_plugin_verification_data[] = \ @@ -116,6 +120,13 @@ void Q_CORE_EXPORT qRegisterStaticPluginInstanceFunction(QtPluginInstanceFunctio "debug="QPLUGIN_DEBUG_STR"\n" \ "buildkey="QT_BUILD_KEY; +# if defined (Q_OF_ELF) && defined (Q_CC_GNU) +# define Q_PLUGIN_VERIFICATION_SECTION \ + __attribute__ ((section (".qtplugin"))) __attribute__((used)) +# else +# define Q_PLUGIN_VERIFICATION_SECTION +# endif + # if defined (Q_OS_WIN32) && defined(Q_CC_BOR) # define Q_STANDARD_CALL __stdcall # else @@ -123,7 +134,7 @@ void Q_CORE_EXPORT qRegisterStaticPluginInstanceFunction(QtPluginInstanceFunctio # endif # define Q_EXPORT_PLUGIN2(PLUGIN, PLUGINCLASS) \ - Q_PLUGIN_VERIFICATION_DATA \ + Q_PLUGIN_VERIFICATION_SECTION Q_PLUGIN_VERIFICATION_DATA \ Q_EXTERN_C Q_DECL_EXPORT \ const char * Q_STANDARD_CALL qt_plugin_query_verification_data() \ { return qt_plugin_verification_data; } \ diff --git a/src/corelib/plugin/qsystemlibrary.cpp b/src/corelib/plugin/qsystemlibrary.cpp new file mode 100644 index 0000000..eeb142b --- /dev/null +++ b/src/corelib/plugin/qsystemlibrary.cpp @@ -0,0 +1,136 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qsystemlibrary_p.h" +#include <QtCore/qvarlengtharray.h> +#include <QtCore/qstringlist.h> +#include <QtCore/qfileinfo.h> + +/*! + + \internal + \class QSystemLibrary + + The purpose of this class is to load only libraries that are located in + well-known and trusted locations on the filesystem. It does not suffer from + the security problem that QLibrary has, therefore it will never search in + the current directory. + + The search order is the same as the order in DLL Safe search mode Windows, + except that we don't search: + * The current directory + * The 16-bit system directory. (normally c:\windows\system) + * The Windows directory. (normally c:\windows) + + This means that the effective search order is: + 1. Application path. + 2. System libraries path. + 3. Trying all paths inside the PATH environment variable. + + Note, when onlySystemDirectory is true it will skip 1) and 3). + + DLL Safe search mode is documented in the "Dynamic-Link Library Search + Order" document on MSDN. + + Since library loading code is sometimes shared between Windows and WinCE, + this class can also be used on WinCE. However, its implementation just + calls the LoadLibrary() function. This is ok since it is documented as not + loading from the current directory on WinCE. This behaviour is documented + in the documentation for LoadLibrary for Windows CE at MSDN. + (http://msdn.microsoft.com/en-us/library/ms886736.aspx) +*/ +#if defined(Q_OS_WINCE) +HINSTANCE QSystemLibrary::load(const wchar_t *libraryName, bool onlySystemDirectory /* = true */) +{ + return ::LoadLibrary(libraryName); +} +#else + +#if !defined(QT_BOOTSTRAPPED) +extern QString qAppFileName(); +#endif + +static QString qSystemDirectory() +{ + QVarLengthArray<wchar_t, MAX_PATH> fullPath; + + UINT retLen = ::GetSystemDirectory(fullPath.data(), MAX_PATH); + if (retLen > MAX_PATH) { + fullPath.resize(retLen); + retLen = ::GetSystemDirectory(fullPath.data(), retLen); + } + // in some rare cases retLen might be 0 + return QString::fromWCharArray(fullPath.constData(), int(retLen)); +} + +HINSTANCE QSystemLibrary::load(const wchar_t *libraryName, bool onlySystemDirectory /* = true */) +{ + QStringList searchOrder; + +#if !defined(QT_BOOTSTRAPPED) + if (!onlySystemDirectory) + searchOrder << QFileInfo(qAppFileName()).path(); +#endif + searchOrder << qSystemDirectory(); + + if (!onlySystemDirectory) { + const QString PATH(QLatin1String(qgetenv("PATH").constData())); + searchOrder << PATH.split(QLatin1Char(';'), QString::SkipEmptyParts); + } + QString fileName = QString::fromWCharArray(libraryName); + fileName.append(QLatin1String(".dll")); + + // Start looking in the order specified + for (int i = 0; i < searchOrder.count(); ++i) { + QString fullPathAttempt = searchOrder.at(i); + if (!fullPathAttempt.endsWith(QLatin1Char('\\'))) { + fullPathAttempt.append(QLatin1Char('\\')); + } + fullPathAttempt.append(fileName); + HINSTANCE inst = ::LoadLibrary((const wchar_t *)fullPathAttempt.utf16()); + if (inst != 0) + return inst; + } + return 0; + +} + +#endif //Q_OS_WINCE diff --git a/src/corelib/plugin/qsystemlibrary_p.h b/src/corelib/plugin/qsystemlibrary_p.h new file mode 100644 index 0000000..3251a3c --- /dev/null +++ b/src/corelib/plugin/qsystemlibrary_p.h @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSYSTEMLIBRARY_P_H +#define QSYSTEMLIBRARY_P_H + +#include <QtCore/qglobal.h> +#ifdef Q_OS_WIN +#include <qt_windows.h> +#include <QtCore/qstring.h> + +class QSystemLibrary +{ +public: + explicit QSystemLibrary(const QString &libraryName) + { + m_libraryName = libraryName; + m_handle = 0; + m_didLoad = false; + } + + explicit QSystemLibrary(const wchar_t *libraryName) + { + m_libraryName = QString::fromWCharArray(libraryName); + m_handle = 0; + m_didLoad = false; + } + + bool load(bool onlySystemDirectory = true) + { + m_handle = load((const wchar_t *)m_libraryName.utf16(), onlySystemDirectory); + m_didLoad = true; + return (m_handle != 0); + } + + bool isLoaded() + { + return (m_handle != 0); + } + + void *resolve(const char *symbol) + { + if (!m_didLoad) + load(); + if (!m_handle) + return 0; +#ifdef Q_OS_WINCE + return (void*)GetProcAddress(m_handle, (const wchar_t*)QString::fromLatin1(symbol).utf16()); +#else + return (void*)GetProcAddress(m_handle, symbol); +#endif + } + + static void *resolve(const QString &libraryName, const char *symbol) + { + return QSystemLibrary(libraryName).resolve(symbol); + } + + static Q_CORE_EXPORT HINSTANCE load(const wchar_t *lpFileName, bool onlySystemDirectory = true); +private: + HINSTANCE m_handle; + QString m_libraryName; + bool m_didLoad; +}; + +#endif //Q_OS_WIN + +#endif //QSYSTEMLIBRARY_P_H diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index a3c702a..d704615 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -2135,6 +2135,7 @@ void QStateMachine::endMicrostep(QEvent *event) /*! \reimp + This function will call start() to start the state machine. */ void QStateMachine::onEntry(QEvent *event) { @@ -2144,6 +2145,8 @@ void QStateMachine::onEntry(QEvent *event) /*! \reimp + This function will call stop() to stop the state machine and + subsequently emit the stopped() signal. */ void QStateMachine::onExit(QEvent *event) { diff --git a/src/corelib/thread/qatomic.cpp b/src/corelib/thread/qatomic.cpp index 743da24..697da38 100644 --- a/src/corelib/thread/qatomic.cpp +++ b/src/corelib/thread/qatomic.cpp @@ -48,10 +48,9 @@ For atomic operations on pointers, see the QAtomicPointer class. - An complex operation that completes without interruption is said - to be \e atomic. The QAtomicInt class provides atomic reference - counting, test-and-set, fetch-and-store, and fetch-and-add for - integers. + An \e atomic operation is a complex operation that completes without interruption. + The QAtomicInt class provides atomic reference counting, test-and-set, fetch-and-store, + and fetch-and-add for integers. \section1 Non-atomic convenience operators @@ -635,9 +634,8 @@ For atomic operations on integers, see the QAtomicInt class. - An complex operation that completes without interruption is said - to be \e atomic. The QAtomicPointer class provides atomic - test-and-set, fetch-and-store, and fetch-and-add for pointers. + An \e atomic operation is a complex operation that completes without interruption. + The QAtomicPointer class provides atomic test-and-set, fetch-and-store, and fetch-and-add for pointers. \section1 Non-atomic convenience operators diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp index d193b2e..2824e15 100644 --- a/src/corelib/thread/qthread_unix.cpp +++ b/src/corelib/thread/qthread_unix.cpp @@ -142,6 +142,20 @@ static void destroy_current_thread_data_key() } Q_DESTRUCTOR_FUNCTION(destroy_current_thread_data_key) +#ifdef Q_OS_SYMBIAN +static void init_symbian_thread_handle(RThread &thread) +{ + thread = RThread(); + TThreadId threadId = thread.Id(); + thread.Open(threadId); + + // Make thread handle accessible process wide + RThread originalCloser = thread; + thread.Duplicate(thread, EOwnerProcess); + originalCloser.Close(); +} +#endif + QThreadData *QThreadData::current() { pthread_once(¤t_thread_data_once, create_current_thread_data_key); @@ -182,9 +196,7 @@ void QAdoptedThread::init() Q_D(QThread); d->thread_id = pthread_self(); #ifdef Q_OS_SYMBIAN - d->data->symbian_thread_handle = RThread(); - TThreadId threadId = d->data->symbian_thread_handle.Id(); - d->data->symbian_thread_handle.Open(threadId); + init_symbian_thread_handle(d->data->symbian_thread_handle); #endif } @@ -244,9 +256,8 @@ void *QThreadPrivate::start(void *arg) // RThread and pthread_t, we must delay initialization of the RThread // handle when creating a thread, until we are running in the new thread. // Here, we pick up the current thread and assign that to the handle. - data->symbian_thread_handle = RThread(); - TThreadId threadId = data->symbian_thread_handle.Id(); - data->symbian_thread_handle.Open(threadId); + init_symbian_thread_handle(data->symbian_thread_handle); + // On symbian, threads other than the main thread are non critical by default // This means a worker thread can crash without crashing the application - to // use this feature, we would need to use RThread::Logon in the main thread @@ -657,6 +668,18 @@ bool QThread::wait(unsigned long time) return true; while (d->running) { +#ifdef Q_OS_SYMBIAN + // Check if thread still exists. Needed because kernel will kill it without notification + // before global statics are deleted at application exit. + if (d->data->symbian_thread_handle.Handle() + && d->data->symbian_thread_handle.ExitType() != EExitPending) { + // Cannot call finish here as wait is typically called from another thread. + // It won't be necessary anyway, as we should never get here under normal operations; + // all QThreads are EProcessCritical and therefore cannot normally exit + // undetected (i.e. panic) as long as all thread control is via QThread. + return true; + } +#endif if (!d->thread_done.wait(locker.mutex(), time)) return false; } diff --git a/src/corelib/tools/qbitarray.h b/src/corelib/tools/qbitarray.h index 60cdc9c..bd79904 100644 --- a/src/corelib/tools/qbitarray.h +++ b/src/corelib/tools/qbitarray.h @@ -63,6 +63,10 @@ public: explicit QBitArray(int size, bool val = false); QBitArray(const QBitArray &other) : d(other.d) {} inline QBitArray &operator=(const QBitArray &other) { d = other.d; return *this; } +#ifdef Q_COMPILER_RVALUE_REFS + inline QBitArray &operator=(QBitArray &&other) + { qSwap(d, other.d); return *this; } +#endif inline int size() const { return (d.size() << 3) - *d.constData(); } inline int count() const { return (d.size() << 3) - *d.constData(); } diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp index 3062c4a..6be3416 100644 --- a/src/corelib/tools/qbytearray.cpp +++ b/src/corelib/tools/qbytearray.cpp @@ -46,7 +46,6 @@ #include "qlist.h" #include "qlocale.h" #include "qlocale_p.h" -#include "qunicodetables_p.h" #include "qscopedpointer.h" #include <qdatastream.h> @@ -854,7 +853,7 @@ QByteArray::Data QByteArray::shared_empty = { Q_BASIC_ATOMIC_INITIALIZER(1), This operation takes \l{constant time}, because QByteArray is \l{implicitly shared}. This makes returning a QByteArray from a function very fast. If a shared instance is modified, it will be - copied (copy-on-write), and that takes \l{linear time}. + copied (copy-on-write), taking \l{linear time}. \sa operator=() */ @@ -1190,10 +1189,18 @@ void QByteArray::chop(int n) Example: \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 12 - This operation is typically very fast (\l{constant time}), - because QByteArray preallocates extra space at the end of the - character data so it can grow without reallocating the entire - data each time. + Note: QByteArray is an \l{implicitly shared} class. Consequently, + if \e this is an empty QByteArray, then \e this will just share + the data held in \a ba. In this case, no copying of data is done, + taking \l{constant time}. If a shared instance is modified, it will + be copied (copy-on-write), taking \l{linear time}. + + If \e this is not an empty QByteArray, a deep copy of the data is + performed, taking \l{linear time}. + + This operation typically does not suffer from allocation overhead, + because QByteArray preallocates extra space at the end of the data + so that it may grow without reallocating for each append operation. \sa append(), prepend() */ @@ -1478,7 +1485,12 @@ QByteArray QByteArray::nulTerminated() const Note: QByteArray is an \l{implicitly shared} class. Consequently, if \e this is an empty QByteArray, then \e this will just share - the data held in \a ba. In this case, no copying of data is done. + the data held in \a ba. In this case, no copying of data is done, + taking \l{constant time}. If a shared instance is modified, it will + be copied (copy-on-write), taking \l{linear time}. + + If \e this is not an empty QByteArray, a deep copy of the data is + performed, taking \l{linear time}. \sa append(), insert() */ @@ -1551,14 +1563,18 @@ QByteArray &QByteArray::prepend(char ch) This is the same as insert(size(), \a ba). - This operation is typically very fast (\l{constant time}), - because QByteArray preallocates extra space at the end of the - character data so it can grow without reallocating the entire - data each time. - Note: QByteArray is an \l{implicitly shared} class. Consequently, if \e this is an empty QByteArray, then \e this will just share - the data held in \a ba. In this case, no copying of data is done. + the data held in \a ba. In this case, no copying of data is done, + taking \l{constant time}. If a shared instance is modified, it will + be copied (copy-on-write), taking \l{linear time}. + + If \e this is not an empty QByteArray, a deep copy of the data is + performed, taking \l{linear time}. + + This operation typically does not suffer from allocation overhead, + because QByteArray preallocates extra space at the end of the data + so that it may grow without reallocating for each append operation. \sa operator+=(), prepend(), insert() */ diff --git a/src/corelib/tools/qbytearray.h b/src/corelib/tools/qbytearray.h index a3fe3f5..3cdcaab 100644 --- a/src/corelib/tools/qbytearray.h +++ b/src/corelib/tools/qbytearray.h @@ -144,6 +144,10 @@ public: QByteArray &operator=(const QByteArray &); QByteArray &operator=(const char *str); +#ifdef Q_COMPILER_RVALUE_REFS + inline QByteArray &operator=(QByteArray &&other) + { qSwap(d, other.d); return *this; } +#endif inline int size() const; bool isEmpty() const; diff --git a/src/corelib/tools/qchar.cpp b/src/corelib/tools/qchar.cpp index ed0af4e..bb777cd 100644 --- a/src/corelib/tools/qchar.cpp +++ b/src/corelib/tools/qchar.cpp @@ -1630,21 +1630,4 @@ static void canonicalOrderHelper(QString *str, QChar::UnicodeVersion version, in } } -int QT_FASTCALL QUnicodeTables::script(unsigned int uc) -{ - if (uc > 0xffff) - return Common; - int script = uc_scripts[uc >> 7]; - if (script < ScriptSentinel) - return script; - script = (((script - ScriptSentinel) * UnicodeBlockSize) + UnicodeBlockCount); - script = uc_scripts[script + (uc & 0x7f)]; - return script; -} - -Q_CORE_EXPORT QUnicodeTables::LineBreakClass QT_FASTCALL QUnicodeTables::lineBreakClass(uint ucs4) -{ - return (QUnicodeTables::LineBreakClass) qGetProp(ucs4)->line_break_class; -} - QT_END_NAMESPACE diff --git a/src/corelib/tools/qcontiguouscache.h b/src/corelib/tools/qcontiguouscache.h index f767962..4c1a846 100644 --- a/src/corelib/tools/qcontiguouscache.h +++ b/src/corelib/tools/qcontiguouscache.h @@ -110,6 +110,10 @@ public: inline void setSharable(bool sharable) { if (!sharable) detach(); d->sharable = sharable; } QContiguousCache<T> &operator=(const QContiguousCache<T> &other); +#ifdef Q_COMPILER_RVALUE_REFS + inline QContiguousCache<T> &operator=(QContiguousCache<T> &&other) + { qSwap(d, other.d); return *this; } +#endif bool operator==(const QContiguousCache<T> &other) const; inline bool operator!=(const QContiguousCache<T> &other) const { return !(*this == other); } diff --git a/src/corelib/tools/qcryptographichash.cpp b/src/corelib/tools/qcryptographichash.cpp index f418de9..043d6a3 100644 --- a/src/corelib/tools/qcryptographichash.cpp +++ b/src/corelib/tools/qcryptographichash.cpp @@ -147,7 +147,7 @@ void QCryptographicHash::addData(const char *data, int length) } /*! - /overload + \overload addData() */ void QCryptographicHash::addData(const QByteArray &data) { diff --git a/src/corelib/tools/qeasingcurve.cpp b/src/corelib/tools/qeasingcurve.cpp index ee791e0..7fe9170 100644 --- a/src/corelib/tools/qeasingcurve.cpp +++ b/src/corelib/tools/qeasingcurve.cpp @@ -332,7 +332,7 @@ public: enum Type { In, Out, InOut, OutIn }; QEasingCurveFunction(QEasingCurveFunction::Type type = In, qreal period = 0.3, qreal amplitude = 1.0, - qreal overshoot = 1.70158f) + qreal overshoot = 1.70158) : _t(type), _p(period), _a(amplitude), _o(overshoot) { } virtual ~QEasingCurveFunction() {} @@ -359,9 +359,9 @@ QEasingCurveFunction *QEasingCurveFunction::copy() const bool QEasingCurveFunction::operator==(const QEasingCurveFunction& other) { return _t == other._t && - _p == other._p && - _a == other._a && - _o == other._o; + qFuzzyCompare(_p, other._p) && + qFuzzyCompare(_a, other._a) && + qFuzzyCompare(_o, other._o); } QT_BEGIN_INCLUDE_NAMESPACE @@ -400,8 +400,8 @@ struct ElasticEase : public QEasingCurveFunction qreal value(qreal t) { - qreal p = (_p < 0) ? 0.3f : _p; - qreal a = (_a < 0) ? 1.0f : _a; + qreal p = (_p < 0) ? qreal(0.3) : _p; + qreal a = (_a < 0) ? qreal(1.0) : _a; switch(_t) { case In: return easeInElastic(t, a, p); @@ -420,7 +420,7 @@ struct ElasticEase : public QEasingCurveFunction struct BounceEase : public QEasingCurveFunction { BounceEase(Type type) - : QEasingCurveFunction(type, 0.3f, 1.0f) + : QEasingCurveFunction(type, qreal(0.3), qreal(1.0)) { } QEasingCurveFunction *copy() const @@ -432,7 +432,7 @@ struct BounceEase : public QEasingCurveFunction qreal value(qreal t) { - qreal a = (_a < 0) ? 1.0f : _a; + qreal a = (_a < 0) ? qreal(1.0) : _a; switch(_t) { case In: return easeInBounce(t, a); @@ -451,7 +451,7 @@ struct BounceEase : public QEasingCurveFunction struct BackEase : public QEasingCurveFunction { BackEase(Type type) - : QEasingCurveFunction(type, 0.3f, 1.0f, 1.70158f) + : QEasingCurveFunction(type, qreal(0.3), qreal(1.0), qreal(1.70158)) { } QEasingCurveFunction *copy() const @@ -463,7 +463,7 @@ struct BackEase : public QEasingCurveFunction qreal value(qreal t) { - qreal o = (_o < 0) ? 1.70158f : _o; + qreal o = (_o < 0) ? qreal(1.70158) : _o; switch(_t) { case In: return easeInBack(t, o); @@ -595,7 +595,7 @@ static QEasingCurveFunction *curveToFunctionObject(QEasingCurve::Type type) curveFunc = new BackEase(BackEase::OutIn); break; default: - curveFunc = new QEasingCurveFunction(QEasingCurveFunction::In, 0.3f, 1.0f, 1.70158f); // ### + curveFunc = new QEasingCurveFunction(QEasingCurveFunction::In, qreal(0.3), qreal(1.0), qreal(1.70158)); } return curveFunc; @@ -657,9 +657,17 @@ bool QEasingCurve::operator==(const QEasingCurve &other) const { bool res = d_ptr->func == other.d_ptr->func && d_ptr->type == other.d_ptr->type; - if (res && d_ptr->config && other.d_ptr->config) { + if (res) { + if (d_ptr->config && other.d_ptr->config) { // catch the config content - res = d_ptr->config->operator==(*(other.d_ptr->config)); + res = d_ptr->config->operator==(*(other.d_ptr->config)); + + } else if (d_ptr->config || other.d_ptr->config) { + // one one has a config object, which could contain default values + res = qFuzzyCompare(amplitude(), other.amplitude()) && + qFuzzyCompare(period(), other.period()) && + qFuzzyCompare(overshoot(), other.overshoot()); + } } return res; } @@ -681,7 +689,7 @@ bool QEasingCurve::operator==(const QEasingCurve &other) const */ qreal QEasingCurve::amplitude() const { - return d_ptr->config ? d_ptr->config->_a : 1.0; + return d_ptr->config ? d_ptr->config->_a : qreal(1.0); } /*! @@ -705,7 +713,7 @@ void QEasingCurve::setAmplitude(qreal amplitude) */ qreal QEasingCurve::period() const { - return d_ptr->config ? d_ptr->config->_p : 0.3; + return d_ptr->config ? d_ptr->config->_p : qreal(0.3); } /*! @@ -729,7 +737,7 @@ void QEasingCurve::setPeriod(qreal period) */ qreal QEasingCurve::overshoot() const { - return d_ptr->config ? d_ptr->config->_o : 1.70158f; + return d_ptr->config ? d_ptr->config->_o : qreal(1.70158) ; } /*! diff --git a/src/corelib/tools/qelapsedtimer_unix.cpp b/src/corelib/tools/qelapsedtimer_unix.cpp index 2c4ea58..633fa00 100644 --- a/src/corelib/tools/qelapsedtimer_unix.cpp +++ b/src/corelib/tools/qelapsedtimer_unix.cpp @@ -40,22 +40,58 @@ ****************************************************************************/ #include "qelapsedtimer.h" -#include "qpair.h" #include <sys/time.h> #include <time.h> #include <unistd.h> -#if !defined(QT_NO_CLOCK_MONOTONIC) -# if defined(QT_BOOTSTRAPPED) -# define QT_NO_CLOCK_MONOTONIC +#if defined(QT_NO_CLOCK_MONOTONIC) || defined(QT_BOOTSTRAPPED) +// turn off the monotonic clock +# ifdef _POSIX_MONOTONIC_CLOCK +# undef _POSIX_MONOTONIC_CLOCK # endif +# define _POSIX_MONOTONIC_CLOCK -1 #endif QT_BEGIN_NAMESPACE -static qint64 fractionAdjustment() +#if (_POSIX_MONOTONIC_CLOCK-0 != 0) +static const bool monotonicClockChecked = true; +static const bool monotonicClockAvailable = _POSIX_MONOTONIC_CLOCK > 0; +#else +static int monotonicClockChecked = false; +static int monotonicClockAvailable = false; +#endif + +#ifdef Q_CC_GNU +# define is_likely(x) __builtin_expect((x), 1) +#else +# define is_likely(x) (x) +#endif +#define load_acquire(x) ((volatile const int&)(x)) +#define store_release(x,v) ((volatile int&)(x) = (v)) + +static void unixCheckClockType() +{ +#if (_POSIX_MONOTONIC_CLOCK-0 == 0) + if (is_likely(load_acquire(monotonicClockChecked))) + return; + +# if defined(_SC_MONOTONIC_CLOCK) + // detect if the system support monotonic timers + long x = sysconf(_SC_MONOTONIC_CLOCK); + store_release(monotonicClockAvailable, x >= 200112L); +# endif + + store_release(monotonicClockChecked, true); +#endif +} + +static inline qint64 fractionAdjustment() { - if (QElapsedTimer::isMonotonic()) { + // disabled, but otherwise indicates bad usage of QElapsedTimer + //Q_ASSERT(monotonicClockChecked); + + if (monotonicClockAvailable) { // the monotonic timer is measured in nanoseconds // 1 ms = 1000000 ns return 1000*1000ull; @@ -68,90 +104,73 @@ static qint64 fractionAdjustment() bool QElapsedTimer::isMonotonic() { -#if (_POSIX_MONOTONIC_CLOCK-0 > 0) - return true; -#else - static int returnValue = 0; - - if (returnValue == 0) { -# if (_POSIX_MONOTONIC_CLOCK-0 < 0) || !defined(_SC_MONOTONIC_CLOCK) - returnValue = -1; -# elif (_POSIX_MONOTONIC_CLOCK == 0) - // detect if the system support monotonic timers - long x = sysconf(_SC_MONOTONIC_CLOCK); - returnValue = (x >= 200112L) ? 1 : -1; -# endif - } - - return returnValue != -1; -#endif + unixCheckClockType(); + return monotonicClockAvailable; } QElapsedTimer::ClockType QElapsedTimer::clockType() { - return isMonotonic() ? MonotonicClock : SystemTime; + unixCheckClockType(); + return monotonicClockAvailable ? MonotonicClock : SystemTime; } -static inline QPair<long, long> do_gettime() +static inline void do_gettime(qint64 *sec, qint64 *frac) { -#if (_POSIX_MONOTONIC_CLOCK-0 > 0) - timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - return qMakePair<long,long>(ts.tv_sec, ts.tv_nsec); -#else -# if !defined(QT_NO_CLOCK_MONOTONIC) && !defined(QT_BOOTSTRAPPED) - if (QElapsedTimer::isMonotonic()) { +#if (_POSIX_MONOTONIC_CLOCK-0 >= 0) + unixCheckClockType(); + if (is_likely(monotonicClockAvailable)) { timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); - return qMakePair<long,long>(ts.tv_sec, ts.tv_nsec); + *sec = ts.tv_sec; + *frac = ts.tv_nsec; + return; } -# endif +#endif // use gettimeofday timeval tv; ::gettimeofday(&tv, 0); - return qMakePair<long,long>(tv.tv_sec, tv.tv_usec); -#endif + *sec = tv.tv_sec; + *frac = tv.tv_usec; } // used in qcore_unix.cpp and qeventdispatcher_unix.cpp timeval qt_gettime() { - QPair<long, long> r = do_gettime(); + qint64 sec, frac; + do_gettime(&sec, &frac); timeval tv; - tv.tv_sec = r.first; - tv.tv_usec = r.second; - if (QElapsedTimer::isMonotonic()) + tv.tv_sec = sec; + tv.tv_usec = frac; + if (monotonicClockAvailable) tv.tv_usec /= 1000; return tv; } +static qint64 elapsedAndRestart(qint64 sec, qint64 frac, + qint64 *nowsec, qint64 *nowfrac) +{ + do_gettime(nowsec, nowfrac); + sec = *nowsec - sec; + frac = *nowfrac - frac; + return sec * Q_INT64_C(1000) + frac / fractionAdjustment(); +} + void QElapsedTimer::start() { - QPair<long, long> r = do_gettime(); - t1 = r.first; - t2 = r.second; + do_gettime(&t1, &t2); } qint64 QElapsedTimer::restart() { - QPair<long, long> r = do_gettime(); - qint64 oldt1 = t1; - qint64 oldt2 = t2; - t1 = r.first; - t2 = r.second; - - r.first -= oldt1; - r.second -= oldt2; - return r.first * Q_INT64_C(1000) + r.second / fractionAdjustment(); + return elapsedAndRestart(t1, t2, &t1, &t2); } qint64 QElapsedTimer::elapsed() const { - QElapsedTimer now; - now.start(); - return msecsTo(now); + qint64 sec, frac; + return elapsedAndRestart(t1, t2, &sec, &frac); } qint64 QElapsedTimer::msecsSinceReference() const diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h index 360f99d..992ff33 100644 --- a/src/corelib/tools/qhash.h +++ b/src/corelib/tools/qhash.h @@ -283,6 +283,10 @@ public: inline ~QHash() { if (!d->ref.deref()) freeData(d); } QHash<Key, T> &operator=(const QHash<Key, T> &other); +#ifdef Q_COMPILER_RVALUE_REFS + inline QHash<Key, T> &operator=(QHash<Key, T> &&other) + { qSwap(d, other.d); return *this; } +#endif bool operator==(const QHash<Key, T> &other) const; inline bool operator!=(const QHash<Key, T> &other) const { return !(*this == other); } @@ -586,10 +590,11 @@ template <class Key, class T> Q_INLINE_TEMPLATE QHash<Key, T> &QHash<Key, T>::operator=(const QHash<Key, T> &other) { if (d != other.d) { - other.d->ref.ref(); + QHashData *o = other.d; + o->ref.ref(); if (!d->ref.deref()) freeData(d); - d = other.d; + d = o; if (!d->sharable) detach_helper(); } diff --git a/src/corelib/tools/qlinkedlist.h b/src/corelib/tools/qlinkedlist.h index d145fe3..c087944 100644 --- a/src/corelib/tools/qlinkedlist.h +++ b/src/corelib/tools/qlinkedlist.h @@ -85,6 +85,10 @@ public: inline QLinkedList(const QLinkedList<T> &l) : d(l.d) { d->ref.ref(); if (!d->sharable) detach(); } ~QLinkedList(); QLinkedList<T> &operator=(const QLinkedList<T> &); +#ifdef Q_COMPILER_RVALUE_REFS + inline QLinkedList<T> &operator=(QLinkedList<T> &&other) + { qSwap(d, other.d); return *this; } +#endif bool operator==(const QLinkedList<T> &l) const; inline bool operator!=(const QLinkedList<T> &l) const { return !(*this == l); } @@ -312,10 +316,11 @@ template <typename T> QLinkedList<T> &QLinkedList<T>::operator=(const QLinkedList<T> &l) { if (d != l.d) { - l.d->ref.ref(); + QLinkedListData *o = l.d; + o->ref.ref(); if (!d->ref.deref()) free(d); - d = l.d; + d = o; if (!d->sharable) detach_helper(); } diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index 99c9795..8f988d6 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -50,6 +50,10 @@ #include <iterator> #include <list> #endif +#ifdef Q_COMPILER_INITIALIZER_LISTS +#include <iterator> +#include <initializer_list> +#endif #include <new> #include <limits.h> @@ -118,6 +122,14 @@ public: inline QList(const QList<T> &l) : d(l.d) { d->ref.ref(); if (!d->sharable) detach_helper(); } ~QList(); QList<T> &operator=(const QList<T> &l); +#ifdef Q_COMPILER_RVALUE_REFS + inline QList &operator=(QList &&other) + { qSwap(d, other.d); return *this; } +#endif +#ifdef Q_COMPILER_INITIALIZER_LISTS + inline QList(std::initializer_list<T> args) : d(&QListData::shared_null) + { d->ref.ref(); qCopy(args.begin(), args.end(), std::back_inserter(*this)); } +#endif bool operator==(const QList<T> &l) const; inline bool operator!=(const QList<T> &l) const { return !(*this == l); } @@ -424,10 +436,11 @@ template <typename T> Q_INLINE_TEMPLATE QList<T> &QList<T>::operator=(const QList<T> &l) { if (d != l.d) { - l.d->ref.ref(); + QListData::Data *o = l.d; + o->ref.ref(); if (!d->ref.deref()) free(d); - d = l.d; + d = o; if (!d->sharable) detach_helper(); } diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h index 2d11613..ce8fd75 100644 --- a/src/corelib/tools/qmap.h +++ b/src/corelib/tools/qmap.h @@ -185,6 +185,10 @@ public: inline ~QMap() { if (!d) return; if (!d->ref.deref()) freeData(d); } QMap<Key, T> &operator=(const QMap<Key, T> &other); +#ifdef Q_COMPILER_RVALUE_REFS + inline QMap<Key, T> &operator=(QMap<Key, T> &&other) + { qSwap(d, other.d); return *this; } +#endif #ifndef QT_NO_STL explicit QMap(const typename std::map<Key, T> &other); std::map<Key, T> toStdMap() const; @@ -424,10 +428,11 @@ template <class Key, class T> Q_INLINE_TEMPLATE QMap<Key, T> &QMap<Key, T>::operator=(const QMap<Key, T> &other) { if (d != other.d) { - other.d->ref.ref(); + QMapData* o = other.d; + o->ref.ref(); if (!d->ref.deref()) freeData(d); - d = other.d; + d = o; if (!d->sharable) detach_helper(); } diff --git a/src/corelib/tools/qregexp.cpp b/src/corelib/tools/qregexp.cpp index 36827d0..a0df065 100644 --- a/src/corelib/tools/qregexp.cpp +++ b/src/corelib/tools/qregexp.cpp @@ -4172,6 +4172,8 @@ int QRegExp::matchedLength() const } #ifndef QT_NO_REGEXP_CAPTURE + +#ifndef QT_NO_DEPRECATED /*! \obsolete Returns the number of captures contained in the regular expression. @@ -4182,6 +4184,7 @@ int QRegExp::numCaptures() const { return captureCount(); } +#endif /*! \since 4.6 diff --git a/src/corelib/tools/qregexp.h b/src/corelib/tools/qregexp.h index e19c130..0b4a702 100644 --- a/src/corelib/tools/qregexp.h +++ b/src/corelib/tools/qregexp.h @@ -76,6 +76,10 @@ public: QRegExp(const QRegExp &rx); ~QRegExp(); QRegExp &operator=(const QRegExp &rx); +#ifdef Q_COMPILER_RVALUE_REFS + inline QRegExp &operator=(QRegExp &&other) + { qSwap(priv,other.priv); return *this; } +#endif bool operator==(const QRegExp &rx) const; inline bool operator!=(const QRegExp &rx) const { return !operator==(rx); } diff --git a/src/corelib/tools/qset.h b/src/corelib/tools/qset.h index fe50d4d..dc3c45a 100644 --- a/src/corelib/tools/qset.h +++ b/src/corelib/tools/qset.h @@ -61,6 +61,10 @@ public: inline QSet<T> &operator=(const QSet<T> &other) { q_hash = other.q_hash; return *this; } +#ifdef Q_COMPILER_RVALUE_REFS + inline QSet<T> &operator=(QSet<T> &&other) + { qSwap(q_hash, other.q_hash); return *this; } +#endif inline bool operator==(const QSet<T> &other) const { return q_hash == other.q_hash; } diff --git a/src/corelib/tools/qshareddata.h b/src/corelib/tools/qshareddata.h index 80ba7b7..b646a9d 100644 --- a/src/corelib/tools/qshareddata.h +++ b/src/corelib/tools/qshareddata.h @@ -95,9 +95,10 @@ public: if (o.d != d) { if (o.d) o.d->ref.ref(); - if (d && !d->ref.deref()) - delete d; + T *old = d; d = o.d; + if (old && !old->ref.deref()) + delete old; } return *this; } @@ -105,12 +106,17 @@ public: if (o != d) { if (o) o->ref.ref(); - if (d && !d->ref.deref()) - delete d; + T *old = d; d = o; + if (old && !old->ref.deref()) + delete old; } return *this; } +#ifdef Q_COMPILER_RVALUE_REFS + inline QSharedDataPointer<T> &operator=(QSharedDataPointer<T> &&other) + { qSwap(d, other.d); return *this; } +#endif inline bool operator!() const { return !d; } @@ -172,9 +178,10 @@ public: if (o.d != d) { if (o.d) o.d->ref.ref(); - if (d && !d->ref.deref()) - delete d; + T *old = d; d = o.d; + if (old && !old->ref.deref()) + delete old; } return *this; } @@ -182,12 +189,17 @@ public: if (o != d) { if (o) o->ref.ref(); - if (d && !d->ref.deref()) - delete d; + T *old = d; d = o; + if (old && !old->ref.deref()) + delete old; } return *this; } +#ifdef Q_COMPILER_RVALUE_REFS + inline QSharedDataPointer<T> &operator=(QSharedDataPointer<T> &&other) + { qSwap(d, other.d); return *this; } +#endif inline bool operator!() const { return !d; } diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h index bb06f3a..20dda12 100644 --- a/src/corelib/tools/qsharedpointer_impl.h +++ b/src/corelib/tools/qsharedpointer_impl.h @@ -465,6 +465,13 @@ public: BaseClass::internalCopy(other); return *this; } +#ifdef Q_COMPILER_RVALUE_REFS + inline QSharedPointer<T> &operator=(QSharedPointer<T> &&other) + { + QSharedPointer<T>::internalSwap(other); + return *this; + } +#endif template <class X> inline QSharedPointer(const QSharedPointer<X> &other) : BaseClass(other) diff --git a/src/corelib/tools/qsimd.cpp b/src/corelib/tools/qsimd.cpp index 8005d7d..7babf3a 100644 --- a/src/corelib/tools/qsimd.cpp +++ b/src/corelib/tools/qsimd.cpp @@ -41,6 +41,7 @@ #include "qsimd_p.h" #include <QByteArray> +#include <stdio.h> #if defined(Q_OS_WINCE) #include <windows.h> @@ -50,15 +51,32 @@ #include <intrin.h> #endif +#if defined(Q_OS_LINUX) && defined(__arm__) +#include "private/qcore_unix_p.h" + +// the kernel header definitions for HWCAP_* +// (the ones we need/may need anyway) + +// copied from <asm/hwcap.h> (ARM) +#define HWCAP_IWMMXT 512 +#define HWCAP_CRUNCH 1024 +#define HWCAP_THUMBEE 2048 +#define HWCAP_NEON 4096 +#define HWCAP_VFPv3 8192 +#define HWCAP_VFPv3D16 16384 + +// copied from <linux/auxvec.h> +#define AT_HWCAP 16 /* arch dependent hints at CPU capabilities */ + +#endif + QT_BEGIN_NAMESPACE -uint qDetectCPUFeatures() +#if defined (Q_OS_WINCE) +static inline uint detectProcessorFeatures() { - static uint features = 0xffffffff; - if (features != 0xffffffff) - return features; + uint features = 0; -#if defined (Q_OS_WINCE) #if defined (ARM) if (IsProcessorFeaturePresent(PF_ARM_INTEL_WMMX)) { features = IWMMXT; @@ -78,77 +96,98 @@ uint qDetectCPUFeatures() #endif features = 0; return features; -#elif defined(QT_HAVE_IWMMXT) +} + +#elif defined(__arm__) || defined(__arm) || defined(QT_HAVE_IWMMXT) || defined(QT_HAVE_NEON) +static inline uint detectProcessorFeatures() +{ + uint features = 0; + +#if defined(Q_OS_LINUX) + int auxv = ::qt_safe_open("/proc/self/auxv", O_RDONLY); + if (auxv != -1) { + unsigned long vector[64]; + int nread; + while (features == 0) { + nread = ::qt_safe_read(auxv, (char *)vector, sizeof vector); + if (nread <= 0) { + // EOF or error + break; + } + + int max = nread / (sizeof vector[0]); + for (int i = 0; i < max; i += 2) + if (vector[i] == AT_HWCAP) { + if (vector[i+1] & HWCAP_IWMMXT) + features |= IWMMXT; + if (vector[i+1] & HWCAP_NEON) + features |= NEON; + break; + } + } + + ::qt_safe_close(auxv); + return features; + } + // fall back if /proc/self/auxv wasn't found +#endif + +#if defined(QT_HAVE_IWMMXT) // runtime detection only available when running as a previlegied process - static const bool doIWMMXT = !qgetenv("QT_NO_IWMMXT").toInt(); - features = doIWMMXT ? IWMMXT : 0; - return features; + features = IWMMXT; #elif defined(QT_HAVE_NEON) - static const bool doNEON = !qgetenv("QT_NO_NEON").toInt(); - features = doNEON ? NEON : 0; + features = NEON; +#endif + return features; -#else - features = 0; -#if defined(__x86_64__) || defined(Q_OS_WIN64) - features = MMX|SSE|SSE2|CMOV; -#elif defined(__ia64__) - features = MMX|SSE|SSE2; +} + #elif defined(__i386__) || defined(_M_IX86) +static inline uint detectProcessorFeatures() +{ + uint features = 0; + unsigned int extended_result = 0; unsigned int feature_result = 0; uint result = 0; /* see p. 118 of amd64 instruction set manual Vol3 */ #if defined(Q_CC_GNU) - asm ("push %%ebx\n" - "pushf\n" - "pop %%eax\n" - "mov %%eax, %%ebx\n" - "xor $0x00200000, %%eax\n" - "push %%eax\n" + long cpuid_supported, tmp1; + asm ("pushf\n" + "pop %0\n" + "mov %0, %1\n" + "xor $0x00200000, %0\n" + "push %0\n" "popf\n" "pushf\n" - "pop %%eax\n" - "xor %%edx, %%edx\n" - "xor %%ebx, %%eax\n" - "jz 1f\n" - - "mov $0x00000001, %%eax\n" - "cpuid\n" - "1:\n" - "pop %%ebx\n" - "mov %%edx, %0\n" - "mov %%ecx, %1\n" - : "=r" (result), "=r" (feature_result) - : - : "%eax", "%ecx", "%edx" - ); + "pop %0\n" + "xor %1, %0\n" // %eax is now 0 if CPUID is not supported + : "=a" (cpuid_supported), "=r" (tmp1) + ); + if (cpuid_supported) { + asm ("xchg %%ebx, %2\n" + "cpuid\n" + "xchg %%ebx, %2\n" + : "=c" (feature_result), "=d" (result), "=&r" (tmp1) + : "a" (1)); - asm ("push %%ebx\n" - "pushf\n" - "pop %%eax\n" - "mov %%eax, %%ebx\n" - "xor $0x00200000, %%eax\n" - "push %%eax\n" - "popf\n" - "pushf\n" - "pop %%eax\n" - "xor %%edx, %%edx\n" - "xor %%ebx, %%eax\n" - "jz 2f\n" + asm ("xchg %%ebx, %1\n" + "cpuid\n" + "cmp $0x80000000, %%eax\n" + "jnbe 1f\n" + "xor %0, %0\n" + "jmp 2f\n" + "1:\n" + "mov $0x80000001, %%eax\n" + "cpuid\n" + "2:\n" + "xchg %%ebx, %1\n" + : "=d" (extended_result), "=&r" (tmp1) + : "a" (0x80000000) + : "%ecx" + ); + } - "mov $0x80000000, %%eax\n" - "cpuid\n" - "cmp $0x80000000, %%eax\n" - "jbe 2f\n" - "mov $0x80000001, %%eax\n" - "cpuid\n" - "2:\n" - "pop %%ebx\n" - "mov %%edx, %0\n" - : "=r" (extended_result) - : - : "%eax", "%ecx", "%edx" - ); #elif defined (Q_OS_WIN) _asm { push eax @@ -210,6 +249,7 @@ uint qDetectCPUFeatures() } #endif + // result now contains the standard feature bits if (result & (1u << 15)) features |= CMOV; @@ -236,33 +276,23 @@ uint qDetectCPUFeatures() if (feature_result & (1u << 28)) features |= AVX; -#endif // i386 + return features; +} -#if defined(__x86_64__) || defined(Q_OS_WIN64) +#elif defined(__x86_64) || defined(Q_OS_WIN64) +static inline uint detectProcessorFeatures() +{ + uint features = MMX|SSE|SSE2|CMOV; uint feature_result = 0; #if defined(Q_CC_GNU) - asm ("push %%rbx\n" - "pushf\n" - "pop %%rax\n" - "mov %%eax, %%ebx\n" - "xor $0x00200000, %%eax\n" - "push %%rax\n" - "popf\n" - "pushf\n" - "pop %%rax\n" - "xor %%edx, %%edx\n" - "xor %%ebx, %%eax\n" - "jz 1f\n" - - "mov $0x00000001, %%eax\n" + long tmp; + asm ("xchg %%rbx, %1\n" "cpuid\n" - "1:\n" - "pop %%rbx\n" - "mov %%ecx, %0\n" - : "=r" (feature_result) - : - : "%eax", "%ecx", "%edx" + "xchg %%rbx, %1\n" + : "=c" (feature_result), "=&r" (tmp) + : "a" (1) + : "%edx" ); #elif defined (Q_OS_WIN64) { @@ -282,33 +312,97 @@ uint qDetectCPUFeatures() features |= SSE4_2; if (feature_result & (1u << 28)) features |= AVX; -#endif // x86_64 -#if defined(QT_HAVE_MMX) - if (qgetenv("QT_NO_MMX").toInt()) - features ^= MMX; -#endif - if (qgetenv("QT_NO_MMXEXT").toInt()) - features ^= MMXEXT; + return features; +} -#if defined(QT_HAVE_3DNOW) - if (qgetenv("QT_NO_3DNOW").toInt()) - features ^= MMX3DNOW; -#endif - if (qgetenv("QT_NO_3DNOWEXT").toInt()) - features ^= MMX3DNOWEXT; +#elif defined(__ia64__) +static inline uint detectProcessorFeatures() +{ + return MMX|SSE|SSE2; +} -#if defined(QT_HAVE_SSE) - if (qgetenv("QT_NO_SSE").toInt()) - features ^= SSE; -#endif -#if defined(QT_HAVE_SSE2) - if (qgetenv("QT_NO_SSE2").toInt()) - features ^= SSE2; +#else +static inline uint detectProcessorFeatures() +{ + return 0; +} #endif +/* + * Use kdesdk/scripts/generate_string_table.pl to update the table below. + * Here's the data (don't forget the ONE leading space): + mmx + mmxext + mmx3dnow + mmx3dnowext + sse + sse2 + cmov + iwmmxt + neon + sse3 + ssse3 + sse4.1 + sse4.2 + avx + */ + +// begin generated +static const char features_string[] = + " mmx\0" + " mmxext\0" + " mmx3dnow\0" + " mmx3dnowext\0" + " sse\0" + " sse2\0" + " cmov\0" + " iwmmxt\0" + " neon\0" + " sse3\0" + " ssse3\0" + " sse4.1\0" + " sse4.2\0" + " avx\0" + "\0"; + +static const int features_indices[] = { + 0, 5, 13, 23, 36, 41, 47, 53, + 61, 67, 73, 80, 88, 96, -1 +}; +// end generated + +const int features_count = (sizeof features_indices - 1) / (sizeof features_indices[0]); + +uint qDetectCPUFeatures() +{ + static QBasicAtomicInt features = Q_BASIC_ATOMIC_INITIALIZER(-1); + if (features != -1) + return features; + + uint f = detectProcessorFeatures(); + QByteArray disable = qgetenv("QT_NO_CPU_FEATURE"); + if (!disable.isEmpty()) { + disable.prepend(' '); + for (int i = 0; i < features_count; ++i) { + if (disable.contains(features_string + features_indices[i])) + f &= ~(1 << i); + } + } + + features = f; return features; -#endif +} + +void qDumpCPUFeatures() +{ + uint features = qDetectCPUFeatures(); + printf("Processor features: "); + for (int i = 0; i < features_count; ++i) { + if (features & (1 << i)) + printf("%s", features_string + features_indices[i]); + } + puts(""); } QT_END_NAMESPACE diff --git a/src/corelib/tools/qsimd_p.h b/src/corelib/tools/qsimd_p.h index a3148fb..664543b 100644 --- a/src/corelib/tools/qsimd_p.h +++ b/src/corelib/tools/qsimd_p.h @@ -51,8 +51,13 @@ QT_BEGIN_HEADER #if defined(QT_NO_MAC_XARCH) || (defined(Q_OS_DARWIN) && (defined(__ppc__) || defined(__ppc64__))) // Disable MMX and SSE on Mac/PPC builds, or if the compiler // does not support -Xarch argument passing -#undef QT_HAVE_SSE2 #undef QT_HAVE_SSE +#undef QT_HAVE_SSE2 +#undef QT_HAVE_SSE3 +#undef QT_HAVE_SSSE3 +#undef QT_HAVE_SSE4_1 +#undef QT_HAVE_SSE4_2 +#undef QT_HAVE_AVX #undef QT_HAVE_3DNOW #undef QT_HAVE_MMX #endif @@ -85,6 +90,7 @@ QT_BEGIN_HEADER // SSE4.1 and SSE4.2 intrinsics #if (defined(QT_HAVE_SSE4_1) || defined(QT_HAVE_SSE4_2)) && (defined(__SSE4_1__) || defined(Q_CC_MSVC)) #include <smmintrin.h> +#include <nmmintrin.h> #endif // AVX intrinsics diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 7ea9877..7589f59 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -189,19 +189,6 @@ static int ucstricmp(const ushort *a, const ushort *ae, const uchar *b) return 1; } -// Unicode case-insensitive comparison -static int ucstrcmp(const QChar *a, int alen, const QChar *b, int blen) -{ - if (a == b && alen == blen) - return 0; - int l = qMin(alen, blen); - while (l-- && *a == *b) - a++,b++; - if (l == -1) - return (alen-blen); - return a->unicode() - b->unicode(); -} - // Unicode case-sensitive compare two same-sized strings static int ucstrncmp(const QChar *a, const QChar *b, int l) { @@ -212,28 +199,71 @@ static int ucstrncmp(const QChar *a, const QChar *b, int l) return a->unicode() - b->unicode(); } +// Unicode case-sensitive comparison +static int ucstrcmp(const QChar *a, int alen, const QChar *b, int blen) +{ + if (a == b && alen == blen) + return 0; + int l = qMin(alen, blen); + int cmp = ucstrncmp(a, b, l); + return cmp ? cmp : (alen-blen); +} + // Unicode case-insensitive compare two same-sized strings static int ucstrnicmp(const ushort *a, const ushort *b, int l) { return ucstricmp(a, a + l, b, b + l); } +// Benchmarking indicates that doing memcmp is much slower than +// executing the comparison ourselves. +// +// The profiling was done on a population of calls to qMemEquals, generated +// during a run of the demo browser. The profile of the data (32-bit x86 +// Linux) was: +// +// total number of comparisons: 21353 +// longest string compared: 95 +// average comparison length: 14.8786 +// cache-line crosses: 5661 (13.3%) +// alignment histogram: +// 0xXXX0 = 512 (1.2%) strings, 0 (0.0%) of which same-aligned +// 0xXXX2 = 15087 (35.3%) strings, 5145 (34.1%) of which same-aligned +// 0xXXX4 = 525 (1.2%) strings, 0 (0.0%) of which same-aligned +// 0xXXX6 = 557 (1.3%) strings, 6 (1.1%) of which same-aligned +// 0xXXX8 = 509 (1.2%) strings, 0 (0.0%) of which same-aligned +// 0xXXXa = 24358 (57.0%) strings, 9901 (40.6%) of which same-aligned +// 0xXXXc = 557 (1.3%) strings, 0 (0.0%) of which same-aligned +// 0xXXXe = 601 (1.4%) strings, 15 (2.5%) of which same-aligned +// total = 42706 (100%) strings, 15067 (35.3%) of which same-aligned +// +// 92% of the strings have alignment of 2 or 10, which is due to malloc on +// 32-bit Linux returning values aligned to 8 bytes, and offsetof(array, QString::Data) == 18. +// +// The profile on 64-bit will be different since offsetof(array, QString::Data) == 26. +// +// The benchmark results were, for a Core-i7 @ 2.67 GHz 32-bit, compiled with -O3 -funroll-loops: +// 16-bit loads only: 872,301 CPU ticks [Qt 4.5 / memcmp] +// 32- and 16-bit loads: 773,362 CPU ticks [Qt 4.6] +// SSE2 "movdqu" 128-bit loads: 618,736 CPU ticks +// SSE3 "lddqu" 128-bit loads: 619,954 CPU ticks +// SSSE3 "palignr" corrections: 852,147 CPU ticks +// SSE4.2 "pcmpestrm": 738,702 CPU ticks +// +// The same benchmark on an Atom N450 @ 1.66 GHz, is: +// 16-bit loads only: 2,185,882 CPU ticks +// 32- and 16-bit loads: 1,805,060 CPU ticks +// SSE2 "movdqu" 128-bit loads: 2,529,843 CPU ticks +// SSE3 "lddqu" 128-bit loads: 2,514,858 CPU ticks +// SSSE3 "palignr" corrections: 2,160,325 CPU ticks +// SSE4.2 not available +// +// The conclusion we reach is that alignment the SSE2 unaligned code can gain +// 20% improvement in performance in some systems, but suffers a penalty due +// to the unaligned loads on others. + static bool qMemEquals(const quint16 *a, const quint16 *b, int length) { - // Benchmarking indicates that doing memcmp is much slower than - // executing the comparison ourselves. - // To make it even faster, we do a 32-bit comparison, comparing - // twice the amount of data as a normal word-by-word comparison. - // - // Benchmarking results on a 2.33 GHz Core2 Duo, with a 64-QChar - // block of data, with 4194304 iterations (per iteration): - // operation usec cpu ticks - // memcmp 330 710 - // 16-bit 79 167-171 - // 32-bit aligned 49 105-109 - // - // Testing also indicates that unaligned 32-bit loads are as - // performant as 32-bit aligned. if (a == b || !length) return true; @@ -927,6 +957,24 @@ QString QString::fromWCharArray(const wchar_t *string, int size) \sa utf16(), toAscii(), toLatin1(), toUtf8(), toLocal8Bit() */ +template<typename T> int toUcs4_helper(const unsigned short *uc, int length, T *out) +{ + int i = 0; + for (; i < length; ++i) { + uint u = uc[i]; + if (QChar::isHighSurrogate(u) && i < length-1) { + ushort low = uc[i+1]; + if (QChar::isLowSurrogate(low)) { + ++i; + u = QChar::surrogateToUcs4(u, low); + } + } + *out = T(u); + ++out; + } + return i; +} + /*! \since 4.2 @@ -951,21 +999,7 @@ int QString::toWCharArray(wchar_t *array) const memcpy(array, utf16(), sizeof(wchar_t)*length()); return length(); } else { - wchar_t *a = array; - const unsigned short *uc = utf16(); - for (int i = 0; i < length(); ++i) { - uint u = uc[i]; - if (QChar::isHighSurrogate(u) && i + 1 < length()) { - ushort low = uc[i+1]; - if (QChar::isLowSurrogate(low)) { - u = QChar::surrogateToUcs4(u, low); - ++i; - } - } - *a = wchar_t(u); - ++a; - } - return a - array; + return toUcs4_helper<wchar_t>(utf16(), length(), array); } } @@ -3701,7 +3735,7 @@ QByteArray QString::toUtf8() const Returns a UCS-4/UTF-32 representation of the string as a QVector<uint>. UCS-4 is a Unicode codec and is lossless. All characters from this string - can be encoded in UCS-4. + can be encoded in UCS-4. The vector is not null terminated. \sa fromUtf8(), toAscii(), toLatin1(), toLocal8Bit(), QTextCodec, fromUcs4(), toWCharArray() */ @@ -3709,20 +3743,8 @@ QVector<uint> QString::toUcs4() const { QVector<uint> v(length()); uint *a = v.data(); - const unsigned short *uc = utf16(); - for (int i = 0; i < length(); ++i) { - uint u = uc[i]; - if (QChar(u).isHighSurrogate() && i < length()-1) { - ushort low = uc[i+1]; - if (QChar(low).isLowSurrogate()) { - ++i; - u = QChar::surrogateToUcs4(u, low); - } - } - *a = u; - ++a; - } - v.resize(a - v.data()); + int len = toUcs4_helper<uint>(utf16(), length(), a); + v.resize(len); return v; } @@ -3943,8 +3965,8 @@ QString QString::fromUtf8(const char *str, int size) This function checks for a Byte Order Mark (BOM). If it is missing, host byte order is assumed. - This function is comparatively slow. - Use QString(const ushort *, int) or QString(const ushort *) if possible. + This function is slow compared to the other Unicode conversions. + Use QString(const QChar *, int) or QString(const QChar *) if possible. QString makes a deep copy of the Unicode data. @@ -8961,4 +8983,114 @@ static inline bool qt_ends_with(const QChar *haystack, int haystackLen, return true; } +/*! + \since 4.8 + + Returns a Latin-1 representation of the string as a QByteArray. + + The returned byte array is undefined if the string contains non-Latin1 + characters. Those characters may be suppressed or replaced with a + question mark. + + \sa toAscii(), toUtf8(), toLocal8Bit(), QTextCodec +*/ +QByteArray QStringRef::toLatin1() const +{ + return toLatin1_helper(unicode(), length()); +} + +/*! + \since 4.8 + + Returns an 8-bit representation of the string as a QByteArray. + + If a codec has been set using QTextCodec::setCodecForCStrings(), + it is used to convert Unicode to 8-bit char; otherwise this + function does the same as toLatin1(). + + Note that, despite the name, this function does not necessarily return an US-ASCII + (ANSI X3.4-1986) string and its result may not be US-ASCII compatible. + + \sa toLatin1(), toUtf8(), toLocal8Bit(), QTextCodec +*/ +QByteArray QStringRef::toAscii() const +{ +#ifndef QT_NO_TEXTCODEC + if (QString::codecForCStrings) + return QString::codecForCStrings->fromUnicode(unicode(), length()); +#endif // QT_NO_TEXTCODEC + return toLatin1(); +} + +/*! + \since 4.8 + + Returns the local 8-bit representation of the string as a + QByteArray. The returned byte array is undefined if the string + contains characters not supported by the local 8-bit encoding. + + QTextCodec::codecForLocale() is used to perform the conversion from + Unicode. If the locale encoding could not be determined, this function + does the same as toLatin1(). + + If this string contains any characters that cannot be encoded in the + locale, the returned byte array is undefined. Those characters may be + suppressed or replaced by another. + + \sa toAscii(), toLatin1(), toUtf8(), QTextCodec +*/ +QByteArray QStringRef::toLocal8Bit() const +{ +#ifndef QT_NO_TEXTCODEC + if (QTextCodec::codecForLocale()) + return QTextCodec::codecForLocale()->fromUnicode(unicode(), length()); +#endif // QT_NO_TEXTCODEC + return toLatin1(); +} + +/*! + \since 4.8 + + Returns a UTF-8 representation of the string as a QByteArray. + + UTF-8 is a Unicode codec and can represent all characters in a Unicode + string like QString. + + However, in the Unicode range, there are certain codepoints that are not + considered characters. The Unicode standard reserves the last two + codepoints in each Unicode Plane (U+FFFE, U+FFFF, U+1FFFE, U+1FFFF, + U+2FFFE, etc.), as well as 16 codepoints in the range U+FDD0..U+FDDF, + inclusive, as non-characters. If any of those appear in the string, they + may be discarded and will not appear in the UTF-8 representation, or they + may be replaced by one or more replacement characters. + + \sa toAscii(), toLatin1(), toLocal8Bit(), QTextCodec +*/ +QByteArray QStringRef::toUtf8() const +{ + if (isNull()) + return QByteArray(); + + return QUtf8::convertFromUnicode(constData(), length(), 0); +} + +/*! + \since 4.8 + + Returns a UCS-4/UTF-32 representation of the string as a QVector<uint>. + + UCS-4 is a Unicode codec and is lossless. All characters from this string + can be encoded in UCS-4. + + \sa fromUtf8(), toAscii(), toLatin1(), toLocal8Bit(), QTextCodec, fromUcs4(), toWCharArray() +*/ +QVector<uint> QStringRef::toUcs4() const +{ + QVector<uint> v(length()); + uint *a = v.data(); + int len = toUcs4_helper<uint>(reinterpret_cast<const unsigned short *>(unicode()), length(), a); + v.resize(len); + return v; +} + QT_END_NAMESPACE diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index 7f7e475..589fdc2 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -104,7 +104,10 @@ public: QString &operator=(QChar c); QString &operator=(const QString &); inline QString &operator=(const QLatin1String &); - +#ifdef Q_COMPILER_RVALUE_REFS + inline QString &operator=(QString &&other) + { qSwap(d, other.d); return *this; } +#endif inline int size() const { return d->size; } inline int count() const { return d->size; } inline int length() const; @@ -613,6 +616,7 @@ private: ushort asciiCache : 1; ushort capacity : 1; ushort reserved : 11; + // ### Qt5: try to ensure that "array" is aligned to 16 bytes on both 32- and 64-bit ushort array[1]; }; static Data shared_null; @@ -1161,6 +1165,12 @@ public: inline const QChar *data() const { return unicode(); } inline const QChar *constData() const { return unicode(); } + QByteArray toAscii() const Q_REQUIRED_RESULT; + QByteArray toLatin1() const Q_REQUIRED_RESULT; + QByteArray toUtf8() const Q_REQUIRED_RESULT; + QByteArray toLocal8Bit() const Q_REQUIRED_RESULT; + QVector<uint> toUcs4() const Q_REQUIRED_RESULT; + inline void clear() { m_string = 0; m_position = m_size = 0; } QString toString() const; inline bool isEmpty() const { return m_size == 0; } diff --git a/src/corelib/tools/qstringmatcher.cpp b/src/corelib/tools/qstringmatcher.cpp index 80a8457..d445ed4 100644 --- a/src/corelib/tools/qstringmatcher.cpp +++ b/src/corelib/tools/qstringmatcher.cpp @@ -40,7 +40,6 @@ ****************************************************************************/ #include "qstringmatcher.h" -#include "qunicodetables_p.h" QT_BEGIN_NAMESPACE diff --git a/src/corelib/tools/qunicodetables.cpp b/src/corelib/tools/qunicodetables.cpp index 9df31e5..68e72cc 100644 --- a/src/corelib/tools/qunicodetables.cpp +++ b/src/corelib/tools/qunicodetables.cpp @@ -4345,6 +4345,11 @@ Q_CORE_EXPORT const QUnicodeTables::Properties * QT_FASTCALL QUnicodeTables::pro return uc_properties + index; } +Q_CORE_EXPORT QUnicodeTables::LineBreakClass QT_FASTCALL QUnicodeTables::lineBreakClass(uint ucs4) +{ + return (QUnicodeTables::LineBreakClass)qGetProp(ucs4)->line_break_class; +} + static const ushort specialCaseMap[] = { 0x53, 0x73, 0x0, 0x53, 0x53, 0x0, @@ -8561,7 +8566,7 @@ static const unsigned char uc_scripts[] = { Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Common, Common, Common, Common, Greek, Greek, Common, Common, - Common, Common, Greek, Greek, Greek, Greek, Common, Common, + Common, Common, Greek, Greek, Greek, Greek, Common, Common, /* U+0380-03ff at offset 640 */ Common, Common, Common, Common, Greek, Greek, Greek, Common, @@ -8579,7 +8584,7 @@ static const unsigned char uc_scripts[] = { Greek, Greek, Coptic, Coptic, Coptic, Coptic, Coptic, Coptic, Coptic, Coptic, Coptic, Coptic, Coptic, Coptic, Coptic, Coptic, Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, - Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, + Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, /* U+0480-04ff at offset 768 */ Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Common, @@ -8597,7 +8602,7 @@ static const unsigned char uc_scripts[] = { Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, - Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, + Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, /* U+0500-057f at offset 896 */ Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, @@ -8615,7 +8620,7 @@ static const unsigned char uc_scripts[] = { Common, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, - Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, + Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, /* U+0580-05ff at offset 1024 */ Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, @@ -8633,7 +8638,7 @@ static const unsigned char uc_scripts[] = { Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Common, Common, Common, Common, Common, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Common, Common, Common, - Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, /* U+0600-067f at offset 1152 */ Common, Common, Common, Common, Common, Common, Common, Common, @@ -8651,7 +8656,7 @@ static const unsigned char uc_scripts[] = { Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Inherited, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, - Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, /* U+0680-06ff at offset 1280 */ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, @@ -8669,7 +8674,7 @@ static const unsigned char uc_scripts[] = { Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, - Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, /* U+0700-077f at offset 1408 */ Syriac, Syriac, Syriac, Syriac, Syriac, Syriac, Syriac, Syriac, @@ -8687,7 +8692,7 @@ static const unsigned char uc_scripts[] = { Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, - Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, /* U+0780-07ff at offset 1536 */ Thaana, Thaana, Thaana, Thaana, Thaana, Thaana, Thaana, Thaana, @@ -8705,7 +8710,7 @@ static const unsigned char uc_scripts[] = { Nko, Nko, Nko, Nko, Nko, Nko, Nko, Nko, Nko, Nko, Nko, Nko, Nko, Nko, Nko, Nko, Nko, Nko, Nko, Nko, Nko, Nko, Nko, Nko, - Nko, Nko, Nko, Common, Common, Common, Common, Common, + Nko, Nko, Nko, Common, Common, Common, Common, Common, /* U+0900-097f at offset 1664 */ Common, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, @@ -8723,7 +8728,7 @@ static const unsigned char uc_scripts[] = { Devanagari, Devanagari, Devanagari, Devanagari, Common, Common, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Common, Common, Common, Common, Common, Common, Common, Common, - Common, Common, Common, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, + Common, Common, Common, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, /* U+0980-09ff at offset 1792 */ Common, Bengali, Bengali, Bengali, Common, Bengali, Bengali, Bengali, @@ -8741,7 +8746,7 @@ static const unsigned char uc_scripts[] = { Bengali, Bengali, Bengali, Bengali, Common, Common, Bengali, Bengali, Bengali, Bengali, Bengali, Bengali, Bengali, Bengali, Bengali, Bengali, Bengali, Bengali, Bengali, Bengali, Bengali, Bengali, Bengali, Bengali, - Bengali, Bengali, Bengali, Common, Common, Common, Common, Common, + Bengali, Bengali, Bengali, Common, Common, Common, Common, Common, /* U+0a00-0a7f at offset 1920 */ Common, Gurmukhi, Gurmukhi, Gurmukhi, Common, Gurmukhi, Gurmukhi, Gurmukhi, @@ -8759,7 +8764,7 @@ static const unsigned char uc_scripts[] = { Common, Common, Common, Common, Common, Common, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Common, Common, Common, - Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, /* U+0a80-0aff at offset 2048 */ Common, Gujarati, Gujarati, Gujarati, Common, Gujarati, Gujarati, Gujarati, @@ -8777,7 +8782,7 @@ static const unsigned char uc_scripts[] = { Gujarati, Gujarati, Gujarati, Gujarati, Common, Common, Gujarati, Gujarati, Gujarati, Gujarati, Gujarati, Gujarati, Gujarati, Gujarati, Gujarati, Gujarati, Common, Gujarati, Common, Common, Common, Common, Common, Common, - Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, /* U+0b00-0b7f at offset 2176 */ Common, Oriya, Oriya, Oriya, Common, Oriya, Oriya, Oriya, @@ -8795,7 +8800,7 @@ static const unsigned char uc_scripts[] = { Oriya, Oriya, Common, Common, Common, Common, Oriya, Oriya, Oriya, Oriya, Oriya, Oriya, Oriya, Oriya, Oriya, Oriya, Oriya, Oriya, Common, Common, Common, Common, Common, Common, - Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, /* U+0b80-0bff at offset 2304 */ Common, Common, Tamil, Tamil, Common, Tamil, Tamil, Tamil, @@ -8813,7 +8818,7 @@ static const unsigned char uc_scripts[] = { Common, Common, Common, Common, Common, Common, Tamil, Tamil, Tamil, Tamil, Tamil, Tamil, Tamil, Tamil, Tamil, Tamil, Tamil, Tamil, Tamil, Tamil, Tamil, Tamil, Tamil, Tamil, - Tamil, Tamil, Tamil, Common, Common, Common, Common, Common, + Tamil, Tamil, Tamil, Common, Common, Common, Common, Common, /* U+0c00-0c7f at offset 2432 */ Common, Telugu, Telugu, Telugu, Common, Telugu, Telugu, Telugu, @@ -8831,7 +8836,7 @@ static const unsigned char uc_scripts[] = { Telugu, Telugu, Common, Common, Common, Common, Telugu, Telugu, Telugu, Telugu, Telugu, Telugu, Telugu, Telugu, Telugu, Telugu, Common, Common, Common, Common, Common, Common, Common, Common, - Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, /* U+0c80-0cff at offset 2560 */ Common, Common, Kannada, Kannada, Common, Kannada, Kannada, Kannada, @@ -8849,7 +8854,7 @@ static const unsigned char uc_scripts[] = { Kannada, Kannada, Kannada, Kannada, Common, Common, Kannada, Kannada, Kannada, Kannada, Kannada, Kannada, Kannada, Kannada, Kannada, Kannada, Common, Kannada, Kannada, Common, Common, Common, Common, Common, - Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, /* U+0d00-0d7f at offset 2688 */ Common, Common, Malayalam, Malayalam, Common, Malayalam, Malayalam, Malayalam, @@ -8867,7 +8872,7 @@ static const unsigned char uc_scripts[] = { Malayalam, Malayalam, Common, Common, Common, Common, Malayalam, Malayalam, Malayalam, Malayalam, Malayalam, Malayalam, Malayalam, Malayalam, Malayalam, Malayalam, Common, Common, Common, Common, Common, Common, Common, Common, - Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, /* U+0d80-0dff at offset 2816 */ Common, Common, Sinhala, Sinhala, Common, Sinhala, Sinhala, Sinhala, @@ -8885,7 +8890,7 @@ static const unsigned char uc_scripts[] = { Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Sinhala, Sinhala, Sinhala, Common, Common, Common, - Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, /* U+0e00-0e7f at offset 2944 */ Common, Thai, Thai, Thai, Thai, Thai, Thai, Thai, @@ -8903,7 +8908,7 @@ static const unsigned char uc_scripts[] = { Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, - Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, /* U+0e80-0eff at offset 3072 */ Common, Lao, Lao, Common, Lao, Common, Common, Lao, @@ -8921,7 +8926,7 @@ static const unsigned char uc_scripts[] = { Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, - Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, /* U+0f00-0f7f at offset 3200 */ Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, @@ -8939,7 +8944,7 @@ static const unsigned char uc_scripts[] = { Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Common, Common, Common, Common, Common, Common, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, - Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, + Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, /* U+0f80-0fff at offset 3328 */ Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, @@ -8957,7 +8962,7 @@ static const unsigned char uc_scripts[] = { Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, - Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, /* U+1000-107f at offset 3456 */ Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, @@ -8975,7 +8980,7 @@ static const unsigned char uc_scripts[] = { Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, - Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, /* U+1080-10ff at offset 3584 */ Common, Common, Common, Common, Common, Common, Common, Common, @@ -8993,7 +8998,7 @@ static const unsigned char uc_scripts[] = { Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, - Georgian, Georgian, Georgian, Common, Georgian, Common, Common, Common, + Georgian, Georgian, Georgian, Common, Georgian, Common, Common, Common, /* U+1100-117f at offset 3712 */ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, @@ -9011,7 +9016,7 @@ static const unsigned char uc_scripts[] = { Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, - Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, /* U+1180-11ff at offset 3840 */ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, @@ -9029,7 +9034,7 @@ static const unsigned char uc_scripts[] = { Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, - Hangul, Hangul, Common, Common, Common, Common, Common, Common, + Hangul, Hangul, Common, Common, Common, Common, Common, Common, /* U+1680-16ff at offset 3968 */ Ogham, Ogham, Ogham, Ogham, Ogham, Ogham, Ogham, Ogham, @@ -9047,7 +9052,7 @@ static const unsigned char uc_scripts[] = { Runic, Runic, Runic, Runic, Runic, Runic, Runic, Runic, Runic, Runic, Runic, Common, Common, Common, Runic, Runic, Runic, Common, Common, Common, Common, Common, Common, Common, - Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, /* U+1780-17ff at offset 4096 */ Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, @@ -9065,7 +9070,7 @@ static const unsigned char uc_scripts[] = { Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Common, Common, Common, Common, Common, Common, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, - Khmer, Khmer, Common, Common, Common, Common, Common, Common, + Khmer, Khmer, Common, Common, Common, Common, Common, Common, /* U+1980-19ff at offset 4224 */ NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, @@ -9083,7 +9088,7 @@ static const unsigned char uc_scripts[] = { Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, - Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, + Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, /* U+1d00-1d7f at offset 4352 */ Latin, Latin, Latin, Latin, Latin, Latin, Latin, Latin, @@ -9101,7 +9106,7 @@ static const unsigned char uc_scripts[] = { Greek, Greek, Latin, Latin, Latin, Latin, Greek, Greek, Greek, Greek, Greek, Latin, Latin, Latin, Latin, Latin, Latin, Latin, Latin, Latin, Latin, Latin, Latin, Latin, - Cyrillic, Latin, Latin, Latin, Latin, Latin, Latin, Latin, + Cyrillic, Latin, Latin, Latin, Latin, Latin, Latin, Latin, /* U+1d80-1dff at offset 4480 */ Latin, Latin, Latin, Latin, Latin, Latin, Latin, Latin, @@ -9119,7 +9124,7 @@ static const unsigned char uc_scripts[] = { Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, - Common, Common, Common, Common, Common, Common, Inherited, Inherited, + Common, Common, Common, Common, Common, Common, Inherited, Inherited, /* U+1f00-1f7f at offset 4608 */ Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, @@ -9137,7 +9142,7 @@ static const unsigned char uc_scripts[] = { Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, - Greek, Greek, Greek, Greek, Greek, Greek, Common, Common, + Greek, Greek, Greek, Greek, Greek, Greek, Common, Common, /* U+1f80-1fff at offset 4736 */ Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, @@ -9155,7 +9160,7 @@ static const unsigned char uc_scripts[] = { Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, Common, Common, Greek, Greek, Greek, Common, Greek, Greek, - Greek, Greek, Greek, Greek, Greek, Greek, Greek, Common, + Greek, Greek, Greek, Greek, Greek, Greek, Greek, Common, /* U+2000-207f at offset 4864 */ Common, Common, Common, Common, Common, Common, Common, Common, @@ -9173,7 +9178,7 @@ static const unsigned char uc_scripts[] = { Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Latin, Common, Common, Common, Common, Common, Common, - Common, Common, Common, Common, Common, Common, Common, Latin, + Common, Common, Common, Common, Common, Common, Common, Latin, /* U+2080-20ff at offset 4992 */ Common, Common, Common, Common, Common, Common, Common, Common, @@ -9191,7 +9196,7 @@ static const unsigned char uc_scripts[] = { Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Common, Common, Common, Common, Common, Common, Common, Common, - Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, /* U+2100-217f at offset 5120 */ Common, Common, Common, Common, Common, Common, Common, Common, @@ -9209,7 +9214,7 @@ static const unsigned char uc_scripts[] = { Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, - Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, /* U+2d00-2d7f at offset 5248 */ Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, @@ -9227,7 +9232,7 @@ static const unsigned char uc_scripts[] = { Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, Common, Common, Common, Common, Common, Common, Common, Common, Common, Tifinagh, Common, Common, Common, Common, Common, Common, Common, Common, - Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, /* U+3000-307f at offset 5376 */ Common, Common, Common, Common, Common, Han, Common, Han, @@ -9245,7 +9250,7 @@ static const unsigned char uc_scripts[] = { Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, - Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, + Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, /* U+3080-30ff at offset 5504 */ Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, @@ -9263,7 +9268,7 @@ static const unsigned char uc_scripts[] = { Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, - Katakana, Katakana, Katakana, Common, Common, Katakana, Katakana, Katakana, + Katakana, Katakana, Katakana, Common, Common, Katakana, Katakana, Katakana, /* U+3100-317f at offset 5632 */ Common, Common, Common, Common, Common, Bopomofo, Bopomofo, Bopomofo, @@ -9281,7 +9286,7 @@ static const unsigned char uc_scripts[] = { Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, - Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, /* U+3180-31ff at offset 5760 */ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, @@ -9299,7 +9304,7 @@ static const unsigned char uc_scripts[] = { Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, - Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, + Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, /* U+3200-327f at offset 5888 */ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, @@ -9317,7 +9322,7 @@ static const unsigned char uc_scripts[] = { Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, - Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Common, Common, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Common, Common, /* U+d780-d7ff at offset 6016 */ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, @@ -9335,7 +9340,7 @@ static const unsigned char uc_scripts[] = { Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, - Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, /* U+fb00-fb7f at offset 6144 */ Latin, Latin, Latin, Latin, Latin, Latin, Latin, Common, @@ -9353,7 +9358,7 @@ static const unsigned char uc_scripts[] = { Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, - Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, /* U+fb80-fbff at offset 6272 */ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, @@ -9371,7 +9376,7 @@ static const unsigned char uc_scripts[] = { Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, - Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, /* U+fd00-fd7f at offset 6400 */ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, @@ -9389,7 +9394,7 @@ static const unsigned char uc_scripts[] = { Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, - Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, /* U+fd80-fdff at offset 6528 */ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, @@ -9407,7 +9412,7 @@ static const unsigned char uc_scripts[] = { Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, - Arabic, Arabic, Arabic, Arabic, Arabic, Common, Common, Common, + Arabic, Arabic, Arabic, Arabic, Arabic, Common, Common, Common, /* U+fe00-fe7f at offset 6656 */ Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, @@ -9425,7 +9430,7 @@ static const unsigned char uc_scripts[] = { Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Arabic, Arabic, Arabic, Arabic, Arabic, Common, Arabic, Arabic, - Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, /* U+fe80-feff at offset 6784 */ Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, @@ -9443,7 +9448,7 @@ static const unsigned char uc_scripts[] = { Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, - Arabic, Arabic, Arabic, Arabic, Arabic, Common, Common, Common, + Arabic, Arabic, Arabic, Arabic, Arabic, Common, Common, Common, /* U+ff80-ffff at offset 6912 */ Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, @@ -9461,9 +9466,21 @@ static const unsigned char uc_scripts[] = { Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, Common, - Common, Common, Common, Common, Common, Common, Common, Common + Common, Common, Common, Common, Common, Common, Common, Common }; } // namespace QUnicodeTables +Q_CORE_EXPORT int QT_FASTCALL QUnicodeTables::script(uint ucs4) +{ + if (ucs4 > 0xffff) + return Common; + int script = uc_scripts[ucs4 >> 7]; + if (script < ScriptSentinel) + return script; + script = (((script - ScriptSentinel) * UnicodeBlockSize) + UnicodeBlockCount); + script = uc_scripts[script + (ucs4 & 0x7f)]; + return script; +} + QT_END_NAMESPACE diff --git a/src/corelib/tools/qunicodetables_p.h b/src/corelib/tools/qunicodetables_p.h index 5c7cc08..be52bf9 100644 --- a/src/corelib/tools/qunicodetables_p.h +++ b/src/corelib/tools/qunicodetables_p.h @@ -162,20 +162,6 @@ namespace QUnicodeTables { enum { ScriptSentinel = 32 }; - // see http://www.unicode.org/reports/tr14/tr14-19.html - // we don't use the XX, AI and CB properties and map them to AL instead. - // as we don't support any EBDIC based OS'es, NL is ignored and mapped to AL as well. - enum LineBreakClass { - LineBreak_OP, LineBreak_CL, LineBreak_QU, LineBreak_GL, LineBreak_NS, - LineBreak_EX, LineBreak_SY, LineBreak_IS, LineBreak_PR, LineBreak_PO, - LineBreak_NU, LineBreak_AL, LineBreak_ID, LineBreak_IN, LineBreak_HY, - LineBreak_BA, LineBreak_BB, LineBreak_B2, LineBreak_ZW, LineBreak_CM, - LineBreak_WJ, LineBreak_H2, LineBreak_H3, LineBreak_JL, LineBreak_JV, - LineBreak_JT, LineBreak_SA, LineBreak_SG, - LineBreak_SP, LineBreak_CR, LineBreak_LF, LineBreak_BK - }; - - enum GraphemeBreak { GraphemeBreakOther, GraphemeBreakCR, @@ -217,6 +203,20 @@ namespace QUnicodeTables { }; + // see http://www.unicode.org/reports/tr14/tr14-19.html + // we don't use the XX, AI and CB properties and map them to AL instead. + // as we don't support any EBDIC based OS'es, NL is ignored and mapped to AL as well. + enum LineBreakClass { + LineBreak_OP, LineBreak_CL, LineBreak_QU, LineBreak_GL, LineBreak_NS, + LineBreak_EX, LineBreak_SY, LineBreak_IS, LineBreak_PR, LineBreak_PO, + LineBreak_NU, LineBreak_AL, LineBreak_ID, LineBreak_IN, LineBreak_HY, + LineBreak_BA, LineBreak_BB, LineBreak_B2, LineBreak_ZW, LineBreak_CM, + LineBreak_WJ, LineBreak_H2, LineBreak_H3, LineBreak_JL, LineBreak_JV, + LineBreak_JT, LineBreak_SA, LineBreak_SG, + LineBreak_SP, LineBreak_CR, LineBreak_LF, LineBreak_BK + }; + + Q_CORE_EXPORT QUnicodeTables::LineBreakClass QT_FASTCALL lineBreakClass(uint ucs4); inline int lineBreakClass(const QChar &ch) { return lineBreakClass(ch.unicode()); } diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h index 5613c12..c16aefb 100644 --- a/src/corelib/tools/qvector.h +++ b/src/corelib/tools/qvector.h @@ -53,6 +53,9 @@ #endif #include <stdlib.h> #include <string.h> +#ifdef Q_COMPILER_INITIALIZER_LISTS +#include <initializer_list> +#endif QT_BEGIN_HEADER @@ -118,6 +121,13 @@ public: inline QVector(const QVector<T> &v) : d(v.d) { d->ref.ref(); if (!d->sharable) detach_helper(); } inline ~QVector() { if (!d) return; if (!d->ref.deref()) free(p); } QVector<T> &operator=(const QVector<T> &v); +#ifdef Q_COMPILER_RVALUE_REFS + inline QVector<T> operator=(QVector<T> &&other) + { qSwap(p, other.p); return *this; } +#endif +#ifdef Q_COMPILER_INITIALIZER_LISTS + inline QVector(std::initializer_list<T> args); +#endif bool operator==(const QVector<T> &v) const; inline bool operator!=(const QVector<T> &v) const { return !(*this == v); } @@ -293,11 +303,10 @@ public: #ifndef QT_NO_STL static inline QVector<T> fromStdVector(const std::vector<T> &vector) - { QVector<T> tmp; qCopy(vector.begin(), vector.end(), std::back_inserter(tmp)); return tmp; } + { QVector<T> tmp; tmp.reserve(vector.size()); qCopy(vector.begin(), vector.end(), std::back_inserter(tmp)); return tmp; } inline std::vector<T> toStdVector() const - { std::vector<T> tmp; qCopy(constBegin(), constEnd(), std::back_inserter(tmp)); return tmp; } + { std::vector<T> tmp; tmp.reserve(size()); qCopy(constBegin(), constEnd(), std::back_inserter(tmp)); return tmp; } #endif - private: friend class QRegion; // Optimization for QRegion::rects() @@ -377,10 +386,11 @@ inline void QVector<T>::replace(int i, const T &t) template <typename T> QVector<T> &QVector<T>::operator=(const QVector<T> &v) { - v.d->ref.ref(); + QVectorData *o = v.d; + o->ref.ref(); if (!d->ref.deref()) free(p); - d = v.d; + d = o; if (!d->sharable) detach_helper(); return *this; @@ -425,6 +435,22 @@ QVector<T>::QVector(int asize, const T &t) new (--i) T(t); } +#ifdef Q_COMPILER_INITIALIZER_LISTS +template <typename T> +QVector<T>::QVector(std::initializer_list<T> args) +{ + d = malloc(args.size()); + d->ref = 1; + d->alloc = d->size = args.size(); + d->sharable = true; + d->capacity = false; + T* i = p->array + d->size; + auto it = args.end(); + while (i != p->array) + new (--i) T(*(--it)); +} +#endif + template <typename T> void QVector<T>::free(Data *x) { |