diff options
Diffstat (limited to 'src/corelib')
93 files changed, 3238 insertions, 4363 deletions
diff --git a/src/corelib/arch/arch.pri b/src/corelib/arch/arch.pri index 51e67abfd4..5c3b0b78c2 100644 --- a/src/corelib/arch/arch.pri +++ b/src/corelib/arch/arch.pri @@ -1,20 +1,12 @@ win32|wince:HEADERS += arch/qatomic_msvc.h -vxworks:HEADERS += arch/qatomic_vxworks.h -integrity:HEADERS += arch/qatomic_integrity.h HEADERS += \ - arch/qatomic_alpha.h \ arch/qatomic_armv5.h \ arch/qatomic_armv6.h \ arch/qatomic_armv7.h \ - arch/qatomic_bfin.h \ arch/qatomic_bootstrap.h \ arch/qatomic_ia64.h \ arch/qatomic_mips.h \ - arch/qatomic_power.h \ - arch/qatomic_s390.h \ - arch/qatomic_sh4a.h \ - arch/qatomic_sparc.h \ arch/qatomic_x86.h \ arch/qatomic_gcc.h \ arch/qatomic_cxx11.h diff --git a/src/corelib/arch/qatomic_alpha.h b/src/corelib/arch/qatomic_alpha.h deleted file mode 100644 index 5008a1acda..0000000000 --- a/src/corelib/arch/qatomic_alpha.h +++ /dev/null @@ -1,527 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QATOMIC_ALPHA_H -#define QATOMIC_ALPHA_H - -#include <QtCore/qoldbasicatomic.h> - -QT_BEGIN_NAMESPACE - -#if 0 -// silence syncqt warnings -QT_END_NAMESPACE -QT_END_HEADER - -#pragma qt_sync_skip_header_check -#pragma qt_sync_stop_processing -#endif - -#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE - -inline bool QBasicAtomicInt::isReferenceCountingNative() -{ return true; } -inline bool QBasicAtomicInt::isReferenceCountingWaitFree() -{ return false; } - -#define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE - -inline bool QBasicAtomicInt::isTestAndSetNative() -{ return true; } -inline bool QBasicAtomicInt::isTestAndSetWaitFree() -{ return false; } - -#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE - -inline bool QBasicAtomicInt::isFetchAndStoreNative() -{ return true; } -inline bool QBasicAtomicInt::isFetchAndStoreWaitFree() -{ return false; } - -#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE - -inline bool QBasicAtomicInt::isFetchAndAddNative() -{ return true; } -inline bool QBasicAtomicInt::isFetchAndAddWaitFree() -{ return false; } - -#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative() -{ return true; } -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree() -{ return false; } - -#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative() -{ return true; } -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree() -{ return false; } - -#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative() -{ return true; } -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree() -{ return false; } - -#if defined(Q_CC_GNU) - -inline bool QBasicAtomicInt::ref() -{ - int old, tmp; - asm volatile("1:\n" - "ldl_l %0,%2\n" /* old=*ptr; */ - "addl %0,1,%1\n" /* tmp=old+1; */ - "stl_c %1,%2\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */ - "beq %1,2f\n" /* if (tmp == 0) goto 2; */ - "br 3f\n" /* goto 3; */ - "2: br 1b\n" /* goto 1; */ - "3:\n" - : "=&r" (old), "=&r" (tmp), "+m"(_q_value) - : - : "memory"); - return old != -1; -} - -inline bool QBasicAtomicInt::deref() -{ - int old, tmp; - asm volatile("1:\n" - "ldl_l %0,%2\n" /* old=*ptr; */ - "subl %0,1,%1\n" /* tmp=old-1; */ - "stl_c %1,%2\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */ - "beq %1,2f\n" /* if (tmp==0) goto 2; */ - "br 3f\n" /* goto 3; */ - "2: br 1b\n" /* goto 1; */ - "3:\n" - : "=&r" (old), "=&r" (tmp), "+m"(_q_value) - : - : "memory"); - return old != 1; -} - -inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) -{ - int ret; - asm volatile("1:\n" - "ldl_l %0,%1\n" /* ret=*ptr; */ - "cmpeq %0,%2,%0\n"/* if (ret==expected) ret=0; else ret=1; */ - "beq %0,3f\n" /* if (ret==0) goto 3; */ - "mov %3,%0\n" /* ret=newval; */ - "stl_c %0,%1\n" /* if ((*ptr=ret)!=ret) ret=0; else ret=1; */ - "beq %0,2f\n" /* if (ret==0) goto 2; */ - "br 3f\n" /* goto 3; */ - "2: br 1b\n" /* goto 1; */ - "3:\n" - : "=&r" (ret), "+m" (_q_value) - : "r" (expectedValue), "r" (newValue) - : "memory"); - return ret != 0; -} - -inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue) -{ - int ret; - asm volatile("1:\n" - "ldl_l %0,%1\n" /* ret=*ptr; */ - "cmpeq %0,%2,%0\n"/* if (ret==expected) ret=0; else ret=1; */ - "beq %0,3f\n" /* if (ret==0) goto 3; */ - "mov %3,%0\n" /* ret=newval; */ - "stl_c %0,%1\n" /* if ((*ptr=ret)!=ret) ret=0; else ret=1; */ - "beq %0,2f\n" /* if (ret==0) goto 2; */ - "br 3f\n" /* goto 3; */ - "2: br 1b\n" /* goto 1; */ - "3:\n" - "mb\n" - : "=&r" (ret), "+m" (_q_value) - : "r" (expectedValue), "r" (newValue) - : "memory"); - return ret != 0; -} - -inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue) -{ - int ret; - asm volatile("mb\n" - "1:\n" - "ldl_l %0,%1\n" /* ret=*ptr; */ - "cmpeq %0,%2,%0\n"/* if (ret==expected) ret=0; else ret=1; */ - "beq %0,3f\n" /* if (ret==0) goto 3; */ - "mov %3,%0\n" /* ret=newval; */ - "stl_c %0,%1\n" /* if ((*ptr=ret)!=ret) ret=0; else ret=1; */ - "beq %0,2f\n" /* if (ret==0) goto 2; */ - "br 3f\n" /* goto 3; */ - "2: br 1b\n" /* goto 1; */ - "3:\n" - : "=&r" (ret), "+m" (_q_value) - : "r" (expectedValue), "r" (newValue) - : "memory"); - return ret != 0; -} - -inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue) -{ - int old, tmp; - asm volatile("1:\n" - "ldl_l %0,%2\n" /* old=*ptr; */ - "mov %3,%1\n" /* tmp=newval; */ - "stl_c %1,%2\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */ - "beq %1,2f\n" /* if (tmp==0) goto 2; */ - "br 3f\n" /* goto 3; */ - "2: br 1b\n" /* goto 1; */ - "3:\n" - : "=&r" (old), "=&r" (tmp), "+m" (_q_value) - : "r" (newValue) - : "memory"); - return old; -} - -inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue) -{ - int old, tmp; - asm volatile("1:\n" - "ldl_l %0,%2\n" /* old=*ptr; */ - "mov %3,%1\n" /* tmp=newval; */ - "stl_c %1,%2\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */ - "beq %1,2f\n" /* if (tmp==0) goto 2; */ - "br 3f\n" /* goto 3; */ - "2: br 1b\n" /* goto 1; */ - "3:\n" - "mb\n" - : "=&r" (old), "=&r" (tmp), "+m" (_q_value) - : "r" (newValue) - : "memory"); - return old; -} - -inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue) -{ - int old, tmp; - asm volatile("mb\n" - "1:\n" - "ldl_l %0,%2\n" /* old=*ptr; */ - "mov %3,%1\n" /* tmp=newval; */ - "stl_c %1,%2\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */ - "beq %1,2f\n" /* if (tmp==0) goto 2; */ - "br 3f\n" /* goto 3; */ - "2: br 1b\n" /* goto 1; */ - "3:\n" - : "=&r" (old), "=&r" (tmp), "+m" (_q_value) - : "r" (newValue) - : "memory"); - return old; -} - -inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd) -{ - int old, tmp; - asm volatile("1:\n" - "ldl_l %0,%2\n" /* old=*ptr; */ - "addl %0,%3,%1\n"/* tmp=old+value; */ - "stl_c %1,%2\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */ - "beq %1,2f\n" /* if (tmp == 0) goto 2; */ - "br 3f\n" /* goto 3; */ - "2: br 1b\n" /* goto 1; */ - "3:\n" - : "=&r" (old), "=&r" (tmp), "+m"(_q_value) - : "r" (valueToAdd) - : "memory"); - return old; -} - -inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd) -{ - int old, tmp; - asm volatile("1:\n" - "ldl_l %0,%2\n" /* old=*ptr; */ - "addl %0,%3,%1\n"/* tmp=old+value; */ - "stl_c %1,%2\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */ - "beq %1,2f\n" /* if (tmp == 0) goto 2; */ - "br 3f\n" /* goto 3; */ - "2: br 1b\n" /* goto 1; */ - "3:\n" - "mb\n" - : "=&r" (old), "=&r" (tmp), "+m"(_q_value) - : "r" (valueToAdd) - : "memory"); - return old; -} - -inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd) -{ - int old, tmp; - asm volatile("mb\n" - "1:\n" - "ldl_l %0,%2\n" /* old=*ptr; */ - "addl %0,%3,%1\n"/* tmp=old+value; */ - "stl_c %1,%2\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */ - "beq %1,2f\n" /* if (tmp == 0) goto 2; */ - "br 3f\n" /* goto 3; */ - "2: br 1b\n" /* goto 1; */ - "3:\n" - : "=&r" (old), "=&r" (tmp), "+m"(_q_value) - : "r" (valueToAdd) - : "memory"); - return old; -} - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue) -{ - void *ret; - asm volatile("1:\n" - "ldq_l %0,%1\n" /* ret=*ptr; */ - "cmpeq %0,%2,%0\n"/* if (ret==expected) tmp=0; else tmp=1; */ - "beq %0,3f\n" /* if (tmp==0) goto 3; */ - "mov %3,%0\n" /* tmp=newval; */ - "stq_c %0,%1\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */ - "beq %0,2f\n" /* if (ret==0) goto 2; */ - "br 3f\n" /* goto 3; */ - "2: br 1b\n" /* goto 1; */ - "3:\n" - : "=&r" (ret), "+m" (_q_value) - : "r" (expectedValue), "r" (newValue) - : "memory"); - return ret != 0; -} - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue) -{ - void *ret; - asm volatile("1:\n" - "ldq_l %0,%1\n" /* ret=*ptr; */ - "cmpeq %0,%2,%0\n"/* if (ret==expected) tmp=0; else tmp=1; */ - "beq %0,3f\n" /* if (tmp==0) goto 3; */ - "mov %3,%0\n" /* tmp=newval; */ - "stq_c %0,%1\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */ - "beq %0,2f\n" /* if (ret==0) goto 2; */ - "br 3f\n" /* goto 3; */ - "2: br 1b\n" /* goto 1; */ - "3:\n" - "mb\n" - : "=&r" (ret), "+m" (_q_value) - : "r" (expectedValue), "r" (newValue) - : "memory"); - return ret != 0; -} - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue) -{ - void *ret; - asm volatile("mb\n" - "1:\n" - "ldq_l %0,%1\n" /* ret=*ptr; */ - "cmpeq %0,%2,%0\n"/* if (ret==expected) tmp=0; else tmp=1; */ - "beq %0,3f\n" /* if (tmp==0) goto 3; */ - "mov %3,%0\n" /* tmp=newval; */ - "stq_c %0,%1\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */ - "beq %0,2f\n" /* if (ret==0) goto 2; */ - "br 3f\n" /* goto 3; */ - "2: br 1b\n" /* goto 1; */ - "3:\n" - : "=&r" (ret), "+m" (_q_value) - : "r" (expectedValue), "r" (newValue) - : "memory"); - return ret != 0; -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue) -{ - T *old, *tmp; - asm volatile("1:\n" - "ldq_l %0,%2\n" /* old=*ptr; */ - "mov %3,%1\n" /* tmp=newval; */ - "stq_c %1,%2\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */ - "beq %1,2f\n" /* if (tmp==0) goto 2; */ - "br 3f\n" /* goto 3; */ - "2: br 1b\n" /* goto 1; */ - "3:\n" - : "=&r" (old), "=&r" (tmp), "+m" (_q_value) - : "r" (newValue) - : "memory"); - return old; -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue) -{ - T *old, *tmp; - asm volatile("1:\n" - "ldq_l %0,%2\n" /* old=*ptr; */ - "mov %3,%1\n" /* tmp=newval; */ - "stq_c %1,%2\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */ - "beq %1,2f\n" /* if (tmp==0) goto 2; */ - "br 3f\n" /* goto 3; */ - "2: br 1b\n" /* goto 1; */ - "3:\n" - "mb\n" - : "=&r" (old), "=&r" (tmp), "+m" (_q_value) - : "r" (newValue) - : "memory"); - return old; -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue) -{ - T *old, *tmp; - asm volatile("mb\n" - "1:\n" - "ldq_l %0,%2\n" /* old=*ptr; */ - "mov %3,%1\n" /* tmp=newval; */ - "stq_c %1,%2\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */ - "beq %1,2f\n" /* if (tmp==0) goto 2; */ - "br 3f\n" /* goto 3; */ - "2: br 1b\n" /* goto 1; */ - "3:\n" - : "=&r" (old), "=&r" (tmp), "+m" (_q_value) - : "r" (newValue) - : "memory"); - return old; -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd) -{ - T *old, *tmp; - asm volatile("1:\n" - "ldq_l %0,%2\n" /* old=*ptr; */ - "addq %0,%3,%1\n"/* tmp=old+value; */ - "stq_c %1,%2\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */ - "beq %1,2f\n" /* if (tmp == 0) goto 2; */ - "br 3f\n" /* goto 3; */ - "2: br 1b\n" /* goto 1; */ - "3:\n" - : "=&r" (old), "=&r" (tmp), "+m"(_q_value) - : "r" (valueToAdd) - : "memory"); - return reinterpret_cast<T *>(old); -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd) -{ - T *old, *tmp; - asm volatile("1:\n" - "ldq_l %0,%2\n" /* old=*ptr; */ - "addq %0,%3,%1\n"/* tmp=old+value; */ - "stq_c %1,%2\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */ - "beq %1,2f\n" /* if (tmp == 0) goto 2; */ - "br 3f\n" /* goto 3; */ - "2: br 1b\n" /* goto 1; */ - "3:\n" - "mb\n" - : "=&r" (old), "=&r" (tmp), "+m"(_q_value) - : "r" (valueToAdd) - : "memory"); - return reinterpret_cast<T *>(old); -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd) -{ - T *old, *tmp; - asm volatile("mb\n" - "1:\n" - "ldq_l %0,%2\n" /* old=*ptr; */ - "addq %0,%3,%1\n"/* tmp=old+value; */ - "stq_c %1,%2\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */ - "beq %1,2f\n" /* if (tmp == 0) goto 2; */ - "br 3f\n" /* goto 3; */ - "2: br 1b\n" /* goto 1; */ - "3:\n" - : "=&r" (old), "=&r" (tmp), "+m"(_q_value) - : "r" (valueToAdd) - : "memory"); - return reinterpret_cast<T *>(old); -} - -#else -# error "This compiler for Alpha is not supported" -#endif // Q_CC_GNU - -inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) -{ - return testAndSetAcquire(expectedValue, newValue); -} - -inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) -{ - return fetchAndStoreAcquire(newValue); -} - -inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) -{ - return fetchAndAddAcquire(valueToAdd); -} - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) -{ - return testAndSetAcquire(expectedValue, newValue); -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) -{ - return fetchAndStoreAcquire(newValue); -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) -{ - return fetchAndAddAcquire(valueToAdd); -} - -QT_END_NAMESPACE - -#endif // QATOMIC_ALPHA_H diff --git a/src/corelib/arch/qatomic_bfin.h b/src/corelib/arch/qatomic_bfin.h deleted file mode 100644 index 79519308a4..0000000000 --- a/src/corelib/arch/qatomic_bfin.h +++ /dev/null @@ -1,350 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QATOMIC_BFIN_H -#define QATOMIC_BFIN_H - -#include <QtCore/qoldbasicatomic.h> - -QT_BEGIN_NAMESPACE - -#if 0 -// silence syncqt warnings -QT_END_NAMESPACE -QT_END_HEADER - -#pragma qt_sync_skip_header_check -#pragma qt_sync_stop_processing -#endif - -#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_NOT_NATIVE - -inline bool QBasicAtomicInt::isFetchAndStoreNative() -{ return false; } -inline bool QBasicAtomicInt::isFetchAndStoreWaitFree() -{ return false; } - -#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_NOT_NATIVE - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative() -{ return false; } -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree() -{ return false; } - -#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; } - -#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) - -QT_BEGIN_INCLUDE_NAMESPACE -#include <asm/fixed_code.h> -QT_END_INCLUDE_NAMESPACE - -inline bool QBasicAtomicInt::ref() -{ - int ret; - asm volatile("R0 = 1;\n\t" - "P0 = %3;\n\t" - "CALL (%2);\n\t" - "%0 = R0;" - : "=da" (ret), "=m" (_q_value) - : "a" (ATOMIC_ADD32), "da" (&_q_value), "m" (_q_value) - : "R0", "R1", "P0", "RETS", "memory"); - return ret != 0; -} - -inline bool QBasicAtomicInt::deref() -{ - int ret; - asm volatile("R0 = 1;\n\t" - "P0 = %3;\n\t" - "CALL (%2);\n\t" - "%0 = R0;" - : "=da" (ret), "=m" (_q_value) - : "a" (ATOMIC_SUB32), "da" (&_q_value), "m" (_q_value) - : "R0", "R1", "P0", "RETS", "memory"); - return ret != 0; -} - -inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) -{ - long int readval; - asm volatile ("P0 = %2;\n\t" - "R1 = %3;\n\t" - "R2 = %4;\n\t" - "CALL (%5);\n\t" - "%0 = R0;\n\t" - : "=da" (readval), "=m" (_q_value) - : "da" (&_q_value), - "da" (expectedValue), - "da" (newValue), - "a" (ATOMIC_CAS32), - "m" (_q_value) - : "P0", "R0", "R1", "R2", "RETS", "memory", "cc"); - return readval == expectedValue; -} - -inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) -{ - asm volatile("R1 = %2;\n\t" - "P0 = %4;\n\t" - "CALL (%3);\n\t" - "%0 = R0;" - : "=da" (newValue), "=m" (_q_value) - : "da" (newValue), "a" (ATOMIC_XCHG32), "da" (&_q_value), "m" (_q_value) - : "R0", "R1", "P0", "RETS", "memory"); - return newValue; -} - -inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) -{ - int ret; - asm volatile("R0 = %[val];\n\t" - "P0 = %[qvalp];\n\t" - "CALL (%[addr]);\n\t" - "%[ret] = R1;" - : [ret] "=da" (ret), "=m" (_q_value) - : [addr] "a" (ATOMIC_ADD32), [qvalp] "da" (&_q_value), "m" (_q_value), [val] "da" (valueToAdd) - : "R0", "R1", "P0", "RETS", "memory"); - return ret; -} - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) -{ - T *readval; - asm volatile ("P0 = %2;\n\t" - "R1 = %3;\n\t" - "R2 = %4;\n\t" - "CALL (%5);\n\t" - "%0 = R0;\n\t" - : "=da" (readval), "=m" (_q_value) - : "da" (&_q_value), - "da" (expectedValue), - "da" (newValue), - "a" (ATOMIC_CAS32), - "m" (_q_value) - : "P0", "R0", "R1", "R2", "RETS", "memory", "cc"); - return readval == expectedValue; -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) -{ - asm volatile("R1 = %2;\n\t" - "P0 = %4;\n\t" - "CALL (%3);\n\t" - "%0 = R0;" - : "=da" (newValue), "=m" (_q_value) - : "da" (newValue), "a" (ATOMIC_XCHG32), "da" (&_q_value), "m" (_q_value) - : "R0", "R1", "P0", "RETS", "memory"); - return newValue; -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) -{ - T* ret; - asm volatile("R0 = %[val];\n\t" - "P0 = %[qvalp];\n\t" - "CALL (%[addr]);\n\t" - "%[ret] = R1;" - : [ret] "=da" (ret), "=m" (_q_value) - : [addr] "a" (ATOMIC_ADD32), [qvalp] "da" (&_q_value), "m" (_q_value), [val] "da" (valueToAdd * sizeof(T)) - : "R0", "R1", "P0", "RETS", "memory"); - return ret; -} - - -#endif // Q_OS_LINUX && Q_CC_GNU - -// Test and set for integers - -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 - -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::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>::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 - -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>::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 - -#endif // QATOMIC_BFIN_H diff --git a/src/corelib/arch/qatomic_integrity.h b/src/corelib/arch/qatomic_integrity.h deleted file mode 100644 index f8cfc8ce5b..0000000000 --- a/src/corelib/arch/qatomic_integrity.h +++ /dev/null @@ -1,295 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QATOMIC_INTEGRITY_H -#define QATOMIC_INTEGRITY_H - -#include <QtCore/qoldbasicatomic.h> -#include <INTEGRITY.h> - -QT_BEGIN_NAMESPACE - -#if 0 -// silence syncqt warnings -QT_END_NAMESPACE -QT_END_HEADER - -#pragma qt_sync_skip_header_check -#pragma qt_sync_stop_processing -#endif - -#define qt_i2addr(a) reinterpret_cast<Address *>(const_cast<int *>(a)) -#define qt_p2addr(a) reinterpret_cast<Address *>(const_cast<void *>(a)) -#define qt_addr(a) reinterpret_cast<Address>(a) - - -#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 true; } -inline bool QBasicAtomicInt::isTestAndSetWaitFree() -{ return true; } - -#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_NOT_NATIVE - -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 true; } -inline bool QBasicAtomicInt::isFetchAndAddWaitFree() -{ return true; } - -#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_NOT_NATIVE - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative() -{ return true; } -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree() -{ return true; } - -#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_NOT_NATIVE - -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 true; } -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree() -{ return true; } - -// Reference counting - -inline bool QBasicAtomicInt::ref() -{ - int oldval; - AtomicModify(qt_i2addr(&_q_value), qt_i2addr(&oldval), 0, 1); - return _q_value != -1; -} - -inline bool QBasicAtomicInt::deref() -{ - int oldval; - AtomicModify(qt_i2addr(&_q_value), qt_i2addr(&oldval), 0, -1U); - return _q_value != 0; -} - -// Test and set for integers - -inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) -{ - return TestAndSet(qt_i2addr(&_q_value), expectedValue, newValue) == Success; -} - -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 - -inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) -{ - int old_val; - do { - old_val = _q_value; - } while (TestAndSet(qt_i2addr(&_q_value), old_val, newValue) != Success); - return old_val; -} - -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) -{ - int old_val; - do { - old_val = _q_value; - } while (TestAndSet(qt_i2addr(&_q_value), old_val, old_val + valueToAdd) != Success); - return old_val; -} - -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) -{ - return TestAndSet((Address*)&_q_value, qt_addr(expectedValue), qt_addr(newValue)) == Success; -} - -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 - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) -{ - Address old_val; - do { - old_val = *reinterpret_cast<Address *>(const_cast<T *>(newValue)); - } while (TestAndSet(reinterpret_cast<Address *>(const_cast<T **>(&_q_value)), old_val, qt_addr(newValue)) != Success); - return reinterpret_cast<T *>(old_val); -} - -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) -{ - AtomicModify(qt_p2addr(&_q_value), qt_addr(_q_value), qt_addr(_q_value) + valueToAdd * sizeof(T)); - return _q_value; -} - -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 - -#endif // QATOMIC_INTEGRITY_H - diff --git a/src/corelib/arch/qatomic_power.h b/src/corelib/arch/qatomic_power.h deleted file mode 100644 index 3ddd303795..0000000000 --- a/src/corelib/arch/qatomic_power.h +++ /dev/null @@ -1,521 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QATOMIC_POWER_H -#define QATOMIC_POWER_H - -#include <QtCore/qoldbasicatomic.h> - -QT_BEGIN_NAMESPACE - -#if 0 -// silence syncqt warnings -QT_END_NAMESPACE -QT_END_HEADER - -#pragma qt_sync_skip_header_check -#pragma qt_sync_stop_processing -#endif - -#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE - -inline bool QBasicAtomicInt::isReferenceCountingNative() -{ return true; } -inline bool QBasicAtomicInt::isReferenceCountingWaitFree() -{ return false; } - -#define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE - -inline bool QBasicAtomicInt::isTestAndSetNative() -{ return true; } -inline bool QBasicAtomicInt::isTestAndSetWaitFree() -{ return false; } - -#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE - -inline bool QBasicAtomicInt::isFetchAndStoreNative() -{ return true; } -inline bool QBasicAtomicInt::isFetchAndStoreWaitFree() -{ return false; } - -#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE - -inline bool QBasicAtomicInt::isFetchAndAddNative() -{ return true; } -inline bool QBasicAtomicInt::isFetchAndAddWaitFree() -{ return false; } - -#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative() -{ return true; } -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree() -{ return false; } - -#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative() -{ return true; } -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree() -{ return false; } - -#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative() -{ return true; } -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree() -{ return false; } - -#if defined(Q_CC_GNU) - -#ifdef Q_PROCESSOR_POWER_32 -# define _Q_VALUE "0, %[_q_value]" -# define _Q_VALUE_MEMORY_OPERAND "+m" (_q_value) -# define _Q_VALUE_REGISTER_OPERAND [_q_value] "r" (&_q_value), -#else // Q_PROCESSOR_POWER_64 -# define _Q_VALUE "%y[_q_value]" -# define _Q_VALUE_MEMORY_OPERAND [_q_value] "+Z" (_q_value) -# define _Q_VALUE_REGISTER_OPERAND -#endif - -inline bool QBasicAtomicInt::ref() -{ - int originalValue; - int newValue; - asm volatile("lwarx %[originalValue]," _Q_VALUE "\n" - "addi %[newValue], %[originalValue], %[one]\n" - "stwcx. %[newValue]," _Q_VALUE "\n" - "bne- $-12\n" - : [originalValue] "=&b" (originalValue), - [newValue] "=&r" (newValue), - _Q_VALUE_MEMORY_OPERAND - : _Q_VALUE_REGISTER_OPERAND - [one] "i" (1) - : "cc", "memory"); - return newValue != 0; -} - -inline bool QBasicAtomicInt::deref() -{ - int originalValue; - int newValue; - asm volatile("lwarx %[originalValue]," _Q_VALUE "\n" - "addi %[newValue], %[originalValue], %[minusOne]\n" - "stwcx. %[newValue]," _Q_VALUE "\n" - "bne- $-12\n" - : [originalValue] "=&b" (originalValue), - [newValue] "=&r" (newValue), - _Q_VALUE_MEMORY_OPERAND - : _Q_VALUE_REGISTER_OPERAND - [minusOne] "i" (-1) - : "cc", "memory"); - return newValue != 0; -} - -inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) -{ - int result; - asm volatile("lwarx %[result]," _Q_VALUE "\n" - "xor. %[result], %[result], %[expectedValue]\n" - "bne $+12\n" - "stwcx. %[newValue]," _Q_VALUE "\n" - "bne- $-16\n" - : [result] "=&r" (result), - _Q_VALUE_MEMORY_OPERAND - : _Q_VALUE_REGISTER_OPERAND - [expectedValue] "r" (expectedValue), - [newValue] "r" (newValue) - : "cc", "memory"); - return result == 0; -} - -inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue) -{ - int result; - asm volatile("lwarx %[result]," _Q_VALUE "\n" - "xor. %[result], %[result], %[expectedValue]\n" - "bne $+16\n" - "stwcx. %[newValue]," _Q_VALUE "\n" - "bne- $-16\n" - "isync\n" - : [result] "=&r" (result), - _Q_VALUE_MEMORY_OPERAND - : _Q_VALUE_REGISTER_OPERAND - [expectedValue] "r" (expectedValue), - [newValue] "r" (newValue) - : "cc", "memory"); - return result == 0; -} - -inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue) -{ - int result; - asm volatile("eieio\n" - "lwarx %[result]," _Q_VALUE "\n" - "xor. %[result], %[result], %[expectedValue]\n" - "bne $+12\n" - "stwcx. %[newValue]," _Q_VALUE "\n" - "bne- $-16\n" - : [result] "=&r" (result), - _Q_VALUE_MEMORY_OPERAND - : _Q_VALUE_REGISTER_OPERAND - [expectedValue] "r" (expectedValue), - [newValue] "r" (newValue) - : "cc", "memory"); - return result == 0; -} - -inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue) -{ - int originalValue; - asm volatile("lwarx %[originalValue]," _Q_VALUE "\n" - "stwcx. %[newValue]," _Q_VALUE "\n" - "bne- $-8\n" - : [originalValue] "=&r" (originalValue), - _Q_VALUE_MEMORY_OPERAND - : _Q_VALUE_REGISTER_OPERAND - [newValue] "r" (newValue) - : "cc", "memory"); - return originalValue; -} - -inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue) -{ - int originalValue; - asm volatile("lwarx %[originalValue]," _Q_VALUE "\n" - "stwcx. %[newValue]," _Q_VALUE "\n" - "bne- $-8\n" - "isync\n" - : [originalValue] "=&r" (originalValue), - _Q_VALUE_MEMORY_OPERAND - : _Q_VALUE_REGISTER_OPERAND - [newValue] "r" (newValue) - : "cc", "memory"); - return originalValue; -} - -inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue) -{ - int originalValue; - asm volatile("eieio\n" - "lwarx %[originalValue]," _Q_VALUE "\n" - "stwcx. %[newValue]," _Q_VALUE "\n" - "bne- $-8\n" - : [originalValue] "=&r" (originalValue), - _Q_VALUE_MEMORY_OPERAND - : _Q_VALUE_REGISTER_OPERAND - [newValue] "r" (newValue) - : "cc", "memory"); - return originalValue; -} - -inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd) -{ - int originalValue; - int newValue; - asm volatile("lwarx %[originalValue]," _Q_VALUE "\n" - "add %[newValue], %[originalValue], %[valueToAdd]\n" - "stwcx. %[newValue]," _Q_VALUE "\n" - "bne- $-12\n" - : [originalValue] "=&r" (originalValue), - [newValue] "=&r" (newValue), - _Q_VALUE_MEMORY_OPERAND - : _Q_VALUE_REGISTER_OPERAND - [valueToAdd] "r" (valueToAdd) - : "cc", "memory"); - return originalValue; -} - -inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd) -{ - int originalValue; - int newValue; - asm volatile("lwarx %[originalValue]," _Q_VALUE "\n" - "add %[newValue], %[originalValue], %[valueToAdd]\n" - "stwcx. %[newValue]," _Q_VALUE "\n" - "bne- $-12\n" - "isync\n" - : [originalValue] "=&r" (originalValue), - [newValue] "=&r" (newValue), - _Q_VALUE_MEMORY_OPERAND - : _Q_VALUE_REGISTER_OPERAND - [valueToAdd] "r" (valueToAdd) - : "cc", "memory"); - return originalValue; -} - -inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd) -{ - int originalValue; - int newValue; - asm volatile("eieio\n" - "lwarx %[originalValue]," _Q_VALUE "\n" - "add %[newValue], %[originalValue], %[valueToAdd]\n" - "stwcx. %[newValue]," _Q_VALUE "\n" - "bne- $-12\n" - : [originalValue] "=&r" (originalValue), - [newValue] "=&r" (newValue), - _Q_VALUE_MEMORY_OPERAND - : _Q_VALUE_REGISTER_OPERAND - [valueToAdd] "r" (valueToAdd) - : "cc", "memory"); - return originalValue; -} - -#ifdef Q_PROCESSOR_POWER_64 -# define LPARX "ldarx" -# define STPCX "stdcx." -#else -# define LPARX "lwarx" -# define STPCX "stwcx." -#endif - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue) -{ - void *result; - asm volatile(LPARX" %[result]," _Q_VALUE "\n" - "xor. %[result], %[result], %[expectedValue]\n" - "bne $+12\n" - STPCX" %[newValue]," _Q_VALUE "\n" - "bne- $-16\n" - : [result] "=&r" (result), - _Q_VALUE_MEMORY_OPERAND - : _Q_VALUE_REGISTER_OPERAND - [expectedValue] "r" (expectedValue), - [newValue] "r" (newValue) - : "cc", "memory"); - return result == 0; -} - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue) -{ - void *result; - asm volatile(LPARX" %[result]," _Q_VALUE "\n" - "xor. %[result], %[result], %[expectedValue]\n" - "bne $+16\n" - STPCX" %[newValue]," _Q_VALUE "\n" - "bne- $-16\n" - "isync\n" - : [result] "=&r" (result), - _Q_VALUE_MEMORY_OPERAND - : _Q_VALUE_REGISTER_OPERAND - [expectedValue] "r" (expectedValue), - [newValue] "r" (newValue) - : "cc", "memory"); - return result == 0; -} - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue) -{ - void *result; - asm volatile("eieio\n" - LPARX" %[result]," _Q_VALUE "\n" - "xor. %[result], %[result], %[expectedValue]\n" - "bne $+12\n" - STPCX" %[newValue]," _Q_VALUE "\n" - "bne- $-16\n" - : [result] "=&r" (result), - _Q_VALUE_MEMORY_OPERAND - : _Q_VALUE_REGISTER_OPERAND - [expectedValue] "r" (expectedValue), - [newValue] "r" (newValue) - : "cc", "memory"); - return result == 0; -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue) -{ - T *originalValue; - asm volatile(LPARX" %[originalValue]," _Q_VALUE "\n" - STPCX" %[newValue]," _Q_VALUE "\n" - "bne- $-8\n" - : [originalValue] "=&r" (originalValue), - _Q_VALUE_MEMORY_OPERAND - : _Q_VALUE_REGISTER_OPERAND - [newValue] "r" (newValue) - : "cc", "memory"); - return originalValue; -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue) -{ - T *originalValue; - asm volatile(LPARX" %[originalValue]," _Q_VALUE "\n" - STPCX" %[newValue]," _Q_VALUE "\n" - "bne- $-8\n" - "isync\n" - : [originalValue] "=&r" (originalValue), - _Q_VALUE_MEMORY_OPERAND - : _Q_VALUE_REGISTER_OPERAND - [newValue] "r" (newValue) - : "cc", "memory"); - return originalValue; -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue) -{ - T *originalValue; - asm volatile("eieio\n" - LPARX" %[originalValue]," _Q_VALUE "\n" - STPCX" %[newValue]," _Q_VALUE "\n" - "bne- $-8\n" - : [originalValue] "=&r" (originalValue), - _Q_VALUE_MEMORY_OPERAND - : _Q_VALUE_REGISTER_OPERAND - [newValue] "r" (newValue) - : "cc", "memory"); - return originalValue; -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd) -{ - T *originalValue; - T *newValue; - asm volatile(LPARX" %[originalValue]," _Q_VALUE "\n" - "add %[newValue], %[originalValue], %[valueToAdd]\n" - STPCX" %[newValue]," _Q_VALUE "\n" - "bne- $-12\n" - : [originalValue] "=&r" (originalValue), - [newValue] "=&r" (newValue), - _Q_VALUE_MEMORY_OPERAND - : _Q_VALUE_REGISTER_OPERAND - [valueToAdd] "r" (valueToAdd * sizeof(T)) - : "cc", "memory"); - return originalValue; -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd) -{ - T *originalValue; - T *newValue; - asm volatile(LPARX" %[originalValue]," _Q_VALUE "\n" - "add %[newValue], %[originalValue], %[valueToAdd]\n" - STPCX" %[newValue]," _Q_VALUE "\n" - "bne- $-12\n" - "isync\n" - : [originalValue] "=&r" (originalValue), - [newValue] "=&r" (newValue), - _Q_VALUE_MEMORY_OPERAND - : _Q_VALUE_REGISTER_OPERAND - [valueToAdd] "r" (valueToAdd * sizeof(T)) - : "cc", "memory"); - return originalValue; -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd) -{ - T *originalValue; - T *newValue; - asm volatile("eieio\n" - LPARX" %[originalValue]," _Q_VALUE "\n" - "add %[newValue], %[originalValue], %[valueToAdd]\n" - STPCX" %[newValue]," _Q_VALUE "\n" - "bne- $-12\n" - : [originalValue] "=&r" (originalValue), - [newValue] "=&r" (newValue), - _Q_VALUE_MEMORY_OPERAND - : _Q_VALUE_REGISTER_OPERAND - [valueToAdd] "r" (valueToAdd * sizeof(T)) - : "cc", "memory"); - return originalValue; -} - -#undef LPARX -#undef STPCX -#undef _Q_VALUE -#undef _Q_VALUE_MEMORY_OPERAND -#undef _Q_VALUE_REGISTER_OPERAND - -#else -# error "This compiler for Power/PowerPC is not supported" -#endif - -inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) -{ - return testAndSetAcquire(expectedValue, newValue); -} - -inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) -{ - return fetchAndStoreAcquire(newValue); -} - -inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) -{ - return fetchAndAddAcquire(valueToAdd); -} - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) -{ - return testAndSetAcquire(expectedValue, newValue); -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) -{ - return fetchAndStoreAcquire(newValue); -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) -{ - return fetchAndAddAcquire(valueToAdd); -} - -QT_END_NAMESPACE - -#endif // QATOMIC_POWER_H diff --git a/src/corelib/arch/qatomic_s390.h b/src/corelib/arch/qatomic_s390.h deleted file mode 100644 index 0469f44e5f..0000000000 --- a/src/corelib/arch/qatomic_s390.h +++ /dev/null @@ -1,433 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QATOMIC_S390_H -#define QATOMIC_S390_H - -#include <QtCore/qoldbasicatomic.h> - -QT_BEGIN_NAMESPACE - -#if 0 -// silence syncqt warnings -QT_END_NAMESPACE -QT_END_HEADER - -#pragma qt_sync_skip_header_check -#pragma qt_sync_stop_processing -#endif - -#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE - -inline bool QBasicAtomicInt::isReferenceCountingNative() -{ return true; } -inline bool QBasicAtomicInt::isReferenceCountingWaitFree() -{ return false; } - -#define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE - -inline bool QBasicAtomicInt::isTestAndSetNative() -{ return true; } -inline bool QBasicAtomicInt::isTestAndSetWaitFree() -{ return false; } - -#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE - -inline bool QBasicAtomicInt::isFetchAndStoreNative() -{ return true; } -inline bool QBasicAtomicInt::isFetchAndStoreWaitFree() -{ return false; } - -#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE - -inline bool QBasicAtomicInt::isFetchAndAddNative() -{ return true; } -inline bool QBasicAtomicInt::isFetchAndAddWaitFree() -{ return false; } - -#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative() -{ return true; } -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree() -{ return false; } - -#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative() -{ return true; } -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree() -{ return false; } - -#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative() -{ return true; } -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree() -{ return false; } - -#ifdef __GNUC__ -#define __GNU_EXTENSION __extension__ -#else -#define __GNU_EXTENSION -#endif - -#define __CS_LOOP(ptr, op_val, op_string, pre, post) __GNU_EXTENSION ({ \ - volatile int old_val, new_val; \ - __asm__ __volatile__(pre \ - " l %0,0(%3)\n" \ - "0: lr %1,%0\n" \ - op_string " %1,%4\n" \ - " cs %0,%1,0(%3)\n" \ - " jl 0b\n" \ - post \ - : "=&d" (old_val), "=&d" (new_val), \ - "=m" (*ptr) \ - : "a" (ptr), "d" (op_val), \ - "m" (*ptr) \ - : "cc", "memory" ); \ - new_val; \ -}) - -#define __CS_OLD_LOOP(ptr, op_val, op_string, pre, post ) __GNU_EXTENSION ({ \ - volatile int old_val, new_val; \ - __asm__ __volatile__(pre \ - " l %0,0(%3)\n" \ - "0: lr %1,%0\n" \ - op_string " %1,%4\n" \ - " cs %0,%1,0(%3)\n" \ - " jl 0b\n" \ - post \ - : "=&d" (old_val), "=&d" (new_val), \ - "=m" (*ptr) \ - : "a" (ptr), "d" (op_val), \ - "m" (*ptr) \ - : "cc", "memory" ); \ - old_val; \ -}) - -#ifdef __s390x__ -#define __CSG_OLD_LOOP(ptr, op_val, op_string, pre, post) __GNU_EXTENSION ({ \ - long old_val, new_val; \ - __asm__ __volatile__(pre \ - " lg %0,0(%3)\n" \ - "0: lgr %1,%0\n" \ - op_string " %1,%4\n" \ - " csg %0,%1,0(%3)\n" \ - " jl 0b\n" \ - post \ - : "=&d" (old_val), "=&d" (new_val), \ - "=m" (*ptr) \ - : "a" (ptr), "d" (op_val), \ - "m" (*ptr) \ - : "cc", "memory" ); \ - old_val; \ -}) -#endif - -inline bool QBasicAtomicInt::ref() -{ - return __CS_LOOP(&_q_value, 1, "ar", "", "") != 0; -} - -inline bool QBasicAtomicInt::deref() -{ - return __CS_LOOP(&_q_value, 1, "sr", "", "") != 0; -} - -inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) -{ - int retval; - __asm__ __volatile__( - " lr %0,%3\n" - " cs %0,%4,0(%2)\n" - " ipm %0\n" - " srl %0,28\n" - "0:" - : "=&d" (retval), "=m" (_q_value) - : "a" (&_q_value), "d" (expectedValue) , "d" (newValue), - "m" (_q_value) : "cc", "memory" ); - return retval == 0; -} - -inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue) -{ - int retval; - __asm__ __volatile__( - " lr %0,%3\n" - " cs %0,%4,0(%2)\n" - " ipm %0\n" - " srl %0,28\n" - "0:\n" - " bcr 15,0\n" - : "=&d" (retval), "=m" (_q_value) - : "a" (&_q_value), "d" (expectedValue) , "d" (newValue), - "m" (_q_value) : "cc", "memory" ); - return retval == 0; -} - -inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue) -{ - int retval; - __asm__ __volatile__( - " bcr 15,0\n" - " lr %0,%3\n" - " cs %0,%4,0(%2)\n" - " ipm %0\n" - " srl %0,28\n" - "0:" - : "=&d" (retval), "=m" (_q_value) - : "a" (&_q_value), "d" (expectedValue) , "d" (newValue), - "m" (_q_value) : "cc", "memory" ); - return retval == 0; -} - -inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) -{ - return testAndSetAcquire(expectedValue, newValue); -} - -inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue) -{ - return __CS_OLD_LOOP(&_q_value, newValue, "lr", "", ""); -} - -inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue) -{ - return __CS_OLD_LOOP(&_q_value, newValue, "lr", "", "bcr 15,0\n"); -} - -inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue) -{ - return __CS_OLD_LOOP(&_q_value, newValue, "lr", "bcr 15,0\n", ""); -} - -inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) -{ - return fetchAndStoreAcquire(newValue); -} - -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); -} - -inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) -{ - return __CS_OLD_LOOP(&_q_value, valueToAdd, "ar", "", "bcr 15,0\n"); -} - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue) -{ - int retval; - -#ifndef __s390x__ - __asm__ __volatile__( - " lr %0,%3\n" - " cs %0,%4,0(%2)\n" - " ipm %0\n" - " srl %0,28\n" - "0:" - : "=&d" (retval), "=m" (_q_value) - : "a" (&_q_value), "d" (expectedValue) , "d" (newValue), - "m" (_q_value) : "cc", "memory" ); -#else - __asm__ __volatile__( - " lgr %0,%3\n" - " csg %0,%4,0(%2)\n" - " ipm %0\n" - " srl %0,28\n" - "0:" - : "=&d" (retval), "=m" (_q_value) - : "a" (&_q_value), "d" (expectedValue) , "d" (newValue), - "m" (_q_value) : "cc", "memory" ); -#endif - - return retval == 0; -} - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue) -{ - int retval; - -#ifndef __s390x__ - __asm__ __volatile__( - " lr %0,%3\n" - " cs %0,%4,0(%2)\n" - " ipm %0\n" - " srl %0,28\n" - "0:\n" - " bcr 15,0\n" - : "=&d" (retval), "=m" (_q_value) - : "a" (&_q_value), "d" (expectedValue) , "d" (newValue), - "m" (_q_value) : "cc", "memory" ); -#else - __asm__ __volatile__( - " lgr %0,%3\n" - " csg %0,%4,0(%2)\n" - " ipm %0\n" - " srl %0,28\n" - "0:\n" - " bcr 15,0\n" - : "=&d" (retval), "=m" (_q_value) - : "a" (&_q_value), "d" (expectedValue) , "d" (newValue), - "m" (_q_value) : "cc", "memory" ); -#endif - - return retval == 0; -} - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue) -{ - int retval; - -#ifndef __s390x__ - __asm__ __volatile__( - " bcr 15,0\n" - " lr %0,%3\n" - " cs %0,%4,0(%2)\n" - " ipm %0\n" - " srl %0,28\n" - "0:" - : "=&d" (retval), "=m" (_q_value) - : "a" (&_q_value), "d" (expectedValue) , "d" (newValue), - "m" (_q_value) : "cc", "memory" ); -#else - __asm__ __volatile__( - " bcr 15,0\n" - " lgr %0,%3\n" - " csg %0,%4,0(%2)\n" - " ipm %0\n" - " srl %0,28\n" - "0:" - : "=&d" (retval), "=m" (_q_value) - : "a" (&_q_value), "d" (expectedValue) , "d" (newValue), - "m" (_q_value) : "cc", "memory" ); -#endif - - return retval == 0; -} - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) -{ - return testAndSetAcquire(expectedValue, newValue); -} - -template <typename T> -Q_INLINE_TEMPLATE T* QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue) -{ -#ifndef __s390x__ - return (T*)__CS_OLD_LOOP(&_q_value, (int)newValue, "lr", "", ""); -#else - return (T*)__CSG_OLD_LOOP(&_q_value, (long)newValue, "lgr", "", ""); -#endif -} - -template <typename T> -Q_INLINE_TEMPLATE T* QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue) -{ -#ifndef __s390x__ - return (T*)__CS_OLD_LOOP(&_q_value, (int)newValue, "lr", "", "bcr 15,0 \n"); -#else - return (T*)__CSG_OLD_LOOP(&_q_value, (long)newValue, "lgr", "", "bcr 15,0 \n"); -#endif -} - -template <typename T> -Q_INLINE_TEMPLATE T* QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue) -{ -#ifndef __s390x__ - return (T*)__CS_OLD_LOOP(&_q_value, (int)newValue, "lr", "bcr 15,0 \n", ""); -#else - return (T*)__CSG_OLD_LOOP(&_q_value, (long)newValue, "lgr", "bcr 15,0\n", ""); -#endif -} - -template <typename T> -Q_INLINE_TEMPLATE T* QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) -{ - return fetchAndStoreAcquire(newValue); -} - - -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); -} - -#undef __GNU_EXTENSION - -QT_END_NAMESPACE - -#endif // QATOMIC_S390_H diff --git a/src/corelib/arch/qatomic_sh4a.h b/src/corelib/arch/qatomic_sh4a.h deleted file mode 100644 index 6e59279f3e..0000000000 --- a/src/corelib/arch/qatomic_sh4a.h +++ /dev/null @@ -1,540 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QATOMIC_SH4A_H -#define QATOMIC_SH4A_H - -#include <QtCore/qoldbasicatomic.h> - -QT_BEGIN_NAMESPACE - - -QT_END_NAMESPACE - -#if 0 -#pragma qt_sync_skip_header_check -#pragma qt_sync_stop_processing -#endif - -#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE - -inline bool QBasicAtomicInt::isReferenceCountingNative() -{ return true; } -inline bool QBasicAtomicInt::isReferenceCountingWaitFree() -{ return false; } - -#define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE - -inline bool QBasicAtomicInt::isTestAndSetNative() -{ return true; } -inline bool QBasicAtomicInt::isTestAndSetWaitFree() -{ return false; } - -#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE - -inline bool QBasicAtomicInt::isFetchAndStoreNative() -{ return true; } -inline bool QBasicAtomicInt::isFetchAndStoreWaitFree() -{ return false; } - -#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE - -inline bool QBasicAtomicInt::isFetchAndAddNative() -{ return true; } -inline bool QBasicAtomicInt::isFetchAndAddWaitFree() -{ return false; } - -#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative() -{ return true; } -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree() -{ return false; } - -#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative() -{ return true; } -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree() -{ return false; } - -#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative() -{ return true; } -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree() -{ return false; } - -QT_BEGIN_NAMESPACE - -#if !defined(Q_CC_GNU) -# error "SH-4A support has not been added for this compiler" -#else - -inline bool QBasicAtomicInt::ref() -{ - register int newValue asm("r0"); - asm volatile("0:\n" - "movli.l @%[_q_value], %[newValue]\n" - "add #1,%[newValue]\n" - "movco.l %[newValue], @%[_q_value]\n" - "bf 0b\n" - : [newValue] "=&r" (newValue), - "+m" (_q_value) - : [_q_value] "r" (&_q_value) - : "cc", "memory"); - return newValue != 0; -} - -inline bool QBasicAtomicInt::deref() -{ - register int newValue asm("r0"); - asm volatile("0:\n" - "movli.l @%[_q_value], %[newValue]\n" - "add #-1,%[newValue]\n" - "movco.l %[newValue], @%[_q_value]\n" - "bf 0b\n" - : [newValue] "=&r" (newValue), - "+m" (_q_value) - : [_q_value] "r" (&_q_value) - : "cc", "memory"); - return newValue != 0; -} - -inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) -{ - int result; - asm volatile("0:\n" - "movli.l @%[_q_value], r0\n" - "xor %[expectedValue], r0\n" - "cmp/eq #0, r0\n" - "bf/s 0f\n" - "mov r0, %[result]\n" - "mov %[newValue], r0\n" - "movco.l r0, @%[_q_value]\n" - "bf 0b\n" - "0:\n" - : [result] "=&r" (result), - "+m" (_q_value) - : [_q_value] "r" (&_q_value), - [expectedValue] "r" (expectedValue), - [newValue] "r" (newValue) - : "r0", "cc", "memory"); - return result == 0; -} - -inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue) -{ - int result; - asm volatile("0:\n" - "movli.l @%[_q_value], r0\n" - "xor %[expectedValue], r0\n" - "cmp/eq #0, r0\n" - "bf/s 0f\n" - "mov r0, %[result]\n" - "mov %[newValue], r0\n" - "movco.l r0, @%[_q_value]\n" - "bf 0b\n" - "synco\n" - "0:\n" - : [result] "=&r" (result), - "+m" (_q_value) - : [_q_value] "r" (&_q_value), - [expectedValue] "r" (expectedValue), - [newValue] "r" (newValue) - : "r0", "cc", "memory"); - return result == 0; -} - -inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue) -{ - int result; - asm volatile("synco\n" - "0:\n" - "movli.l @%[_q_value], r0\n" - "xor %[expectedValue], r0\n" - "cmp/eq #0, r0\n" - "bf/s 0f\n" - "mov r0, %[result]\n" - "mov %[newValue], r0\n" - "movco.l r0, @%[_q_value]\n" - "bf 0b\n" - "0:\n" - : [result] "=&r" (result), - "+m" (_q_value) - : [_q_value] "r" (&_q_value), - [expectedValue] "r" (expectedValue), - [newValue] "r" (newValue) - : "r0", "cc", "memory"); - return result == 0; -} - -inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) -{ - return testAndSetAcquire(expectedValue, newValue); -} - -inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue) -{ - int originalValue; - asm volatile("0:\n" - "movli.l @%[_q_value], r0\n" - "mov r0, %[originalValue]\n" - "mov %[newValue], r0\n" - "movco.l r0, @%[_q_value]\n" - "bf 0b\n" - : [originalValue] "=&r" (originalValue), - "+m" (_q_value) - : [_q_value] "r" (&_q_value), - [newValue] "r" (newValue) - : "r0", "cc", "memory"); - return originalValue; -} - -inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue) -{ - int originalValue; - asm volatile("0:\n" - "movli.l @%[_q_value], r0\n" - "mov r0, %[originalValue]\n" - "mov %[newValue], r0\n" - "movco.l r0, @%[_q_value]\n" - "bf 0b\n" - "synco\n" - : [originalValue] "=&r" (originalValue), - "+m" (_q_value) - : [_q_value] "r" (&_q_value), - [newValue] "r" (newValue) - : "r0", "cc", "memory"); - return originalValue; -} - -inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue) -{ - int originalValue; - asm volatile("synco\n" - "0:\n" - "movli.l @%[_q_value], r0\n" - "mov r0, %[originalValue]\n" - "mov %[newValue], r0\n" - "movco.l r0, @%[_q_value]\n" - "bf 0b\n" - : [originalValue] "=&r" (originalValue), - "+m" (_q_value) - : [_q_value] "r" (&_q_value), - [newValue] "r" (newValue) - : "r0", "cc", "memory"); - return originalValue; -} - -inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) -{ - return fetchAndStoreAcquire(newValue); -} - -inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd) -{ - int originalValue; - asm volatile("0:\n" - "movli.l @%[_q_value], r0\n" - "mov r0, %[originalValue]\n" - "add %[valueToAdd], r0\n" - "movco.l r0, @%[_q_value]\n" - "bf 0b\n" - : [originalValue] "=&r" (originalValue), - "+m" (_q_value) - : [_q_value] "r" (&_q_value), - [valueToAdd] "r" (valueToAdd) - : "r0", "cc", "memory"); - return originalValue; -} - -inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd) -{ - int originalValue; - asm volatile("0:\n" - "movli.l @%[_q_value], r0\n" - "mov r0, %[originalValue]\n" - "add %[valueToAdd], r0\n" - "movco.l r0, @%[_q_value]\n" - "bf 0b\n" - "synco\n" - : [originalValue] "=&r" (originalValue), - "+m" (_q_value) - : [_q_value] "r" (&_q_value), - [valueToAdd] "r" (valueToAdd) - : "r0", "cc", "memory"); - return originalValue; -} - -inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd) -{ - int originalValue; - asm volatile("synco\n" - "0:\n" - "movli.l @%[_q_value], r0\n" - "mov r0, %[originalValue]\n" - "add %[valueToAdd], r0\n" - "movco.l r0, @%[_q_value]\n" - "bf 0b\n" - : [originalValue] "=&r" (originalValue), - "+m" (_q_value) - : [_q_value] "r" (&_q_value), - [valueToAdd] "r" (valueToAdd) - : "r0", "cc", "memory"); - return originalValue; -} - -inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) -{ - return fetchAndAddAcquire(valueToAdd); -} - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue) -{ - T *result; - asm volatile("0:\n" - "movli.l @%[_q_value], r0\n" - "xor %[expectedValue], r0\n" - "cmp/eq #0, r0\n" - "bf/s 0f\n" - "mov r0, %[result]\n" - "mov %[newValue], r0\n" - "movco.l r0, @%[_q_value]\n" - "bf 0b\n" - "0:\n" - : [result] "=&r" (result), - "+m" (_q_value) - : [_q_value] "r" (&_q_value), - [expectedValue] "r" (expectedValue), - [newValue] "r" (newValue) - : "r0", "cc", "memory"); - return result == 0; -} - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue) -{ - T *result; - asm volatile("0:\n" - "movli.l @%[_q_value], r0\n" - "xor %[expectedValue], r0\n" - "cmp/eq #0, r0\n" - "bf/s 0f\n" - "mov r0, %[result]\n" - "mov %[newValue], r0\n" - "movco.l r0, @%[_q_value]\n" - "bf 0b\n" - "synco\n" - "0:\n" - : [result] "=&r" (result), - "+m" (_q_value) - : [_q_value] "r" (&_q_value), - [expectedValue] "r" (expectedValue), - [newValue] "r" (newValue) - : "r0", "cc", "memory"); - return result == 0; -} - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue) -{ - T *result; - asm volatile("synco\n" - "0:\n" - "movli.l @%[_q_value], r0\n" - "xor %[expectedValue], r0\n" - "cmp/eq #0, r0\n" - "bf/s 0f\n" - "mov r0, %[result]\n" - "mov %[newValue], r0\n" - "movco.l r0, @%[_q_value]\n" - "bf 0b\n" - "0:\n" - : [result] "=&r" (result), - "+m" (_q_value) - : [_q_value] "r" (&_q_value), - [expectedValue] "r" (expectedValue), - [newValue] "r" (newValue) - : "r0", "cc", "memory"); - return result == 0; -} - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) -{ - return testAndSetAcquire(expectedValue, newValue); -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue) -{ - T *originalValue; - asm volatile("0:\n" - "movli.l @%[_q_value], r0\n" - "mov r0, %[originalValue]\n" - "mov %[newValue], r0\n" - "movco.l r0, @%[_q_value]\n" - "bf 0b\n" - : [originalValue] "=&r" (originalValue), - "+m" (_q_value) - : [_q_value] "r" (&_q_value), - [newValue] "r" (newValue) - : "r0", "cc", "memory"); - return originalValue; -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue) -{ - T *originalValue; - asm volatile("0:\n" - "movli.l @%[_q_value], r0\n" - "mov r0, %[originalValue]\n" - "mov %[newValue], r0\n" - "movco.l r0, @%[_q_value]\n" - "bf 0b\n" - "synco\n" - : [originalValue] "=&r" (originalValue), - "+m" (_q_value) - : [_q_value] "r" (&_q_value), - [newValue] "r" (newValue) - : "r0", "cc", "memory"); - return originalValue; -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue) -{ - T *originalValue; - asm volatile("synco\n" - "0:\n" - "movli.l @%[_q_value], r0\n" - "mov r0, %[originalValue]\n" - "mov %[newValue], r0\n" - "movco.l r0, @%[_q_value]\n" - "bf 0b\n" - : [originalValue] "=&r" (originalValue), - "+m" (_q_value) - : [_q_value] "r" (&_q_value), - [newValue] "r" (newValue) - : "r0", "cc", "memory"); - return originalValue; -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) -{ - return fetchAndStoreAcquire(newValue); -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd) -{ - T *originalValue; - asm volatile("0:\n" - "movli.l @%[_q_value], r0\n" - "mov r0, %[originalValue]\n" - "add %[valueToAdd], r0\n" - "movco.l r0, @%[_q_value]\n" - "bf 0b\n" - : [originalValue] "=&r" (originalValue), - "+m" (_q_value) - : [_q_value] "r" (&_q_value), - [valueToAdd] "r" (valueToAdd * sizeof(T)) - : "r0", "cc", "memory"); - return originalValue; -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd) -{ - T *originalValue; - asm volatile("0:\n" - "movli.l @%[_q_value], r0\n" - "mov r0, %[originalValue]\n" - "add %[valueToAdd], r0\n" - "movco.l r0, @%[_q_value]\n" - "bf 0b\n" - "synco\n" - : [originalValue] "=&r" (originalValue), - "+m" (_q_value) - : [_q_value] "r" (&_q_value), - [valueToAdd] "r" (valueToAdd * sizeof(T)) - : "r0", "cc", "memory"); - return originalValue; -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd) -{ - T *originalValue; - asm volatile("synco\n" - "0:\n" - "movli.l @%[_q_value], r0\n" - "mov r0, %[originalValue]\n" - "add %[valueToAdd], r0\n" - "movco.l r0, @%[_q_value]\n" - "bf 0b\n" - : [originalValue] "=&r" (originalValue), - "+m" (_q_value) - : [_q_value] "r" (&_q_value), - [valueToAdd] "r" (valueToAdd * sizeof(T)) - : "r0", "cc", "memory"); - return originalValue; -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) -{ - return fetchAndAddAcquire(valueToAdd); -} - -#endif // Q_CC_GNU - -#endif // QATOMIC_SH4A_H diff --git a/src/corelib/arch/qatomic_sparc.h b/src/corelib/arch/qatomic_sparc.h deleted file mode 100644 index 8aea33ce85..0000000000 --- a/src/corelib/arch/qatomic_sparc.h +++ /dev/null @@ -1,532 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QATOMIC_SPARC_H -#define QATOMIC_SPARC_H - -#include <QtCore/qoldbasicatomic.h> - -QT_BEGIN_NAMESPACE - -#if 0 -// silence syncqt warnings -QT_END_NAMESPACE -QT_END_HEADER - -#pragma qt_sync_skip_header_check -#pragma qt_sync_stop_processing -#endif - -#if defined(_LP64) - -#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE - -inline bool QBasicAtomicInt::isReferenceCountingNative() -{ return true; } -inline bool QBasicAtomicInt::isReferenceCountingWaitFree() -{ return false; } - -#define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT_TEST_AND_SET_IS_WAIT_FREE - -inline bool QBasicAtomicInt::isTestAndSetNative() -{ return true; } -inline bool QBasicAtomicInt::isTestAndSetWaitFree() -{ return true; } - -#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_ALWAYS_NATIVE - -inline bool QBasicAtomicInt::isFetchAndAddNative() -{ return true; } -inline bool QBasicAtomicInt::isFetchAndAddWaitFree() -{ return false; } - -#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE -#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_WAIT_FREE - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative() -{ return true; } -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree() -{ return true; } - -#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_ALWAYS_NATIVE - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative() -{ return true; } -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree() -{ return false; } - -extern "C" { - Q_CORE_EXPORT int q_atomic_increment(volatile int *ptr); - Q_CORE_EXPORT int q_atomic_decrement(volatile int *ptr); - - Q_CORE_EXPORT int q_atomic_test_and_set_int(volatile int *ptr, int expected, int newval); - Q_CORE_EXPORT int q_atomic_test_and_set_acquire_int(volatile int *ptr, - int expected, - int newval); - Q_CORE_EXPORT int q_atomic_test_and_set_release_int(volatile int *ptr, - int expected, - int newval); - - Q_CORE_EXPORT int q_atomic_set_int(volatile int *ptr, int newval); - Q_CORE_EXPORT int q_atomic_fetch_and_store_acquire_int(volatile int *ptr, int newval); - Q_CORE_EXPORT int q_atomic_fetch_and_store_release_int(volatile int *ptr, int newval); - - Q_CORE_EXPORT int q_atomic_fetch_and_add_int(volatile int *ptr, int value); - Q_CORE_EXPORT int q_atomic_fetch_and_add_acquire_int(volatile int *ptr, int value); - Q_CORE_EXPORT int q_atomic_fetch_and_add_release_int(volatile int *ptr, int value); - - Q_CORE_EXPORT int q_atomic_test_and_set_ptr(volatile void *ptr, const void *expected, const void *newval); - Q_CORE_EXPORT int q_atomic_test_and_set_acquire_ptr(volatile void *ptr, - const void *expected, - const void *newval); - Q_CORE_EXPORT int q_atomic_test_and_set_release_ptr(volatile void *ptr, - const void *expected, - const void *newval); - - Q_CORE_EXPORT void *q_atomic_set_ptr(volatile void *ptr, const void *newval); - Q_CORE_EXPORT void *q_atomic_fetch_and_store_acquire_ptr(volatile void *ptr, const void *newval); - Q_CORE_EXPORT void *q_atomic_fetch_and_store_release_ptr(volatile void *ptr, const void *newval); - - Q_CORE_EXPORT void *q_atomic_fetch_and_add_ptr(volatile void *ptr, int value); - Q_CORE_EXPORT void *q_atomic_fetch_and_add_acquire_ptr(volatile void *ptr, int value); - Q_CORE_EXPORT void *q_atomic_fetch_and_add_release_ptr(volatile void *ptr, int value); -} - -inline bool QBasicAtomicInt::ref() -{ - return fetchAndAddRelaxed(1) != -1; -} - -inline bool QBasicAtomicInt::deref() -{ - return fetchAndAddRelaxed(-1) != 1; -} - -inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) -{ - return q_atomic_test_and_set_int(&_q_value, expectedValue, newValue) != 0; -} - -inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue) -{ - return q_atomic_test_and_set_acquire_int(&_q_value, expectedValue, newValue) != 0; -} - -inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue) -{ - return q_atomic_test_and_set_release_int(&_q_value, expectedValue, newValue) != 0; -} - -inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) -{ - return q_atomic_test_and_set_acquire_int(&_q_value, expectedValue, newValue) != 0; -} - -inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue) -{ - return q_atomic_set_int(&_q_value, newValue); -} - -inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue) -{ - return q_atomic_fetch_and_store_acquire_int(&_q_value, newValue); -} - -inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue) -{ - return q_atomic_fetch_and_store_release_int(&_q_value, newValue); -} - -inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) -{ - return q_atomic_fetch_and_store_acquire_int(&_q_value, newValue); -} - -inline int QBasicAtomicInt::fetchAndAddRelaxed(int newValue) -{ - return q_atomic_fetch_and_add_int(&_q_value, newValue); -} - -inline int QBasicAtomicInt::fetchAndAddAcquire(int newValue) -{ - return q_atomic_fetch_and_add_acquire_int(&_q_value, newValue); -} - -inline int QBasicAtomicInt::fetchAndAddRelease(int newValue) -{ - return q_atomic_fetch_and_add_release_int(&_q_value, newValue); -} - -inline int QBasicAtomicInt::fetchAndAddOrdered(int newValue) -{ - return q_atomic_fetch_and_add_acquire_int(&_q_value, newValue); -} - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue) -{ - return q_atomic_test_and_set_ptr(&_q_value, expectedValue, newValue) != 0; -} - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue) -{ - return q_atomic_test_and_set_acquire_ptr(&_q_value, expectedValue, newValue) != 0; -} - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue) -{ - return q_atomic_test_and_set_release_ptr(&_q_value, expectedValue, newValue) != 0; -} - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) -{ - return q_atomic_test_and_set_acquire_ptr(&_q_value, expectedValue, newValue) != 0; -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue) -{ - return reinterpret_cast<T *>(q_atomic_set_ptr(&_q_value, newValue)); -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue) -{ - return reinterpret_cast<T *>(q_atomic_fetch_and_store_acquire_ptr(&_q_value, newValue)); -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue) -{ - return reinterpret_cast<T *>(q_atomic_fetch_and_store_release_ptr(&_q_value, newValue)); -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) -{ - return reinterpret_cast<T *>(q_atomic_fetch_and_store_acquire_ptr(&_q_value, newValue)); -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd) -{ - return reinterpret_cast<T *>(q_atomic_fetch_and_add_ptr(&_q_value, valueToAdd * sizeof(T))); -} - -template <typename T> -Q_INLINE_TEMPLATE -T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd) -{ - return reinterpret_cast<T *>(q_atomic_fetch_and_add_acquire_ptr(&_q_value, valueToAdd * sizeof(T))); -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd) -{ - return reinterpret_cast<T *>(q_atomic_fetch_and_add_release_ptr(&_q_value, valueToAdd * sizeof(T))); -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) -{ - return reinterpret_cast<T *>(q_atomic_fetch_and_add_acquire_ptr(&_q_value, valueToAdd * sizeof(T))); -} - -#else - -#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; } - -extern "C" { - Q_CORE_EXPORT int q_atomic_lock_int(volatile int *addr); - Q_CORE_EXPORT int q_atomic_lock_ptr(volatile void *addr); - Q_CORE_EXPORT void q_atomic_unlock(volatile void *addr, int value); - Q_CORE_EXPORT int q_atomic_set_int(volatile int *ptr, int newval); - Q_CORE_EXPORT void *q_atomic_set_ptr(volatile void *ptr, void *newval); -} // extern "C" - -inline bool QBasicAtomicInt::ref() -{ - const int val = q_atomic_lock_int(&_q_value); - q_atomic_unlock(&_q_value, val + 1); - return val != -1; -} - -inline bool QBasicAtomicInt::deref() -{ - const int val = q_atomic_lock_int(&_q_value); - q_atomic_unlock(&_q_value, val - 1); - return val != 1; -} - -inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) -{ - int val = q_atomic_lock_int(&_q_value); - if (val == expectedValue) { - q_atomic_unlock(&_q_value, newValue); - return true; - } - q_atomic_unlock(&_q_value, val); - return false; -} - -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); -} - -inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) -{ - return q_atomic_set_int(&_q_value, newValue); -} - -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); -} - -inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) -{ - const int originalValue = q_atomic_lock_int(&_q_value); - q_atomic_unlock(&_q_value, originalValue + valueToAdd); - return originalValue; -} - -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); -} - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) -{ - T *val = reinterpret_cast<T *>(q_atomic_lock_ptr(&_q_value)); - if (val == expectedValue) { - q_atomic_unlock(&_q_value, reinterpret_cast<int>(newValue)); - return true; - } - q_atomic_unlock(&_q_value, reinterpret_cast<int>(val)); - return false; -} - -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); -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) -{ - return reinterpret_cast<T *>(q_atomic_set_ptr(&_q_value, newValue)); -} - -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); -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) -{ - T *originalValue = reinterpret_cast<T *>(q_atomic_lock_ptr(&_q_value)); - q_atomic_unlock(&_q_value, int(originalValue + valueToAdd)); - return originalValue; -} - -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); -} - -#endif // _LP64 - -QT_END_NAMESPACE - -#endif // QATOMIC_SPARC_H diff --git a/src/corelib/arch/qatomic_unix.h b/src/corelib/arch/qatomic_unix.h index 03c7d2eee8..02583297f9 100644 --- a/src/corelib/arch/qatomic_unix.h +++ b/src/corelib/arch/qatomic_unix.h @@ -59,6 +59,10 @@ QT_END_NAMESPACE #define Q_ATOMIC_INT_FETCH_AND_ADD_IS_NOT_NATIVE #define Q_ATOMIC_INT32_IS_SUPPORTED +#define Q_ATOMIC_INT32_REFERENCE_COUNTING_IS_NOT_NATIVE +#define Q_ATOMIC_INT32_TEST_AND_SET_IS_NOT_NATIVE +#define Q_ATOMIC_INT32_FETCH_AND_STORE_IS_NOT_NATIVE +#define Q_ATOMIC_INT32_FETCH_AND_ADD_IS_NOT_NATIVE #define Q_ATOMIC_POINTER_TEST_AND_SET_IS_NOT_NATIVE #define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_NOT_NATIVE diff --git a/src/corelib/arch/qatomic_vxworks.h b/src/corelib/arch/qatomic_vxworks.h deleted file mode 100644 index 57e3b6a32b..0000000000 --- a/src/corelib/arch/qatomic_vxworks.h +++ /dev/null @@ -1,330 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the qmake spec of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QATOMIC_VXWORKS_H -#define QATOMIC_VXWORKS_H - -#if defined(__ppc) -# include <QtCore/qatomic_power.h> -#else // generic implementation with taskLock() - -#include <QtCore/qoldbasicatomic.h> - -#if 0 -// we don't want to include the system header here for two function prototypes, -// because it pulls in a _lot_ of stuff that pollutes the global namespace -# include <vxWorksCommon.h> -# include <taskLib.h> -#else -#if defined(_WRS_KERNEL) -extern "C" int taskLock(); -extern "C" int taskUnlock(); -#else -inline int taskLock() { return 0; } -inline int taskUnlock() { return 0; } -#endif -#endif - - - -QT_BEGIN_NAMESPACE - -#if 0 -// silence syncqt warnings -QT_END_NAMESPACE -QT_END_HEADER - -#pragma qt_sync_skip_header_check -#pragma qt_sync_stop_processing -#endif - -#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_NOT_NATIVE - -inline bool QBasicAtomicInt::isFetchAndStoreNative() -{ return false; } -inline bool QBasicAtomicInt::isFetchAndStoreWaitFree() -{ return false; } - -#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_NOT_NATIVE - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative() -{ return false; } -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree() -{ return false; } - -#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; } - -// Reference counting - -inline bool QBasicAtomicInt::ref() -{ - taskLock(); - bool ret = (++_q_value != 0); - taskUnlock(); - return ret; -} - -inline bool QBasicAtomicInt::deref() -{ - taskLock(); - bool ret = (--_q_value != 0); - taskUnlock(); - return ret; -} - -// Test-and-set for integers - -inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) -{ - taskLock(); - if (_q_value == expectedValue) { - _q_value = newValue; - taskUnlock(); - return true; - } - taskUnlock(); - return false; -} - -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 - -inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) -{ - taskLock(); - int returnValue = _q_value; - _q_value = newValue; - taskUnlock(); - return returnValue; -} - -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) -{ - taskLock(); - int originalValue = _q_value; - _q_value += valueToAdd; - taskUnlock(); - return originalValue; -} - -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) -{ - taskLock(); - if (_q_value == expectedValue) { - _q_value = newValue; - taskUnlock(); - return true; - } - taskUnlock(); - return false; -} - -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 - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) -{ - taskLock(); - T *returnValue = (_q_value); - _q_value = newValue; - taskUnlock(); - return returnValue; -} - -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) -{ - taskLock(); - T *returnValue = (_q_value); - _q_value += valueToAdd; - taskUnlock(); - return returnValue; -} - -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 - -#endif // generic implementation with taskLock() - -#endif // QATOMIC_VXWORKS_H diff --git a/src/corelib/arch/qatomic_x86.h b/src/corelib/arch/qatomic_x86.h index f8180ad9d6..608b3db0ff 100644 --- a/src/corelib/arch/qatomic_x86.h +++ b/src/corelib/arch/qatomic_x86.h @@ -339,6 +339,8 @@ T QBasicAtomicOps<1>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveTy #define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_ALWAYS_NATIVE #define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_WAIT_FREE +#ifdef Q_PROCESSOR_X86_64 + #define Q_ATOMIC_INT64_IS_SUPPORTED #define Q_ATOMIC_INT64_REFERENCE_COUNTING_IS_ALWAYS_NATIVE @@ -353,7 +355,6 @@ T QBasicAtomicOps<1>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveTy #define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_ALWAYS_NATIVE #define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_WAIT_FREE -#ifdef Q_PROCESSOR_X86_64 // native support for 64-bit types template<> template<typename T> inline bool QBasicAtomicOps<8>::ref(T &_q_value) Q_DECL_NOTHROW diff --git a/src/corelib/codecs/qutfcodec.cpp b/src/corelib/codecs/qutfcodec.cpp index e425f8634c..b0e0b3f010 100644 --- a/src/corelib/codecs/qutfcodec.cpp +++ b/src/corelib/codecs/qutfcodec.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2013 Intel Corporation ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -48,6 +49,27 @@ QT_BEGIN_NAMESPACE enum { Endian = 0, Data = 1 }; +QByteArray QUtf8::convertFromUnicode(const QChar *uc, int len) +{ + // create a QByteArray with the worst case scenario size + QByteArray result(len * 3, Qt::Uninitialized); + uchar *dst = reinterpret_cast<uchar *>(const_cast<char *>(result.constData())); + const ushort *src = reinterpret_cast<const ushort *>(uc); + const ushort *const end = src + len; + + while (src != end) { + ushort uc = *src++; + int res = QUtf8Functions::toUtf8<QUtf8BaseTraits>(uc, dst, src, end); + if (res < 0) { + // encoding error - append '?' + *dst++ = '?'; + } + } + + result.truncate(dst - reinterpret_cast<uchar *>(const_cast<char *>(result.constData()))); + return result; +} + QByteArray QUtf8::convertFromUnicode(const QChar *uc, int len, QTextCodec::ConverterState *state) { uchar replacement = '?'; @@ -62,61 +84,35 @@ QByteArray QUtf8::convertFromUnicode(const QChar *uc, int len, QTextCodec::Conve surrogate_high = state->state_data[0]; } - QByteArray rstr; - rstr.resize(rlen); - uchar* cursor = (uchar*)rstr.data(); - const QChar *ch = uc; + + QByteArray rstr(rlen, Qt::Uninitialized); + uchar *cursor = reinterpret_cast<uchar *>(const_cast<char *>(rstr.constData())); + const ushort *src = reinterpret_cast<const ushort *>(uc); + const ushort *const end = src + len; + int invalid = 0; if (state && !(state->flags & QTextCodec::IgnoreHeader)) { + // append UTF-8 BOM *cursor++ = 0xef; *cursor++ = 0xbb; *cursor++ = 0xbf; } - const QChar *end = ch + len; - while (ch < end) { - uint u = ch->unicode(); - if (surrogate_high >= 0) { - if (ch->isLowSurrogate()) { - u = QChar::surrogateToUcs4(surrogate_high, u); - surrogate_high = -1; - } else { - // high surrogate without low - *cursor = replacement; - ++ch; - ++invalid; - surrogate_high = -1; - continue; - } - } else if (ch->isLowSurrogate()) { - // low surrogate without high - *cursor = replacement; - ++ch; - ++invalid; + while (src != end) { + ushort uc = surrogate_high == -1 ? *src++ : surrogate_high; + surrogate_high = -1; + int res = QUtf8Functions::toUtf8<QUtf8BaseTraits>(uc, cursor, src, end); + if (Q_LIKELY(res >= 0)) continue; - } else if (ch->isHighSurrogate()) { - surrogate_high = u; - ++ch; - continue; - } - if (u < 0x80) { - *cursor++ = (uchar)u; - } else { - if (u < 0x0800) { - *cursor++ = 0xc0 | ((uchar) (u >> 6)); - } else { - if (QChar::requiresSurrogates(u)) { - *cursor++ = 0xf0 | ((uchar) (u >> 18)); - *cursor++ = 0x80 | (((uchar) (u >> 12)) & 0x3f); - } else { - *cursor++ = 0xe0 | (((uchar) (u >> 12)) & 0x3f); - } - *cursor++ = 0x80 | (((uchar) (u >> 6)) & 0x3f); - } - *cursor++ = 0x80 | ((uchar) (u&0x3f)); + if (res == QUtf8BaseTraits::Error) { + // encoding error + ++invalid; + *cursor++ = replacement; + } else if (res == QUtf8BaseTraits::EndOfString) { + surrogate_high = uc; + break; } - ++ch; } rstr.resize(cursor - (const uchar*)rstr.constData()); @@ -132,114 +128,117 @@ QByteArray QUtf8::convertFromUnicode(const QChar *uc, int len, QTextCodec::Conve return rstr; } +QString QUtf8::convertToUnicode(const char *chars, int len) +{ + QString result(len + 1, Qt::Uninitialized); // worst case + ushort *dst = reinterpret_cast<ushort *>(const_cast<QChar *>(result.constData())); + const uchar *src = reinterpret_cast<const uchar *>(chars); + const uchar *end = src + len; + + while (src < end) { + uchar b = *src++; + int res = QUtf8Functions::fromUtf8<QUtf8BaseTraits>(b, dst, src, end); + if (res < 0) { + // decoding error + *dst++ = QChar::ReplacementCharacter; + } + } + + result.truncate(dst - reinterpret_cast<const ushort *>(result.constData())); + return result; +} + QString QUtf8::convertToUnicode(const char *chars, int len, QTextCodec::ConverterState *state) { bool headerdone = false; ushort replacement = QChar::ReplacementCharacter; int need = 0; - int error = -1; - uint uc = 0; - uint min_uc = 0; + int invalid = 0; + int res; + uchar ch = 0; + + QString result(need + len + 1, Qt::Uninitialized); // worst case + ushort *dst = reinterpret_cast<ushort *>(const_cast<QChar *>(result.constData())); + const uchar *src = reinterpret_cast<const uchar *>(chars); + const uchar *end = src + len; + if (state) { if (state->flags & QTextCodec::IgnoreHeader) headerdone = true; if (state->flags & QTextCodec::ConvertInvalidToNull) replacement = QChar::Null; - need = state->remainingChars; - if (need) { - uc = state->state_data[0]; - min_uc = state->state_data[1]; - } - } - if (!headerdone && len > 3 - && (uchar)chars[0] == 0xef && (uchar)chars[1] == 0xbb && (uchar)chars[2] == 0xbf) { - // starts with a byte order mark - chars += 3; - len -= 3; - headerdone = true; - } - - QString result(need + len + 1, Qt::Uninitialized); // worst case - ushort *qch = (ushort *)result.unicode(); - uchar ch; - int invalid = 0; - - for (int i = 0; i < len; ++i) { - ch = chars[i]; - if (need) { - if ((ch&0xc0) == 0x80) { - uc = (uc << 6) | (ch & 0x3f); - --need; - if (!need) { - // utf-8 bom composes into 0xfeff code point - if (!headerdone && uc == 0xfeff) { - // don't do anything, just skip the BOM - } else if (QChar::requiresSurrogates(uc) && uc <= QChar::LastValidCodePoint) { - // surrogate pair - Q_ASSERT((qch - (ushort*)result.unicode()) + 2 < result.length()); - *qch++ = QChar::highSurrogate(uc); - *qch++ = QChar::lowSurrogate(uc); - } else if ((uc < min_uc) || QChar::isSurrogate(uc) || uc > QChar::LastValidCodePoint) { - // error: overlong sequence, UTF16 surrogate or non-character - *qch++ = replacement; - ++invalid; - } else { - *qch++ = uc; - } - headerdone = true; - } - } else { - // error - i = error; - *qch++ = replacement; - ++invalid; - need = 0; - headerdone = true; - } - } else { - if (ch < 128) { - *qch++ = ushort(ch); - headerdone = true; - } else if ((ch & 0xe0) == 0xc0) { - uc = ch & 0x1f; - need = 1; - error = i; - min_uc = 0x80; - headerdone = true; - } else if ((ch & 0xf0) == 0xe0) { - uc = ch & 0x0f; - need = 2; - error = i; - min_uc = 0x800; - } else if ((ch&0xf8) == 0xf0) { - uc = ch & 0x07; - need = 3; - error = i; - min_uc = 0x10000; - headerdone = true; - } else { - // error - *qch++ = replacement; + if (state->remainingChars) { + // handle incoming state first + uchar remainingCharsData[4]; // longest UTF-8 sequence possible + int remainingCharsCount = state->remainingChars; + int newCharsToCopy = qMin<int>(sizeof(remainingCharsData) - remainingCharsCount, end - src); + + memset(remainingCharsData, 0, sizeof(remainingCharsData)); + memcpy(remainingCharsData, &state->state_data[0], remainingCharsCount); + memcpy(remainingCharsData + remainingCharsCount, src, newCharsToCopy); + + const uchar *begin = &remainingCharsData[1]; + res = QUtf8Functions::fromUtf8<QUtf8BaseTraits>(remainingCharsData[0], dst, begin, + static_cast<const uchar *>(remainingCharsData) + remainingCharsCount + newCharsToCopy); + if (res == QUtf8BaseTraits::EndOfString) { + // if we got EndOfString again, then there were too few bytes in src; + // copy to our state and return + state->remainingChars = remainingCharsCount + newCharsToCopy; + memcpy(&state->state_data[0], remainingCharsData, state->remainingChars); + return QString(); + } else if (res == QUtf8BaseTraits::Error) { ++invalid; + *dst++ = replacement; + } else if (!headerdone && res >= 0) { + // eat the UTF-8 BOM headerdone = true; + if (dst[-1] == 0xfeff) + --dst; } + + // adjust src now that we have maybe consumed a few chars + //Q_ASSERT(res > remainingCharsCount) + src += res - remainingCharsCount; } } - if (!state && need > 0) { - // unterminated UTF sequence - for (int i = error; i < len; ++i) { - *qch++ = replacement; + + // main body, stateless decoding + res = 0; + while (res >= 0 && src < end) { + ch = *src++; + res = QUtf8Functions::fromUtf8<QUtf8BaseTraits>(ch, dst, src, end); + if (!headerdone && res >= 0) { + headerdone = true; + // eat the UTF-8 BOM + if (dst[-1] == 0xfeff) + --dst; + } + if (res == QUtf8BaseTraits::Error) { + res = 0; ++invalid; + *dst++ = replacement; } } - result.truncate(qch - (ushort *)result.unicode()); + + if (!state && res == QUtf8BaseTraits::EndOfString) { + // unterminated UTF sequence + *dst++ = QChar::ReplacementCharacter; + while (src++ < end) + *dst++ = QChar::ReplacementCharacter; + } + + result.truncate(dst - (ushort *)result.unicode()); if (state) { state->invalidChars += invalid; - state->remainingChars = need; if (headerdone) state->flags |= QTextCodec::IgnoreHeader; - state->state_data[0] = need ? uc : 0; - state->state_data[1] = need ? min_uc : 0; + if (res == QUtf8BaseTraits::EndOfString) { + --src; // unread the byte in ch + state->remainingChars = end - src; + memcpy(&state->state_data[0], src, end - src); + } else { + state->remainingChars = 0; + } } return result; } diff --git a/src/corelib/codecs/qutfcodec_p.h b/src/corelib/codecs/qutfcodec_p.h index e1214d50bc..c252edede7 100644 --- a/src/corelib/codecs/qutfcodec_p.h +++ b/src/corelib/codecs/qutfcodec_p.h @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2013 Intel Corporation ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -58,6 +59,227 @@ QT_BEGIN_NAMESPACE +struct QUtf8BaseTraits +{ + static const bool isTrusted = false; + static const bool allowNonCharacters = true; + static const bool skipAsciiHandling = false; + static const int Error = -1; + static const int EndOfString = -2; + + static bool isValidCharacter(uint u) + { return int(u) >= 0; } + + static void appendByte(uchar *&ptr, uchar b) + { *ptr++ = b; } + + static uchar peekByte(const uchar *ptr, int n = 0) + { return ptr[n]; } + + static qptrdiff availableBytes(const uchar *ptr, const uchar *end) + { return end - ptr; } + + static void advanceByte(const uchar *&ptr, int n = 1) + { ptr += n; } + + static void appendUtf16(ushort *&ptr, ushort uc) + { *ptr++ = uc; } + + static void appendUcs4(ushort *&ptr, uint uc) + { + appendUtf16(ptr, QChar::highSurrogate(uc)); + appendUtf16(ptr, QChar::lowSurrogate(uc)); + } + + static ushort peekUtf16(const ushort *ptr, int n = 0) + { return ptr[n]; } + + static qptrdiff availableUtf16(const ushort *ptr, const ushort *end) + { return end - ptr; } + + static void advanceUtf16(const ushort *&ptr, int n = 1) + { ptr += n; } + + // it's possible to output to UCS-4 too + static void appendUtf16(uint *&ptr, ushort uc) + { *ptr++ = uc; } + + static void appendUcs4(uint *&ptr, uint uc) + { *ptr++ = uc; } +}; + +struct QUtf8BaseTraitsNoAscii : public QUtf8BaseTraits +{ + static const bool skipAsciiHandling = true; +}; + +namespace QUtf8Functions +{ + /// returns 0 on success; errors can only happen if \a u is a surrogate: + /// Error if \a u is a low surrogate; + /// if \a u is a high surrogate, Error if the next isn't a low one, + /// EndOfString if we run into the end of the string. + template <typename Traits, typename OutputPtr, typename InputPtr> inline + int toUtf8(ushort u, OutputPtr &dst, InputPtr &src, InputPtr end) + { + if (!Traits::skipAsciiHandling && u < 0x80) { + // U+0000 to U+007F (US-ASCII) - one byte + Traits::appendByte(dst, uchar(u)); + return 0; + } else if (u < 0x0800) { + // U+0080 to U+07FF - two bytes + // first of two bytes + Traits::appendByte(dst, 0xc0 | uchar(u >> 6)); + } else { + if (!QChar::isSurrogate(u)) { + // U+0800 to U+FFFF (except U+D800-U+DFFF) - three bytes + if (!Traits::allowNonCharacters && QChar::isNonCharacter(u)) + return Traits::Error; + + // first of three bytes + Traits::appendByte(dst, 0xe0 | uchar(u >> 12)); + } else { + // U+10000 to U+10FFFF - four bytes + // need to get one extra codepoint + if (Traits::availableUtf16(src, end) == 0) + return Traits::EndOfString; + + ushort low = Traits::peekUtf16(src); + if (!QChar::isHighSurrogate(u)) + return Traits::Error; + if (!QChar::isLowSurrogate(low)) + return Traits::Error; + + Traits::advanceUtf16(src); + uint ucs4 = QChar::surrogateToUcs4(u, low); + + if (!Traits::allowNonCharacters && QChar::isNonCharacter(ucs4)) + return Traits::Error; + + // first byte + Traits::appendByte(dst, 0xf0 | (uchar(ucs4 >> 18) & 0xf)); + + // second of four bytes + Traits::appendByte(dst, 0x80 | (uchar(ucs4 >> 12) & 0x3f)); + + // for the rest of the bytes + u = ushort(ucs4); + } + + // second to last byte + Traits::appendByte(dst, 0x80 | (uchar(u >> 6) & 0x3f)); + } + + // last byte + Traits::appendByte(dst, 0x80 | (u & 0x3f)); + return 0; + } + + inline bool isContinuationByte(uchar b) + { + return (b & 0xc0) == 0x80; + } + + /// returns the number of characters consumed (including \a b) in case of success; + /// returns negative in case of error: Traits::Error or Traits::EndOfString + template <typename Traits, typename OutputPtr, typename InputPtr> inline + int fromUtf8(uchar b, OutputPtr &dst, InputPtr &src, InputPtr end) + { + int charsNeeded; + uint min_uc; + uint uc; + + if (!Traits::skipAsciiHandling && b < 0x80) { + // US-ASCII + Traits::appendUtf16(dst, b); + return 1; + } + + if (!Traits::isTrusted && Q_UNLIKELY(b <= 0xC1)) { + // an UTF-8 first character must be at least 0xC0 + // however, all 0xC0 and 0xC1 first bytes can only produce overlong sequences + return Traits::Error; + } else if (b < 0xe0) { + charsNeeded = 2; + min_uc = 0x80; + uc = b & 0x1f; + } else if (b < 0xf0) { + charsNeeded = 3; + min_uc = 0x800; + uc = b & 0x0f; + } else if (b < 0xf5) { + charsNeeded = 4; + min_uc = 0x10000; + uc = b & 0x07; + } else { + // the last Unicode character is U+10FFFF + // it's encoded in UTF-8 as "\xF4\x8F\xBF\xBF" + // therefore, a byte higher than 0xF4 is not the UTF-8 first byte + return Traits::Error; + } + + int bytesAvailable = Traits::availableBytes(src, end); + if (Q_UNLIKELY(bytesAvailable < charsNeeded - 1)) { + // it's possible that we have an error instead of just unfinished bytes + if (bytesAvailable > 0 && !isContinuationByte(Traits::peekByte(src, 0))) + return Traits::Error; + if (bytesAvailable > 1 && !isContinuationByte(Traits::peekByte(src, 1))) + return Traits::Error; + if (bytesAvailable > 2 && !isContinuationByte(Traits::peekByte(src, 2))) + return Traits::Error; + return Traits::EndOfString; + } + + // first continuation character + b = Traits::peekByte(src, 0); + if (!isContinuationByte(b)) + return Traits::Error; + uc <<= 6; + uc |= b & 0x3f; + + if (charsNeeded > 2) { + // second continuation character + b = Traits::peekByte(src, 1); + if (!isContinuationByte(b)) + return Traits::Error; + uc <<= 6; + uc |= b & 0x3f; + + if (charsNeeded > 3) { + // third continuation character + b = Traits::peekByte(src, 2); + if (!isContinuationByte(b)) + return Traits::Error; + uc <<= 6; + uc |= b & 0x3f; + } + } + + // we've decoded something; safety-check it + if (!Traits::isTrusted) { + if (uc < min_uc) + return Traits::Error; + if (QChar::isSurrogate(uc) || uc > QChar::LastValidCodePoint) + return Traits::Error; + if (!Traits::allowNonCharacters && QChar::isNonCharacter(uc)) + return Traits::Error; + } + + // write the UTF-16 sequence + if (!QChar::requiresSurrogates(uc)) { + // UTF-8 decoded and no surrogates are required + // detach if necessary + Traits::appendUtf16(dst, ushort(uc)); + } else { + // UTF-8 decoded to something that requires a surrogate pair + Traits::appendUcs4(dst, uc); + } + + Traits::advanceByte(src, charsNeeded - 1); + return charsNeeded; + } +} + enum DataEndianness { DetectEndianness, @@ -67,7 +289,9 @@ enum DataEndianness struct QUtf8 { + static QString convertToUnicode(const char *, int); static QString convertToUnicode(const char *, int, QTextCodec::ConverterState *); + static QByteArray convertFromUnicode(const QChar *, int); static QByteArray convertFromUnicode(const QChar *, int, QTextCodec::ConverterState *); }; diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h index 44077132d4..2b957782e8 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -98,6 +98,7 @@ # define Q_UNREACHABLE_IMPL() __assume(0) # define Q_NORETURN __declspec(noreturn) # define Q_DECL_DEPRECATED __declspec(deprecated) +# define Q_DECL_DEPRECATED_X(text) __declspec(deprecated(text)) # define Q_DECL_EXPORT __declspec(dllexport) # define Q_DECL_IMPORT __declspec(dllimport) /* Intel C++ disguising as Visual C++: the `using' keyword avoids warnings */ @@ -152,6 +153,9 @@ # define Q_CC_INTEL # define Q_ASSUME_IMPL(expr) __assume(expr) # define Q_UNREACHABLE_IMPL() __builtin_unreachable() +# if __INTEL_COMPILER >= 1300 +# define Q_DECL_DEPRECATED_X(text) __attribute__ ((__deprecated__(text))) +# endif # elif defined(__clang__) /* Clang also masquerades as GCC */ # define Q_CC_CLANG @@ -173,6 +177,7 @@ # if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405 # define Q_ASSUME_IMPL(expr) if (expr){} else __builtin_unreachable() # define Q_UNREACHABLE_IMPL() __builtin_unreachable() +# define Q_DECL_DEPRECATED_X(text) __attribute__ ((__deprecated__(text))) # endif # endif @@ -528,6 +533,9 @@ # if !__has_feature(cxx_rtti) # define QT_NO_RTTI # endif +# if __has_feature(attribute_deprecated_with_message) +# define Q_DECL_DEPRECATED_X(text) __attribute__ ((__deprecated__(text))) +# endif /* C++11 features, see http://clang.llvm.org/cxx_status.html */ # if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) @@ -861,6 +869,9 @@ #ifndef Q_DECL_VARIABLE_DEPRECATED # define Q_DECL_VARIABLE_DEPRECATED Q_DECL_DEPRECATED #endif +#ifndef Q_DECL_DEPRECATED_X +# define Q_DECL_DEPRECATED_X(text) Q_DECL_DEPRECATED +#endif #ifndef Q_DECL_EXPORT # define Q_DECL_EXPORT #endif diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index 6644d6d101..e0a78d8533 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -2186,7 +2186,9 @@ QString qt_error_string(int errorCode) s = QT_TRANSLATE_NOOP("QIODevice", "No space left on device"); break; default: { -#ifdef Q_OS_WIN +#if defined(Q_OS_WIN) + // Retrieve the system error message for the last-error code. +# ifndef Q_OS_WINRT wchar_t *string = 0; FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, NULL, @@ -2197,6 +2199,17 @@ QString qt_error_string(int errorCode) NULL); ret = QString::fromWCharArray(string); LocalFree((HLOCAL)string); +# else // !Q_OS_WINRT + __declspec(thread) static wchar_t errorString[4096]; + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + errorCode, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + errorString, + ARRAYSIZE(errorString), + NULL); + ret = QString::fromWCharArray(errorString); +# endif // Q_OS_WINRT if (ret.isEmpty() && errorCode == ERROR_MOD_NOT_FOUND) ret = QString::fromLatin1("The specified module could not be found."); diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 9db48354b3..8a86dc158e 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -45,11 +45,11 @@ #include <stddef.h> -#define QT_VERSION_STR "5.2.1" +#define QT_VERSION_STR "5.3.0" /* QT_VERSION is (major << 16) + (minor << 8) + patch. */ -#define QT_VERSION 0x050201 +#define QT_VERSION 0x050300 /* can be used like #if (QT_VERSION >= QT_VERSION_CHECK(4, 4, 0)) */ @@ -191,7 +191,7 @@ typedef qint64 qlonglong; typedef quint64 qulonglong; #ifndef QT_POINTER_SIZE -# if defined(Q_OS_WIN64) +# if defined(Q_OS_WIN64) || (defined(Q_OS_WINRT) && defined(_M_X64)) # define QT_POINTER_SIZE 8 # elif defined(Q_OS_WIN32) || defined(Q_OS_WINCE) || defined(Q_OS_WINRT) # define QT_POINTER_SIZE 4 @@ -221,11 +221,14 @@ typedef double qreal; #if defined(QT_NO_DEPRECATED) # undef QT_DEPRECATED +# undef QT_DEPRECATED_X # undef QT_DEPRECATED_VARIABLE # undef QT_DEPRECATED_CONSTRUCTOR #elif defined(QT_DEPRECATED_WARNINGS) # undef QT_DEPRECATED # define QT_DEPRECATED Q_DECL_DEPRECATED +# undef QT_DEPRECATED_X +# define QT_DEPRECATED_X(text) Q_DECL_DEPRECATED_X(text) # undef QT_DEPRECATED_VARIABLE # define QT_DEPRECATED_VARIABLE Q_DECL_VARIABLE_DEPRECATED # undef QT_DEPRECATED_CONSTRUCTOR @@ -233,6 +236,8 @@ typedef double qreal; #else # undef QT_DEPRECATED # define QT_DEPRECATED +# undef QT_DEPRECATED_X +# define QT_DEPRECATED_X(text) # undef QT_DEPRECATED_VARIABLE # define QT_DEPRECATED_VARIABLE # undef QT_DEPRECATED_CONSTRUCTOR @@ -559,7 +564,12 @@ class QDataStream; #endif #if defined(Q_OS_WINRT) +# define QT_NO_FILESYSTEMWATCHER +# define QT_NO_GETADDRINFO +# define QT_NO_NETWORKPROXY # define QT_NO_PROCESS +# define QT_NO_SOCKETNOTIFIER +# define QT_NO_SOCKS5 #endif inline void qt_noop(void) {} @@ -1030,14 +1040,17 @@ template <typename T> struct QEnableIf<true, T> { typedef T Type; }; #endif QT_END_NAMESPACE -// Q_GLOBAL_STATIC -#include <QtCore/qglobalstatic.h> -// qDebug and friends +// We need to keep QTypeInfo, QSysInfo, QFlags, qDebug & family in qglobal.h for compatibility with Qt 4. +// Be careful when changing the order of these files. +#include <QtCore/qtypeinfo.h> +#include <QtCore/qsysinfo.h> #include <QtCore/qlogging.h> + #include <QtCore/qflags.h> -#include <QtCore/qsysinfo.h> -#include <QtCore/qtypeinfo.h> + +#include <QtCore/qatomic.h> +#include <QtCore/qglobalstatic.h> #endif /* __cplusplus */ diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp index 1c3b09f602..22a9980812 100644 --- a/src/corelib/global/qlibraryinfo.cpp +++ b/src/corelib/global/qlibraryinfo.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include "qdir.h" +#include "qstringlist.h" #include "qfile.h" #include "qsettings.h" #include "qlibraryinfo.h" @@ -113,6 +114,8 @@ public: } }; +static const char platformsSection[] = "Platforms"; + QLibrarySettings::QLibrarySettings() : settings(QLibraryInfoPrivate::findConfiguration()) { @@ -132,7 +135,8 @@ QLibrarySettings::QLibrarySettings() haveEffectivePaths = children.contains(QLatin1String("EffectivePaths")); #endif // Backwards compat: an existing but empty file is claimed to contain the Paths section. - havePaths = !haveEffectivePaths || children.contains(QLatin1String("Paths")); + havePaths = (!haveEffectivePaths && !children.contains(QLatin1String(platformsSection))) + || children.contains(QLatin1String("Paths")); #ifndef QT_BOOTSTRAPPED if (!havePaths) settings.reset(0); @@ -466,6 +470,33 @@ QLibraryInfo::rawLocation(LibraryLocation loc, PathGroup group) } /*! + Returns additional arguments to the platform plugin matching + \a platformName which can be specified as a string list using + the key \c Arguments in a group called \c Platforms of the + \c qt.conf file. + + sa {Using qt.conf} + + \internal + + \since 5.3 +*/ + +QStringList QLibraryInfo::platformPluginArguments(const QString &platformName) +{ +#ifndef QT_BOOTSTRAPPED + if (const QSettings *settings = QLibraryInfoPrivate::findConfiguration()) { + QString key = QLatin1String(platformsSection); + key += QLatin1Char('/'); + key += platformName; + key += QLatin1String("Arguments"); + return settings->value(key).toStringList(); + } +#endif // !QT_BOOTSTRAPPED + return QStringList(); +} + +/*! \enum QLibraryInfo::LibraryLocation \keyword library location diff --git a/src/corelib/global/qlibraryinfo.h b/src/corelib/global/qlibraryinfo.h index 17864b555b..54ef794d3e 100644 --- a/src/corelib/global/qlibraryinfo.h +++ b/src/corelib/global/qlibraryinfo.h @@ -47,6 +47,8 @@ QT_BEGIN_NAMESPACE +class QStringList; + class Q_CORE_EXPORT QLibraryInfo { public: @@ -96,6 +98,8 @@ public: static QString rawLocation(LibraryLocation, PathGroup); #endif + static QStringList platformPluginArguments(const QString &platformName); + private: QLibraryInfo(); }; diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index 8a46f3a6ab..97212def92 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -998,6 +998,10 @@ public: Key_ChannelUp = 0x01000118, Key_ChannelDown = 0x01000119, + Key_Guide = 0x0100011a, + Key_Info = 0x0100011b, + Key_Settings = 0x0100011c, + Key_MediaLast = 0x0100ffff, // Keypad navigation keys @@ -1015,6 +1019,7 @@ public: //Key_Jisho = 0x01020007, // IME: Dictionary key //Key_Oyayubi_Left = 0x01020008, // IME: Left Oyayubi key //Key_Oyayubi_Right = 0x01020009, // IME: Right Oyayubi key + Key_Exit = 0x0102000a, // Device keys Key_Context1 = 0x01100000, @@ -1596,6 +1601,12 @@ public: ScrollUpdate, ScrollEnd }; + + enum MouseEventSource { + MouseEventNotSynthesized, + MouseEventSynthesizedBySystem, + MouseEventSynthesizedByQt + }; } #ifdef Q_MOC_RUN ; diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc index ae377e124b..851b6609ea 100644 --- a/src/corelib/global/qnamespace.qdoc +++ b/src/corelib/global/qnamespace.qdoc @@ -2895,3 +2895,25 @@ \value ScrollEnd Scrolling has ended, but the scrolling distance did not change anymore. */ + +/*! + \enum Qt::MouseEventSource + \since 5.3 + + This enum describes the source of a mouse event and can be useful + to determine if the event is an artificial mouse event originating + from another device such as a touchscreen. + + \value MouseEventNotSynthesized The most common value. On + platforms where such information is available this value indicates + that the event was generated in response to a genuine mouse event + in the system. + + \value MouseEventSynthesizedBySystem Indicates that the mouse + event was synthesized from a touch event by the platform. + + \value MouseEventSynthesizedByQt Indicates that the mouse event was + synthesized from an unhandled touch event by Qt. + + \sa Qt::AA_SynthesizeMouseForUnhandledTouchEvents +*/ diff --git a/src/corelib/global/qnumeric.cpp b/src/corelib/global/qnumeric.cpp index d09357c26c..7d8bd8c3c6 100644 --- a/src/corelib/global/qnumeric.cpp +++ b/src/corelib/global/qnumeric.cpp @@ -41,6 +41,7 @@ #include "qnumeric.h" #include "qnumeric_p.h" +#include <string.h> QT_BEGIN_NAMESPACE @@ -99,4 +100,139 @@ Q_CORE_EXPORT double qQNaN() { return qt_qnan(); } Q_CORE_EXPORT double qInf() { return qt_inf(); } + +/*! + \internal + */ +static inline quint32 f2i(float f) +{ + quint32 i; + memcpy(&i, &f, sizeof(f)); + return i; +} + +/*! + Returns the number of representable floating-point numbers between \a a and \a b. + + This function provides an alternative way of doing approximated comparisons of floating-point + numbers similar to qFuzzyCompare(). However, it returns the distance between two numbers, which + gives the caller a possibility to choose the accepted error. Errors are relative, so for + instance the distance between 1.0E-5 and 1.00001E-5 will give 110, while the distance between + 1.0E36 and 1.00001E36 will give 127. + + This function is useful if a floating point comparison requires a certain precision. + Therefore, if \a a and \a b are equal it will return 0. The maximum value it will return for 32-bit + floating point numbers is 4,278,190,078. This is the distance between \c{-FLT_MAX} and + \c{+FLT_MAX}. + + The function does not give meaningful results if any of the arguments are \c Infinite or \c NaN. + You can check for this by calling qIsFinite(). + + The return value can be considered as the "error", so if you for instance want to compare + two 32-bit floating point numbers and all you need is an approximated 24-bit precision, you can + use this function like this: + + \code + if (qFloatDistance(a, b) < (1 << 7)) { // The last 7 bits are not + // significant + // precise enough + } + \endcode + + \sa qFuzzyCompare() + \relates <QtGlobal> +*/ +Q_CORE_EXPORT quint32 qFloatDistance(float a, float b) +{ + static const quint32 smallestPositiveFloatAsBits = 0x00000001; // denormalized, (SMALLEST), (1.4E-45) + /* Assumes: + * IEE754 format. + * Integers and floats have the same endian + */ + Q_STATIC_ASSERT(sizeof(quint32) == sizeof(float)); + Q_ASSERT(qIsFinite(a) && qIsFinite(b)); + if (a == b) + return 0; + if ((a < 0) != (b < 0)) { + // if they have different signs + if (a < 0) + a = -a; + else /*if (b < 0)*/ + b = -b; + return qFloatDistance(0.0F, a) + qFloatDistance(0.0F, b); + } + if (a < 0) { + a = -a; + b = -b; + } + // at this point a and b should not be negative + + // 0 is special + if (!a) + return f2i(b) - smallestPositiveFloatAsBits + 1; + if (!b) + return f2i(a) - smallestPositiveFloatAsBits + 1; + + // finally do the common integer subtraction + return a > b ? f2i(a) - f2i(b) : f2i(b) - f2i(a); +} + + +/*! + \internal + */ +static inline quint64 d2i(double d) +{ + quint64 i; + memcpy(&i, &d, sizeof(d)); + return i; +} + +/*! + Returns the number of representable floating-point numbers between \a a and \a b. + + This function serves the same purpose as \c{qFloatDistance(float, float)}, but + returns the distance between two \c double numbers. Since the range is larger + than for two \c float numbers (\c{[-DBL_MAX,DBL_MAX]}), the return type is quint64. + + + \sa qFuzzyCompare() + \relates <QtGlobal> +*/ +Q_CORE_EXPORT quint64 qFloatDistance(double a, double b) +{ + static const quint64 smallestPositiveFloatAsBits = 0x1; // denormalized, (SMALLEST) + /* Assumes: + * IEE754 format double precision + * Integers and floats have the same endian + */ + Q_STATIC_ASSERT(sizeof(quint64) == sizeof(double)); + Q_ASSERT(qIsFinite(a) && qIsFinite(b)); + if (a == b) + return 0; + if ((a < 0) != (b < 0)) { + // if they have different signs + if (a < 0) + a = -a; + else /*if (b < 0)*/ + b = -b; + return qFloatDistance(0.0, a) + qFloatDistance(0.0, b); + } + if (a < 0) { + a = -a; + b = -b; + } + // at this point a and b should not be negative + + // 0 is special + if (!a) + return d2i(b) - smallestPositiveFloatAsBits + 1; + if (!b) + return d2i(a) - smallestPositiveFloatAsBits + 1; + + // finally do the common integer subtraction + return a > b ? d2i(a) - d2i(b) : d2i(b) - d2i(a); +} + + QT_END_NAMESPACE diff --git a/src/corelib/global/qnumeric.h b/src/corelib/global/qnumeric.h index 25db5443eb..633486dff1 100644 --- a/src/corelib/global/qnumeric.h +++ b/src/corelib/global/qnumeric.h @@ -57,6 +57,9 @@ Q_CORE_EXPORT double qSNaN(); Q_CORE_EXPORT double qQNaN(); Q_CORE_EXPORT double qInf(); +Q_CORE_EXPORT quint32 qFloatDistance(float a, float b); +Q_CORE_EXPORT quint64 qFloatDistance(double a, double b); + #define Q_INFINITY (QT_PREPEND_NAMESPACE(qInf)()) #define Q_SNAN (QT_PREPEND_NAMESPACE(qSNaN)()) #define Q_QNAN (QT_PREPEND_NAMESPACE(qQNaN)()) diff --git a/src/corelib/global/qtypeinfo.h b/src/corelib/global/qtypeinfo.h index 5837c8d94e..114e11345a 100644 --- a/src/corelib/global/qtypeinfo.h +++ b/src/corelib/global/qtypeinfo.h @@ -60,6 +60,7 @@ class QTypeInfo public: enum { isPointer = false, + isIntegral = false, isComplex = true, isStatic = true, isLarge = (sizeof(T)>sizeof(void*)), @@ -74,6 +75,7 @@ class QTypeInfo<void> public: enum { isPointer = false, + isIntegral = false, isComplex = false, isStatic = false, isLarge = false, @@ -88,6 +90,7 @@ class QTypeInfo<T*> public: enum { isPointer = true, + isIntegral = false, isComplex = false, isStatic = false, isLarge = false, @@ -125,6 +128,7 @@ public: isStatic = QTypeInfo<T1>::isStatic || QTypeInfo<T2>::isStatic || QTypeInfo<T3>::isStatic || QTypeInfo<T4>::isStatic, isLarge = sizeof(T) > sizeof(void*), isPointer = false, + isIntegral = false, isDummy = false, sizeOf = sizeof(T) }; @@ -138,6 +142,7 @@ class QTypeInfo< CONTAINER<T> > \ public: \ enum { \ isPointer = false, \ + isIntegral = false, \ isComplex = true, \ isStatic = false, \ isLarge = (sizeof(CONTAINER<T>) > sizeof(void*)), \ @@ -168,7 +173,8 @@ enum { /* TYPEINFO flags */ Q_PRIMITIVE_TYPE = 0x1, Q_STATIC_TYPE = 0, Q_MOVABLE_TYPE = 0x2, - Q_DUMMY_TYPE = 0x4 + Q_DUMMY_TYPE = 0x4, + Q_INTEGRAL_TYPE = 0x8 }; #define Q_DECLARE_TYPEINFO_BODY(TYPE, FLAGS) \ @@ -180,6 +186,7 @@ public: \ isStatic = (((FLAGS) & (Q_MOVABLE_TYPE | Q_PRIMITIVE_TYPE)) == 0), \ isLarge = (sizeof(TYPE)>sizeof(void*)), \ isPointer = false, \ + isIntegral = ((FLAGS) & Q_INTEGRAL_TYPE) != 0, \ isDummy = (((FLAGS) & Q_DUMMY_TYPE) != 0), \ sizeOf = sizeof(TYPE) \ }; \ @@ -221,23 +228,33 @@ Q_DECLARE_SHARED_STL(TYPE) /* QTypeInfo primitive specializations */ -Q_DECLARE_TYPEINFO(bool, Q_PRIMITIVE_TYPE); -Q_DECLARE_TYPEINFO(char, Q_PRIMITIVE_TYPE); -Q_DECLARE_TYPEINFO(signed char, Q_PRIMITIVE_TYPE); -Q_DECLARE_TYPEINFO(uchar, Q_PRIMITIVE_TYPE); -Q_DECLARE_TYPEINFO(short, Q_PRIMITIVE_TYPE); -Q_DECLARE_TYPEINFO(ushort, Q_PRIMITIVE_TYPE); -Q_DECLARE_TYPEINFO(int, Q_PRIMITIVE_TYPE); -Q_DECLARE_TYPEINFO(uint, Q_PRIMITIVE_TYPE); -Q_DECLARE_TYPEINFO(long, Q_PRIMITIVE_TYPE); -Q_DECLARE_TYPEINFO(ulong, Q_PRIMITIVE_TYPE); -Q_DECLARE_TYPEINFO(qint64, Q_PRIMITIVE_TYPE); -Q_DECLARE_TYPEINFO(quint64, Q_PRIMITIVE_TYPE); +Q_DECLARE_TYPEINFO(bool, Q_PRIMITIVE_TYPE | Q_INTEGRAL_TYPE); +Q_DECLARE_TYPEINFO(char, Q_PRIMITIVE_TYPE | Q_INTEGRAL_TYPE); +Q_DECLARE_TYPEINFO(signed char, Q_PRIMITIVE_TYPE | Q_INTEGRAL_TYPE); +Q_DECLARE_TYPEINFO(uchar, Q_PRIMITIVE_TYPE | Q_INTEGRAL_TYPE); +Q_DECLARE_TYPEINFO(short, Q_PRIMITIVE_TYPE | Q_INTEGRAL_TYPE); +Q_DECLARE_TYPEINFO(ushort, Q_PRIMITIVE_TYPE | Q_INTEGRAL_TYPE); +Q_DECLARE_TYPEINFO(int, Q_PRIMITIVE_TYPE | Q_INTEGRAL_TYPE); +Q_DECLARE_TYPEINFO(uint, Q_PRIMITIVE_TYPE | Q_INTEGRAL_TYPE); +Q_DECLARE_TYPEINFO(long, Q_PRIMITIVE_TYPE | Q_INTEGRAL_TYPE); +Q_DECLARE_TYPEINFO(ulong, Q_PRIMITIVE_TYPE | Q_INTEGRAL_TYPE); +Q_DECLARE_TYPEINFO(qint64, Q_PRIMITIVE_TYPE | Q_INTEGRAL_TYPE); +Q_DECLARE_TYPEINFO(quint64, Q_PRIMITIVE_TYPE | Q_INTEGRAL_TYPE); Q_DECLARE_TYPEINFO(float, Q_PRIMITIVE_TYPE); Q_DECLARE_TYPEINFO(double, Q_PRIMITIVE_TYPE); #ifndef Q_OS_DARWIN Q_DECLARE_TYPEINFO(long double, Q_PRIMITIVE_TYPE); #endif +#ifdef Q_COMPILER_UNICODE_STRINGS +// ### Qt6: define as Q_PRIMITIVE_TYPE +// We can't do it now because it would break BC on QList<char32_t> +Q_DECLARE_TYPEINFO(char16_t, Q_INTEGRAL_TYPE); +Q_DECLARE_TYPEINFO(char32_t, Q_INTEGRAL_TYPE); +#endif +#if !defined(Q_CC_MSVC) || defined(_NATIVE_WCHAR_T_DEFINED) +// ### Qt6: same as above +Q_DECLARE_TYPEINFO(wchar_t, Q_INTEGRAL_TYPE); +#endif QT_END_NAMESPACE #endif // QTYPEINFO_H diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri index f06bf61b09..0ec3d949b9 100644 --- a/src/corelib/io/io.pri +++ b/src/corelib/io/io.pri @@ -94,7 +94,6 @@ SOURCES += \ io/qloggingregistry.cpp win32 { - SOURCES += io/qsettings_win.cpp SOURCES += io/qfsfileengine_win.cpp SOURCES += io/qlockfile_win.cpp @@ -102,11 +101,12 @@ win32 { HEADERS += io/qfilesystemwatcher_win_p.h SOURCES += io/qfilesystemengine_win.cpp SOURCES += io/qfilesystemiterator_win.cpp - SOURCES += io/qstandardpaths_win.cpp !winrt { + SOURCES += io/qsettings_win.cpp HEADERS += io/qwindowspipewriter_p.h SOURCES += io/qwindowspipewriter.cpp + SOURCES += io/qstandardpaths_win.cpp wince* { SOURCES += io/qprocess_wince.cpp @@ -119,6 +119,8 @@ win32 { io/qwinoverlappedionotifier.cpp \ io/qwindowspipereader.cpp } + } else { + SOURCES += io/qstandardpaths_winrt.cpp } } else:unix|integrity { SOURCES += \ diff --git a/src/corelib/io/qdatastream.cpp b/src/corelib/io/qdatastream.cpp index af5605f8c7..a6fbffee7e 100644 --- a/src/corelib/io/qdatastream.cpp +++ b/src/corelib/io/qdatastream.cpp @@ -251,7 +251,7 @@ QT_BEGIN_NAMESPACE return retVal; enum { - DefaultStreamVersion = QDataStream::Qt_5_2 + DefaultStreamVersion = QDataStream::Qt_5_3 }; /*! @@ -541,6 +541,7 @@ void QDataStream::setByteOrder(ByteOrder bo) \value Qt_5_0 Version 13 (Qt 5.0) \value Qt_5_1 Version 14 (Qt 5.1) \value Qt_5_2 Version 15 (Qt 5.2) + \value Qt_5_3 Same as Qt_5_2 \sa setVersion(), version() */ diff --git a/src/corelib/io/qdatastream.h b/src/corelib/io/qdatastream.h index f107e801b6..28f1d51a12 100644 --- a/src/corelib/io/qdatastream.h +++ b/src/corelib/io/qdatastream.h @@ -87,8 +87,9 @@ public: Qt_4_9 = Qt_4_8, Qt_5_0 = 13, Qt_5_1 = 14, - Qt_5_2 = 15 -#if QT_VERSION >= 0x050300 + Qt_5_2 = 15, + Qt_5_3 = Qt_5_2 +#if QT_VERSION >= 0x050400 #error Add the datastream version for this Qt version #endif }; diff --git a/src/corelib/io/qdebug.h b/src/corelib/io/qdebug.h index 9ed5f6e951..00177b659e 100644 --- a/src/corelib/io/qdebug.h +++ b/src/corelib/io/qdebug.h @@ -80,7 +80,9 @@ public: inline QDebug &operator=(const QDebug &other); inline ~QDebug() { if (!--stream->ref) { - if(stream->message_output) { + if (stream->space && stream->buffer.endsWith(QLatin1Char(' '))) + stream->buffer.chop(1); + if (stream->message_output) { QT_TRY { qt_message_output(stream->type, stream->context, @@ -172,6 +174,7 @@ template <class T> inline QDebug operator<<(QDebug debug, const QList<T> &list) #endif { + const bool oldSetting = debug.autoInsertSpaces(); debug.nospace() << '('; for (typename QList<T>::size_type i = 0; i < list.count(); ++i) { if (i) @@ -179,7 +182,8 @@ inline QDebug operator<<(QDebug debug, const QList<T> &list) debug << list.at(i); } debug << ')'; - return debug.space(); + debug.setAutoInsertSpaces(oldSetting); + return debug.maybeSpace(); } #if defined(FORCE_UREF) @@ -190,7 +194,9 @@ template <typename T> inline QDebug operator<<(QDebug debug, const QVector<T> &vec) #endif { + const bool oldSetting = debug.autoInsertSpaces(); debug.nospace() << "QVector"; + debug.setAutoInsertSpaces(oldSetting); return operator<<(debug, vec.toList()); } @@ -202,13 +208,15 @@ template <class aKey, class aT> inline QDebug operator<<(QDebug debug, const QMap<aKey, aT> &map) #endif { + const bool oldSetting = debug.autoInsertSpaces(); debug.nospace() << "QMap("; for (typename QMap<aKey, aT>::const_iterator it = map.constBegin(); it != map.constEnd(); ++it) { debug << '(' << it.key() << ", " << it.value() << ')'; } debug << ')'; - return debug.space(); + debug.setAutoInsertSpaces(oldSetting); + return debug.maybeSpace(); } #if defined(FORCE_UREF) @@ -219,12 +227,14 @@ template <class aKey, class aT> inline QDebug operator<<(QDebug debug, const QHash<aKey, aT> &hash) #endif { + const bool oldSetting = debug.autoInsertSpaces(); debug.nospace() << "QHash("; for (typename QHash<aKey, aT>::const_iterator it = hash.constBegin(); it != hash.constEnd(); ++it) debug << '(' << it.key() << ", " << it.value() << ')'; debug << ')'; - return debug.space(); + debug.setAutoInsertSpaces(oldSetting); + return debug.maybeSpace(); } #if defined(FORCE_UREF) @@ -235,14 +245,18 @@ template <class T1, class T2> inline QDebug operator<<(QDebug debug, const QPair<T1, T2> &pair) #endif { + const bool oldSetting = debug.autoInsertSpaces(); debug.nospace() << "QPair(" << pair.first << ',' << pair.second << ')'; - return debug.space(); + debug.setAutoInsertSpaces(oldSetting); + return debug.maybeSpace(); } template <typename T> inline QDebug operator<<(QDebug debug, const QSet<T> &set) { + const bool oldSetting = debug.autoInsertSpaces(); debug.nospace() << "QSet"; + debug.setAutoInsertSpaces(oldSetting); return operator<<(debug, set.toList()); } @@ -254,6 +268,7 @@ template <class T> inline QDebug operator<<(QDebug debug, const QContiguousCache<T> &cache) #endif { + const bool oldSetting = debug.autoInsertSpaces(); debug.nospace() << "QContiguousCache("; for (int i = cache.firstIndex(); i <= cache.lastIndex(); ++i) { debug << cache[i]; @@ -261,7 +276,8 @@ inline QDebug operator<<(QDebug debug, const QContiguousCache<T> &cache) debug << ", "; } debug << ')'; - return debug.space(); + debug.setAutoInsertSpaces(oldSetting); + return debug.maybeSpace(); } #if defined(FORCE_UREF) @@ -272,6 +288,7 @@ template <class T> inline QDebug operator<<(QDebug debug, const QFlags<T> &flags) #endif { + const bool oldSetting = debug.autoInsertSpaces(); debug.nospace() << "QFlags("; bool needSeparator = false; for (uint i = 0; i < sizeof(T) * 8; ++i) { @@ -284,7 +301,8 @@ inline QDebug operator<<(QDebug debug, const QFlags<T> &flags) } } debug << ')'; - return debug.space(); + debug.setAutoInsertSpaces(oldSetting); + return debug.maybeSpace(); } QT_END_NAMESPACE diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp index 43db2ec1fe..a60bcde30d 100644 --- a/src/corelib/io/qdir.cpp +++ b/src/corelib/io/qdir.cpp @@ -2144,7 +2144,7 @@ QString QDir::cleanPath(const QString &path) name.replace(dir_separator, QLatin1Char('/')); bool allowUncPaths = false; -#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) //allow unc paths +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) //allow unc paths allowUncPaths = true; #endif diff --git a/src/corelib/io/qdiriterator.cpp b/src/corelib/io/qdiriterator.cpp index 5b48c4c7db..79cdec9674 100644 --- a/src/corelib/io/qdiriterator.cpp +++ b/src/corelib/io/qdiriterator.cpp @@ -477,7 +477,7 @@ QDirIterator::~QDirIterator() /*! Advances the iterator to the next entry, and returns the file path of this new entry. If hasNext() returns \c false, this function does nothing, and - returns a null QString. + returns an empty QString. You can call fileName() or filePath() to get the current entry file name or path, or fileInfo() to get a QFileInfo for the current entry. diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp index 257f18a6bb..dbc6d28846 100644 --- a/src/corelib/io/qfilesystemengine_win.cpp +++ b/src/corelib/io/qfilesystemengine_win.cpp @@ -63,13 +63,28 @@ # include <types.h> #endif #include <objbase.h> -#include <shlobj.h> +#ifndef Q_OS_WINRT +# include <shlobj.h> +# include <accctrl.h> +#endif #include <initguid.h> -#include <accctrl.h> #include <ctype.h> #include <limits.h> -#define SECURITY_WIN32 -#include <security.h> +#ifndef Q_OS_WINRT +# define SECURITY_WIN32 +# include <security.h> +#else // !Q_OS_WINRT +# include <wrl.h> +# include <windows.foundation.h> +# include <windows.storage.h> +# include <Windows.ApplicationModel.h> + +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Storage; +using namespace ABI::Windows::ApplicationModel; +#endif // Q_OS_WINRT #ifndef SPI_GETPLATFORMTYPE #define SPI_GETPLATFORMTYPE 257 @@ -141,7 +156,7 @@ QT_BEGIN_NAMESPACE Q_CORE_EXPORT int qt_ntfs_permission_lookup = 0; -#if defined(Q_OS_WINCE) +#if defined(Q_OS_WINCE) || defined(Q_OS_WINRT) static QString qfsPrivateCurrentDir = QLatin1String(""); // As none of the functions we try to resolve do exist on Windows CE // we use QT_NO_LIBRARY to shorten everything up a little bit. @@ -289,14 +304,14 @@ static bool resolveUNCLibs() } #endif triedResolve = true; -#if !defined(Q_OS_WINCE) +#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) HINSTANCE hLib = QSystemLibrary::load(L"Netapi32"); if (hLib) { ptrNetShareEnum = (PtrNetShareEnum)GetProcAddress(hLib, "NetShareEnum"); if (ptrNetShareEnum) ptrNetApiBufferFree = (PtrNetApiBufferFree)GetProcAddress(hLib, "NetApiBufferFree"); } -#endif +#endif // !Q_OS_WINCE && !Q_OS_WINRT } return ptrNetShareEnum && ptrNetApiBufferFree; } @@ -304,7 +319,7 @@ static bool resolveUNCLibs() static QString readSymLink(const QFileSystemEntry &link) { QString result; -#if !defined(Q_OS_WINCE) +#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) HANDLE handle = CreateFile((wchar_t*)link.nativeFilePath().utf16(), FILE_READ_EA, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, @@ -347,11 +362,11 @@ static QString readSymLink(const QFileSystemEntry &link) result.replace(0,matchVolName.matchedLength(), QString::fromWCharArray(buffer)); } } -#endif +#endif // !Q_OS_WINCE && !Q_OS_WINRT } #else Q_UNUSED(link); -#endif // Q_OS_WINCE +#endif // Q_OS_WINCE || Q_OS_WINRT return result; } @@ -432,7 +447,11 @@ static inline bool getFindData(QString path, WIN32_FIND_DATA &findData) // can't handle drives if (!path.endsWith(QLatin1Char(':'))) { +#ifndef Q_OS_WINRT HANDLE hFind = ::FindFirstFile((wchar_t*)path.utf16(), &findData); +#else + HANDLE hFind = ::FindFirstFileEx((const wchar_t*)path.utf16(), FindExInfoStandard, &findData, FindExSearchNameMatch, NULL, 0); +#endif if (hFind != INVALID_HANDLE_VALUE) { ::FindClose(hFind); return true; @@ -506,7 +525,7 @@ QString QFileSystemEngine::nativeAbsoluteFilePath(const QString &path) { // can be //server or //server/share QString absPath; -#if !defined(Q_OS_WINCE) +#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) QVarLengthArray<wchar_t, MAX_PATH> buf(qMax(MAX_PATH, path.size() + 1)); wchar_t *fileName = 0; DWORD retLen = GetFullPathName((wchar_t*)path.utf16(), buf.size(), buf.data(), &fileName); @@ -516,12 +535,17 @@ QString QFileSystemEngine::nativeAbsoluteFilePath(const QString &path) } if (retLen != 0) absPath = QString::fromWCharArray(buf.data(), retLen); -#else +#elif !defined(Q_OS_WINCE) + if (QDir::isRelativePath(path)) + absPath = QDir::toNativeSeparators(QDir::cleanPath(QDir::currentPath() + QLatin1Char('/') + path)); + else + absPath = QDir::toNativeSeparators(QDir::cleanPath(path)); +#else // Q_OS_WINRT if (path.startsWith(QLatin1Char('/')) || path.startsWith(QLatin1Char('\\'))) absPath = QDir::toNativeSeparators(path); else absPath = QDir::toNativeSeparators(QDir::cleanPath(qfsPrivateCurrentDir + QLatin1Char('/') + path)); -#endif +#endif // Q_OS_WINCE // This is really ugly, but GetFullPathName strips off whitespace at the end. // If you for instance write ". " in the lineedit of QFileDialog, // (which is an invalid filename) this function will strip the space off and viola, @@ -548,9 +572,17 @@ QFileSystemEntry QFileSystemEngine::absoluteName(const QFileSystemEntry &entry) ret = entry.filePath(); #endif } else { +#ifndef Q_OS_WINRT ret = QDir::cleanPath(QDir::currentPath() + QLatin1Char('/') + entry.filePath()); +#else + // Some WinRT APIs do not support absolute paths (due to sandboxing). + // Thus the port uses the executable's directory as its root directory + // and treats paths relative to that as absolute paths. + ret = QDir::cleanPath(QDir::current().relativeFilePath(entry.filePath())); +#endif } +#ifndef Q_OS_WINRT // The path should be absolute at this point. // From the docs : // Absolute paths begin with the directory separator "/" @@ -563,6 +595,7 @@ QFileSystemEntry QFileSystemEngine::absoluteName(const QFileSystemEntry &entry) // Force uppercase drive letters. ret[0] = ret.at(0).toUpper(); } +#endif // !Q_OS_WINRT return QFileSystemEntry(ret, QFileSystemEntry::FromInternalPath()); } @@ -590,18 +623,24 @@ typedef struct _FILE_ID_INFO { static inline QByteArray fileId(HANDLE handle) { QByteArray result; +#ifndef Q_OS_WINRT BY_HANDLE_FILE_INFORMATION info; if (GetFileInformationByHandle(handle, &info)) { result = QByteArray::number(uint(info.nFileIndexLow), 16); result += ':'; result += QByteArray::number(uint(info.nFileIndexHigh), 16); } +#else // !Q_OS_WINRT + Q_UNUSED(handle); + Q_UNIMPLEMENTED(); +#endif // Q_OS_WINRT return result; } // File ID for Windows starting from version 8. QByteArray fileIdWin8(HANDLE handle) { +#ifndef Q_OS_WINRT typedef BOOL (WINAPI* GetFileInformationByHandleExType)(HANDLE, Q_FILE_INFO_BY_HANDLE_CLASS, void *, DWORD); // Dynamically resolve GetFileInformationByHandleEx (Vista onwards). @@ -621,6 +660,16 @@ QByteArray fileIdWin8(HANDLE handle) result += QByteArray((char *)&infoEx.FileId, sizeof(infoEx.FileId)).toHex(); } } +#else // !Q_OS_WINRT + QByteArray result; + FILE_ID_INFO infoEx; + if (GetFileInformationByHandleEx(handle, FileIdInfo, + &infoEx, sizeof(FILE_ID_INFO))) { + result = QByteArray::number(infoEx.VolumeSerialNumber, 16); + result += ':'; + result += QByteArray((char *)infoEx.FileId.Identifier, sizeof(infoEx.FileId.Identifier)).toHex(); + } +#endif // Q_OS_WINRT return result; } #endif // !Q_OS_WINCE @@ -631,8 +680,13 @@ QByteArray QFileSystemEngine::id(const QFileSystemEntry &entry) #ifndef Q_OS_WINCE QByteArray result; const HANDLE handle = +#ifndef Q_OS_WINRT CreateFile((wchar_t*)entry.nativeFilePath().utf16(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); +#else // !Q_OS_WINRT + CreateFile2((const wchar_t*)entry.nativeFilePath().utf16(), GENERIC_READ, + FILE_SHARE_READ, OPEN_EXISTING, NULL); +#endif // Q_OS_WINRT if (handle) { result = QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS8 ? fileIdWin8(handle) : fileId(handle); @@ -810,7 +864,7 @@ static bool tryDriveUNCFallback(const QFileSystemEntry &fname, QFileSystemMetaDa { bool entryExists = false; DWORD fileAttrib = 0; -#if !defined(Q_OS_WINCE) +#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) if (fname.isDriveRoot()) { // a valid drive ?? DWORD drivesBitmask = ::GetLogicalDrives(); @@ -851,7 +905,7 @@ static bool tryDriveUNCFallback(const QFileSystemEntry &fname, QFileSystemMetaDa fileAttrib = FILE_ATTRIBUTE_DIRECTORY; entryExists = true; } -#if !defined(Q_OS_WINCE) +#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) } #endif if (entryExists) @@ -894,12 +948,32 @@ bool QFileSystemEngine::fillMetaData(HANDLE fHandle, QFileSystemMetaData &data, { data.entryFlags &= ~what; clearWinStatData(data); +#ifndef Q_OS_WINRT BY_HANDLE_FILE_INFORMATION fileInfo; UINT oldmode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX); if (GetFileInformationByHandle(fHandle , &fileInfo)) { data.fillFromFindInfo(fileInfo); } SetErrorMode(oldmode); +#else // !Q_OS_WINRT + FILE_BASIC_INFO fileBasicInfo; + if (GetFileInformationByHandleEx(fHandle, FileBasicInfo, &fileBasicInfo, sizeof(fileBasicInfo))) { + data.fillFromFileAttribute(fileBasicInfo.FileAttributes); + data.creationTime_.dwHighDateTime = fileBasicInfo.CreationTime.HighPart; + data.creationTime_.dwLowDateTime = fileBasicInfo.CreationTime.LowPart; + data.lastAccessTime_.dwHighDateTime = fileBasicInfo.LastAccessTime.HighPart; + data.lastAccessTime_.dwLowDateTime = fileBasicInfo.LastAccessTime.LowPart; + data.lastWriteTime_.dwHighDateTime = fileBasicInfo.LastWriteTime.HighPart; + data.lastWriteTime_.dwLowDateTime = fileBasicInfo.LastWriteTime.LowPart; + if (!(data.fileAttribute_ & FILE_ATTRIBUTE_DIRECTORY)) { + FILE_STANDARD_INFO fileStandardInfo; + if (GetFileInformationByHandleEx(fHandle, FileStandardInfo, &fileStandardInfo, sizeof(fileStandardInfo))) + data.size_ = fileStandardInfo.EndOfFile.QuadPart; + } else + data.size_ = 0; + data.knownFlagsMask |= QFileSystemMetaData::Times | QFileSystemMetaData::SizeAttribute; + } +#endif // Q_OS_WINRT return data.hasFlags(what); } @@ -931,7 +1005,9 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM } if (what & QFileSystemMetaData::WinStatFlags) { +#ifndef Q_OS_WINRT UINT oldmode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX); +#endif clearWinStatData(data); WIN32_FIND_DATA findData; // The memory structure for WIN32_FIND_DATA is same as WIN32_FILE_ATTRIBUTE_DATA @@ -943,11 +1019,15 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM } else { if (!tryFindFallback(fname, data)) if (!tryDriveUNCFallback(fname, data)) { +#ifndef Q_OS_WINRT SetErrorMode(oldmode); +#endif return false; } } +#ifndef Q_OS_WINRT SetErrorMode(oldmode); +#endif } if (what & QFileSystemMetaData::Permissions) @@ -1006,7 +1086,14 @@ static bool isDirPath(const QString &dirPath, bool *existed) if (path.length() == 2 && path.at(1) == QLatin1Char(':')) path += QLatin1Char('\\'); +#ifndef Q_OS_WINRT DWORD fileAttrib = ::GetFileAttributes((wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16()); +#else // Q_OS_WINRT + DWORD fileAttrib = INVALID_FILE_ATTRIBUTES; + WIN32_FILE_ATTRIBUTE_DATA data; + if (::GetFileAttributesEx((const wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16(), GetFileExInfoStandard, &data)) + fileAttrib = data.dwFileAttributes; +#endif // Q_OS_WINRT if (fileAttrib == INVALID_FILE_ATTRIBUTES) { int errorCode = GetLastError(); if (errorCode == ERROR_ACCESS_DENIED || errorCode == ERROR_SHARING_VIOLATION) { @@ -1100,6 +1187,30 @@ QString QFileSystemEngine::rootPath() { #if defined(Q_OS_WINCE) QString ret = QLatin1String("/"); +#elif defined(Q_OS_WINRT) + // We specify the package root as root directory + QString ret = QLatin1String("/"); + // Get package location + ComPtr<IPackageStatics> statics; + if (FAILED(GetActivationFactory(HStringReference(RuntimeClass_Windows_ApplicationModel_Package).Get(), &statics))) + return ret; + ComPtr<IPackage> package; + if (FAILED(statics->get_Current(&package))) + return ret; + ComPtr<IStorageFolder> installedLocation; + if (FAILED(package->get_InstalledLocation(&installedLocation))) + return ret; + + ComPtr<IStorageItem> item; + if (FAILED(installedLocation.As(&item))) + return ret; + + HSTRING finalWinPath; + if (FAILED(item->get_Path(&finalWinPath))) + return ret; + + ret = QDir::fromNativeSeparators(QString::fromWCharArray(WindowsGetStringRawBuffer(finalWinPath, nullptr))); + #else QString ret = QString::fromLatin1(qgetenv("SystemDrive").constData()); if (ret.isEmpty()) @@ -1158,12 +1269,13 @@ QString QFileSystemEngine::homePath() QString QFileSystemEngine::tempPath() { QString ret; +#ifndef Q_OS_WINRT wchar_t tempPath[MAX_PATH]; const DWORD len = GetTempPath(MAX_PATH, tempPath); #ifdef Q_OS_WINCE if (len) ret = QString::fromWCharArray(tempPath, len); -#else +#else // Q_OS_WINCE if (len) { // GetTempPath() can return short names, expand. wchar_t longTempPath[MAX_PATH]; const DWORD longLen = GetLongPathName(tempPath, longTempPath, MAX_PATH); @@ -1171,12 +1283,33 @@ QString QFileSystemEngine::tempPath() QString::fromWCharArray(longTempPath, longLen) : QString::fromWCharArray(tempPath, len); } -#endif +#endif // !Q_OS_WINCE if (!ret.isEmpty()) { while (ret.endsWith(QLatin1Char('\\'))) ret.chop(1); ret = QDir::fromNativeSeparators(ret); } +#else // !Q_OS_WINRT + // According to http://msdn.microsoft.com/en-us/library/windows/apps/windows.storage.applicationdata.temporaryfolder.aspx + // the API is not available on winphone which should cause one of the functions + // below to fail + ComPtr<IApplicationDataStatics> applicationDataStatics; + if (FAILED(GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_ApplicationData).Get(), &applicationDataStatics))) + return ret; + ComPtr<IApplicationData> applicationData; + if (FAILED(applicationDataStatics->get_Current(&applicationData))) + return ret; + ComPtr<IStorageFolder> tempFolder; + if (FAILED(applicationData->get_TemporaryFolder(&tempFolder))) + return ret; + ComPtr<IStorageItem> tempFolderItem; + if (FAILED(tempFolder.As(&tempFolderItem))) + return ret; + HSTRING path; + if (FAILED(tempFolderItem->get_Path(&path))) + return ret; + ret = QDir::fromNativeSeparators(QString::fromWCharArray(WindowsGetStringRawBuffer(path, nullptr))); +#endif // Q_OS_WINRT if (ret.isEmpty()) { #if !defined(Q_OS_WINCE) ret = QLatin1String("C:/tmp"); @@ -1195,7 +1328,7 @@ bool QFileSystemEngine::setCurrentPath(const QFileSystemEntry &entry) if(!(meta.exists() && meta.isDirectory())) return false; -#if !defined(Q_OS_WINCE) +#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) //TODO: this should really be using nativeFilePath(), but that returns a path in long format \\?\c:\foo //which causes many problems later on when it's returned through currentPath() return ::SetCurrentDirectory(reinterpret_cast<const wchar_t*>(QDir::toNativeSeparators(entry.filePath()).utf16())) != 0; @@ -1208,7 +1341,7 @@ bool QFileSystemEngine::setCurrentPath(const QFileSystemEntry &entry) QFileSystemEntry QFileSystemEngine::currentPath() { QString ret; -#if !defined(Q_OS_WINCE) +#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) DWORD size = 0; wchar_t currentName[PATH_MAX]; size = ::GetCurrentDirectory(PATH_MAX, currentName); @@ -1224,13 +1357,17 @@ QFileSystemEntry QFileSystemEngine::currentPath() } if (ret.length() >= 2 && ret[1] == QLatin1Char(':')) ret[0] = ret.at(0).toUpper(); // Force uppercase drive letters. -#else +#else // !Q_OS_WINCE && !Q_OS_WINRT //TODO - a race condition exists when using currentPath / setCurrentPath from multiple threads if (qfsPrivateCurrentDir.isEmpty()) +#ifndef Q_OS_WINRT qfsPrivateCurrentDir = QCoreApplication::applicationDirPath(); +#else + qfsPrivateCurrentDir = QDir::rootPath(); +#endif ret = qfsPrivateCurrentDir; -#endif +#endif // Q_OS_WINCE || Q_OS_WINRT return QFileSystemEntry(ret, QFileSystemEntry::FromNativePath()); } @@ -1248,8 +1385,16 @@ bool QFileSystemEngine::createLink(const QFileSystemEntry &source, const QFileSy //static bool QFileSystemEngine::copyFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error) { +#ifndef Q_OS_WINRT bool ret = ::CopyFile((wchar_t*)source.nativeFilePath().utf16(), (wchar_t*)target.nativeFilePath().utf16(), true) != 0; +#else // !Q_OS_WINRT + COPYFILE2_EXTENDED_PARAMETERS copyParams = { + sizeof(copyParams), COPY_FILE_FAIL_IF_EXISTS, NULL, NULL, NULL + }; + bool ret = ::CopyFile2((const wchar_t*)source.nativeFilePath().utf16(), + (const wchar_t*)target.nativeFilePath().utf16(), ©Params) != 0; +#endif // Q_OS_WINRT if(!ret) error = QSystemError(::GetLastError(), QSystemError::NativeError); return ret; @@ -1258,8 +1403,13 @@ bool QFileSystemEngine::copyFile(const QFileSystemEntry &source, const QFileSyst //static bool QFileSystemEngine::renameFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error) { +#ifndef Q_OS_WINRT bool ret = ::MoveFile((wchar_t*)source.nativeFilePath().utf16(), (wchar_t*)target.nativeFilePath().utf16()) != 0; +#else // !Q_OS_WINRT + bool ret = ::MoveFileEx((const wchar_t*)source.nativeFilePath().utf16(), + (const wchar_t*)target.nativeFilePath().utf16(), 0) != 0; +#endif // Q_OS_WINRT if(!ret) error = QSystemError(::GetLastError(), QSystemError::NativeError); return ret; diff --git a/src/corelib/io/qfilesystementry.cpp b/src/corelib/io/qfilesystementry.cpp index 3934c6a673..42a724670e 100644 --- a/src/corelib/io/qfilesystementry.cpp +++ b/src/corelib/io/qfilesystementry.cpp @@ -170,6 +170,12 @@ void QFileSystemEntry::resolveNativeFilePath() const #else m_nativeFilePath = QFile::encodeName(QDir::toNativeSeparators(m_filePath)); #endif +#ifdef Q_OS_WINRT + while (m_nativeFilePath.startsWith(QLatin1Char('\\'))) + m_nativeFilePath.remove(0,1); + if (m_nativeFilePath.isEmpty()) + m_nativeFilePath.append(QLatin1Char('.')); +#endif } } diff --git a/src/corelib/io/qfilesystemiterator_unix.cpp b/src/corelib/io/qfilesystemiterator_unix.cpp index bfedd3f70c..0b59aa169a 100644 --- a/src/corelib/io/qfilesystemiterator_unix.cpp +++ b/src/corelib/io/qfilesystemiterator_unix.cpp @@ -105,8 +105,8 @@ bool QFileSystemIterator::advance(QFileSystemEntry &fileEntry, QFileSystemMetaDa if (!dir) return false; -#if defined(Q_OS_QNX) && defined(__EXT_QNX__READDIR_R) - lastError = _readdir_r(dir, mt_file.data(), &dirEntry, direntSize); +#if defined(Q_OS_QNX) && defined(QT_EXT_QNX_READDIR_R) + lastError = QT_EXT_QNX_READDIR_R(dir, mt_file.data(), &dirEntry, direntSize); if (lastError) return false; #elif defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_CYGWIN) diff --git a/src/corelib/io/qfilesystemiterator_win.cpp b/src/corelib/io/qfilesystemiterator_win.cpp index 90232f7cfc..dda96bd45a 100644 --- a/src/corelib/io/qfilesystemiterator_win.cpp +++ b/src/corelib/io/qfilesystemiterator_win.cpp @@ -39,10 +39,12 @@ ** ****************************************************************************/ -#if _WIN32_WINNT < 0x0500 -#undef _WIN32_WINNT -#define _WIN32_WINNT 0x0500 -#endif +#if !defined(WINAPI_FAMILY) +# if _WIN32_WINNT < 0x0500 +# undef _WIN32_WINNT +# define _WIN32_WINNT 0x0500 +# endif // _WIN32_WINNT < 0x500 +#endif // !WINAPI_FAMILY #include "qfilesystemiterator_p.h" #include "qfilesystemengine_p.h" @@ -73,6 +75,10 @@ QFileSystemIterator::QFileSystemIterator(const QFileSystemEntry &entry, QDir::Fi if (!nativePath.endsWith(QLatin1Char('\\'))) nativePath.append(QLatin1Char('\\')); nativePath.append(QLatin1Char('*')); +#ifdef Q_OS_WINRT + if (nativePath.startsWith(QLatin1Char('\\'))) + nativePath.remove(0, 1); +#endif if (!dirPath.endsWith(QLatin1Char('/'))) dirPath.append(QLatin1Char('/')); if ((filters & (QDir::Dirs|QDir::Drives)) && (!(filters & (QDir::Files)))) diff --git a/src/corelib/io/qfilesystemmetadata_p.h b/src/corelib/io/qfilesystemmetadata_p.h index 1abc9b7ec4..de79ec32d3 100644 --- a/src/corelib/io/qfilesystemmetadata_p.h +++ b/src/corelib/io/qfilesystemmetadata_p.h @@ -219,7 +219,9 @@ public: #if defined(Q_OS_WIN) inline void fillFromFileAttribute(DWORD fileAttribute, bool isDriveRoot = false); inline void fillFromFindData(WIN32_FIND_DATA &findData, bool setLinkType = false, bool isDriveRoot = false); +# ifndef Q_OS_WINRT inline void fillFromFindInfo(BY_HANDLE_FILE_INFORMATION &fileInfo); +# endif #endif private: friend class QFileSystemEngine; @@ -340,6 +342,7 @@ inline void QFileSystemMetaData::fillFromFindData(WIN32_FIND_DATA &findData, boo } } +#ifndef Q_OS_WINRT inline void QFileSystemMetaData::fillFromFindInfo(BY_HANDLE_FILE_INFORMATION &fileInfo) { fillFromFileAttribute(fileInfo.dwFileAttributes); @@ -355,7 +358,8 @@ inline void QFileSystemMetaData::fillFromFindInfo(BY_HANDLE_FILE_INFORMATION &fi } knownFlagsMask |= Times | SizeAttribute; } -#endif +#endif // !Q_OS_WINRT +#endif // Q_OS_WIN QT_END_NAMESPACE diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp index 2b38019674..c974daab06 100644 --- a/src/corelib/io/qfsfileengine_win.cpp +++ b/src/corelib/io/qfsfileengine_win.cpp @@ -60,14 +60,18 @@ # include <types.h> #endif #include <objbase.h> -#include <shlobj.h> +#ifndef Q_OS_WINRT +# include <shlobj.h> +# include <accctrl.h> +#endif #include <initguid.h> -#include <accctrl.h> #include <ctype.h> #include <limits.h> #include <stdio.h> -#define SECURITY_WIN32 -#include <security.h> +#ifndef Q_OS_WINRT +# define SECURITY_WIN32 +# include <security.h> +#endif #ifndef PATH_MAX #define PATH_MAX FILENAME_MAX @@ -93,7 +97,7 @@ QString QFSFileEnginePrivate::longFileName(const QString &path) return path; QString absPath = QFileSystemEngine::nativeAbsoluteFilePath(path); -#if !defined(Q_OS_WINCE) +#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) QString prefix = QLatin1String("\\\\?\\"); if (isUncPath(absPath)) { prefix.append(QLatin1String("UNC\\")); // "\\\\?\\UNC\\" @@ -121,11 +125,12 @@ bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode) if (openMode & QIODevice::WriteOnly) accessRights |= GENERIC_WRITE; - SECURITY_ATTRIBUTES securityAtts = { sizeof(SECURITY_ATTRIBUTES), NULL, FALSE }; // WriteOnly can create files, ReadOnly cannot. DWORD creationDisp = (openMode & QIODevice::WriteOnly) ? OPEN_ALWAYS : OPEN_EXISTING; // Create the file handle. +#ifndef Q_OS_WINRT + SECURITY_ATTRIBUTES securityAtts = { sizeof(SECURITY_ATTRIBUTES), NULL, FALSE }; fileHandle = CreateFile((const wchar_t*)fileEntry.nativeFilePath().utf16(), accessRights, shareMode, @@ -133,6 +138,13 @@ bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode) creationDisp, FILE_ATTRIBUTE_NORMAL, NULL); +#else // !Q_OS_WINRT + fileHandle = CreateFile2((const wchar_t*)fileEntry.nativeFilePath().utf16(), + accessRights, + shareMode, + creationDisp, + NULL); +#endif // Q_OS_WINRT // Bail out on error. if (fileHandle == INVALID_HANDLE_VALUE) { @@ -473,7 +485,7 @@ int QFSFileEnginePrivate::nativeHandle() const */ bool QFSFileEnginePrivate::nativeIsSequential() const { -#if !defined(Q_OS_WINCE) +#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) HANDLE handle = fileHandle; if (fh || fd != -1) handle = (HANDLE)_get_osfhandle(fh ? QT_FILENO(fh) : fd); @@ -577,7 +589,7 @@ bool QFSFileEngine::setCurrentPath(const QString &path) QString QFSFileEngine::currentPath(const QString &fileName) { -#if !defined(Q_OS_WINCE) +#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) QString ret; //if filename is a drive: then get the pwd of that drive if (fileName.length() >= 2 && @@ -596,10 +608,10 @@ QString QFSFileEngine::currentPath(const QString &fileName) if (ret.length() >= 2 && ret[1] == QLatin1Char(':')) ret[0] = ret.at(0).toUpper(); // Force uppercase drive letters. return ret; -#else +#else // !Q_OS_WINCE && !Q_OS_WINRT Q_UNUSED(fileName); return QFileSystemEngine::currentPath().filePath(); -#endif +#endif // Q_OS_WINCE || Q_OS_WINRT } QString QFSFileEngine::homePath() @@ -620,7 +632,7 @@ QString QFSFileEngine::tempPath() QFileInfoList QFSFileEngine::drives() { QFileInfoList ret; -#if !defined(Q_OS_WINCE) +#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) #if defined(Q_OS_WIN32) quint32 driveBits = (quint32) GetLogicalDrives() & 0x3ffffff; #endif @@ -633,10 +645,10 @@ QFileInfoList QFSFileEngine::drives() driveBits = driveBits >> 1; } return ret; -#else +#else // !Q_OS_WINCE && !Q_OS_WINRT ret.append(QFileInfo(QLatin1String("/"))); return ret; -#endif +#endif // Q_OS_WINCE || Q_OS_WINRT } bool QFSFileEnginePrivate::doStat(QFileSystemMetaData::MetaDataFlags flags) const @@ -661,7 +673,7 @@ bool QFSFileEnginePrivate::doStat(QFileSystemMetaData::MetaDataFlags flags) cons bool QFSFileEngine::link(const QString &newName) { -#if !defined(Q_OS_WINCE) +#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) #if !defined(QT_NO_LIBRARY) bool ret = false; @@ -707,7 +719,7 @@ bool QFSFileEngine::link(const QString &newName) Q_UNUSED(newName); return false; #endif // QT_NO_LIBRARY -#else +#elif defined(Q_OS_WINCE) QString linkName = newName; linkName.replace(QLatin1Char('/'), QLatin1Char('\\')); if (!linkName.endsWith(QLatin1String(".lnk"))) @@ -720,7 +732,11 @@ bool QFSFileEngine::link(const QString &newName) if (!ret) setError(QFile::RenameError, qt_error_string()); return ret; -#endif // Q_OS_WINCE +#else // Q_OS_WINCE + Q_UNUSED(newName); + Q_UNIMPLEMENTED(); + return false; +#endif // Q_OS_WINRT } /*! @@ -937,6 +953,7 @@ QDateTime QFSFileEngine::fileTime(FileTime time) const uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFlags flags) { +#ifndef Q_OS_WINPHONE Q_Q(QFSFileEngine); Q_UNUSED(flags); if (openMode == QFile::NotOpen) { @@ -980,7 +997,11 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, // first create the file mapping handle DWORD protection = (openMode & QIODevice::WriteOnly) ? PAGE_READWRITE : PAGE_READONLY; +#ifndef Q_OS_WINRT mapHandle = ::CreateFileMapping(handle, 0, protection, 0, 0, 0); +#else + mapHandle = ::CreateFileMappingFromApp(handle, 0, protection, 0, 0); +#endif if (mapHandle == NULL) { q->setError(QFile::PermissionsError, qt_error_string()); #ifdef Q_USE_DEPRECATED_MAP_API @@ -998,15 +1019,23 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, DWORD offsetHi = offset >> 32; DWORD offsetLo = offset & Q_UINT64_C(0xffffffff); SYSTEM_INFO sysinfo; +#ifndef Q_OS_WINRT ::GetSystemInfo(&sysinfo); +#else + ::GetNativeSystemInfo(&sysinfo); +#endif DWORD mask = sysinfo.dwAllocationGranularity - 1; DWORD extra = offset & mask; if (extra) offsetLo &= ~mask; // attempt to create the map +#ifndef Q_OS_WINRT LPVOID mapAddress = ::MapViewOfFile(mapHandle, access, offsetHi, offsetLo, size + extra); +#else + LPVOID mapAddress = ::MapViewOfFileFromApp(mapHandle, access, offset, size); +#endif if (mapAddress) { uchar *address = extra + static_cast<uchar*>(mapAddress); maps[address] = extra; @@ -1025,11 +1054,18 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, ::CloseHandle(mapHandle); mapHandle = NULL; +#else // !Q_OS_WINPHONE + Q_UNUSED(offset); + Q_UNUSED(size); + Q_UNUSED(flags); + Q_UNIMPLEMENTED(); +#endif // Q_OS_WINPHONE return 0; } bool QFSFileEnginePrivate::unmap(uchar *ptr) { +#ifndef Q_OS_WINPHONE Q_Q(QFSFileEngine); if (!maps.contains(ptr)) { q->setError(QFile::PermissionsError, qt_error_string(ERROR_ACCESS_DENIED)); @@ -1048,6 +1084,11 @@ bool QFSFileEnginePrivate::unmap(uchar *ptr) } return true; +#else // !Q_OS_WINPHONE + Q_UNUSED(ptr); + Q_UNIMPLEMENTED(); + return false; +#endif // Q_OS_WINPHONE } QT_END_NAMESPACE diff --git a/src/corelib/io/qlockfile_win.cpp b/src/corelib/io/qlockfile_win.cpp index b5f6d9f3da..28f6b02a64 100644 --- a/src/corelib/io/qlockfile_win.cpp +++ b/src/corelib/io/qlockfile_win.cpp @@ -52,7 +52,6 @@ QT_BEGIN_NAMESPACE QLockFile::LockError QLockFilePrivate::tryLock_sys() { - SECURITY_ATTRIBUTES securityAtts = { sizeof(SECURITY_ATTRIBUTES), NULL, FALSE }; const QFileSystemEntry fileEntry(fileName); // When writing, allow others to read. // When reading, QFile will allow others to read and write, all good. @@ -60,6 +59,8 @@ QLockFile::LockError QLockFilePrivate::tryLock_sys() // but Windows doesn't allow recreating it while this handle is open anyway, // so this would only create confusion (can't lock, but no lock file to read from). const DWORD dwShareMode = FILE_SHARE_READ; +#ifndef Q_OS_WINRT + SECURITY_ATTRIBUTES securityAtts = { sizeof(SECURITY_ATTRIBUTES), NULL, FALSE }; HANDLE fh = CreateFile((const wchar_t*)fileEntry.nativeFilePath().utf16(), GENERIC_WRITE, dwShareMode, @@ -67,6 +68,13 @@ QLockFile::LockError QLockFilePrivate::tryLock_sys() CREATE_NEW, // error if already exists FILE_ATTRIBUTE_NORMAL, NULL); +#else // !Q_OS_WINRT + HANDLE fh = CreateFile2((const wchar_t*)fileEntry.nativeFilePath().utf16(), + GENERIC_WRITE, + dwShareMode, + CREATE_NEW, // error if already exists + NULL); +#endif // Q_OS_WINRT if (fh == INVALID_HANDLE_VALUE) { const DWORD lastError = GetLastError(); switch (lastError) { @@ -112,6 +120,9 @@ bool QLockFilePrivate::isApparentlyStale() const if (!getLockInfo(&pid, &hostname, &appname)) return false; + // On WinRT there seems to be no way of obtaining information about other + // processes due to sandboxing +#ifndef Q_OS_WINRT HANDLE procHandle = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid); if (!procHandle) return true; @@ -120,6 +131,7 @@ bool QLockFilePrivate::isApparentlyStale() const ::CloseHandle(procHandle); if (dwR == WAIT_TIMEOUT) return true; +#endif // !Q_OS_WINRT const qint64 age = QFileInfo(fileName).lastModified().msecsTo(QDateTime::currentDateTime()); return staleLockTime > 0 && age > staleLockTime; } diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp index 35b3ed4e3d..db4612ae33 100644 --- a/src/corelib/io/qsettings.cpp +++ b/src/corelib/io/qsettings.cpp @@ -78,6 +78,17 @@ #ifdef Q_OS_WIN // for homedirpath reading from registry # include <private/qsystemlibrary_p.h> # include <qt_windows.h> +# include <shlobj.h> +#endif + +#ifdef Q_OS_WINRT +#include <wrl.h> +#include <windows.foundation.h> +#include <windows.storage.h> +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Storage; #endif #ifndef CSIDL_COMMON_APPDATA @@ -365,7 +376,7 @@ after_loop: // see also qsettings_win.cpp and qsettings_mac.cpp -#if !defined(Q_OS_WIN) && !defined(Q_OS_MAC) +#if defined(Q_OS_WINRT) || (!defined(Q_OS_WIN) && !defined(Q_OS_MAC)) QSettingsPrivate *QSettingsPrivate::create(QSettings::Format format, QSettings::Scope scope, const QString &organization, const QString &application) { @@ -373,7 +384,7 @@ QSettingsPrivate *QSettingsPrivate::create(QSettings::Format format, QSettings:: } #endif -#if !defined(Q_OS_WIN) +#if defined(Q_OS_WINRT) || !defined(Q_OS_WIN) QSettingsPrivate *QSettingsPrivate::create(const QString &fileName, QSettings::Format format) { return new QConfFileSettingsPrivate(fileName, format); @@ -1021,23 +1032,14 @@ void QConfFileSettingsPrivate::initAccess() sync(); // loads the files the first time } -#ifdef Q_OS_WIN +#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) static QString windowsConfigPath(int type) { QString result; -#ifndef Q_OS_WINCE - QSystemLibrary library(QLatin1String("shell32")); -#else - QSystemLibrary library(QLatin1String("coredll")); -#endif // Q_OS_WINCE - typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, LPWSTR, int, BOOL); - GetSpecialFolderPath SHGetSpecialFolderPath = (GetSpecialFolderPath)library.resolve("SHGetSpecialFolderPathW"); - if (SHGetSpecialFolderPath) { - wchar_t path[MAX_PATH]; - SHGetSpecialFolderPath(0, path, type, false); + wchar_t path[MAX_PATH]; + if (SHGetSpecialFolderPath(0, path, type, false)) result = QString::fromWCharArray(path); - } if (result.isEmpty()) { switch (type) { @@ -1063,7 +1065,40 @@ static QString windowsConfigPath(int type) return result; } -#endif // Q_OS_WIN +#elif defined(Q_OS_WINRT) // Q_OS_WIN && !Q_OS_WINRT +static QString windowsConfigPath(int type) +{ + static QString result; + while (result.isEmpty()) { + ComPtr<IApplicationDataStatics> applicationDataStatics; + if (FAILED(GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_ApplicationData).Get(), &applicationDataStatics))) + return result; + ComPtr<IApplicationData> applicationData; + if (FAILED(applicationDataStatics->get_Current(&applicationData))) + return result; + ComPtr<IStorageFolder> localFolder; + if (FAILED(applicationData->get_LocalFolder(&localFolder))) + return result; + ComPtr<IStorageItem> localFolderItem; + if (FAILED(localFolder.As(&localFolderItem))) + return result; + HSTRING path; + if (FAILED(localFolderItem->get_Path(&path))) + return result; + result = QString::fromWCharArray(WindowsGetStringRawBuffer(path, nullptr)); + } + + switch (type) { + case CSIDL_COMMON_APPDATA: + return result + QLatin1String("\\qt-common"); + case CSIDL_APPDATA: + return result + QLatin1String("\\qt-user"); + default: + break; + } + return result; +} +#endif // Q_OS_WINRT static inline int pathHashKey(QSettings::Format format, QSettings::Scope scope) { @@ -1449,10 +1484,18 @@ void QConfFileSettingsPrivate::syncConfFile(int confFileNo) QString writeSemName = QLatin1String("QSettingsWriteSem "); writeSemName.append(file.fileName()); +#ifndef Q_OS_WINRT writeSemaphore = CreateSemaphore(0, 1, 1, reinterpret_cast<const wchar_t *>(writeSemName.utf16())); +#else + writeSemaphore = CreateSemaphoreEx(0, 1, 1, reinterpret_cast<const wchar_t *>(writeSemName.utf16()), 0, SEMAPHORE_ALL_ACCESS); +#endif if (writeSemaphore) { +#ifndef Q_OS_WINRT WaitForSingleObject(writeSemaphore, INFINITE); +#else + WaitForSingleObjectEx(writeSemaphore, INFINITE, FALSE); +#endif } else { setStatus(QSettings::AccessError); return; @@ -1465,11 +1508,19 @@ void QConfFileSettingsPrivate::syncConfFile(int confFileNo) QString readSemName(QLatin1String("QSettingsReadSem ")); readSemName.append(file.fileName()); +#ifndef Q_OS_WINRT readSemaphore = CreateSemaphore(0, FileLockSemMax, FileLockSemMax, reinterpret_cast<const wchar_t *>(readSemName.utf16())); +#else + readSemaphore = CreateSemaphoreEx(0, FileLockSemMax, FileLockSemMax, reinterpret_cast<const wchar_t *>(readSemName.utf16()), 0, SEMAPHORE_ALL_ACCESS); +#endif if (readSemaphore) { for (int i = 0; i < numReadLocks; ++i) +#ifndef Q_OS_WINRT WaitForSingleObject(readSemaphore, INFINITE); +#else + WaitForSingleObjectEx(readSemaphore, INFINITE, FALSE); +#endif } else { setStatus(QSettings::AccessError); if (writeSemaphore != 0) { diff --git a/src/corelib/io/qstandardpaths.cpp b/src/corelib/io/qstandardpaths.cpp index 2207b8c43e..c145ec4bad 100644 --- a/src/corelib/io/qstandardpaths.cpp +++ b/src/corelib/io/qstandardpaths.cpp @@ -72,34 +72,199 @@ QT_BEGIN_NAMESPACE methods such as QStandardPaths::writableLocation, QStandardPaths::standardLocations, and QStandardPaths::displayName. - \value DesktopLocation Returns the user's desktop directory. - \value DocumentsLocation Returns the user's document. - \value FontsLocation Returns the user's fonts. - \value ApplicationsLocation Returns the user's applications. - \value MusicLocation Returns the user's music. - \value MoviesLocation Returns the user's movies. - \value PicturesLocation Returns the user's pictures. - \value TempLocation Returns the system's temporary directory. - \value HomeLocation Returns the user's home directory. + Some of the values in this enum represent a user configuration. Such enum + values will return the same paths in different applications, so they could + be used to share data with other applications. Other values are specific to + this application. Each enum value in the table below describes whether it's + application-specific or generic. + + Application-specific directories should be assumed to be unreachable by + other applications. Therefore, files placed there might not be readable by + other applications, even if run by the same user. On the other hand, generic + directories should be assumed to be accessible by all applications run by + this user, but should still be assumed to be unreachable by applications by + other users. + + The only exception is QStandardPaths::TempLocation (which is the same as + QDir::tempPath()): the path returned may be application-specific, but files + stored there may be accessed by other applications run by the same user. + + Data interchange with other users is out of the scope of QStandardPaths. + + \value DesktopLocation Returns the user's desktop directory. This is a generic value. + On systems with no concept of a desktop, this is the same as + QStandardPaths::HomeLocation. + \value DocumentsLocation Returns the directory containing user document files. + This is a generic value. The returned path is never empty. + \value FontsLocation Returns the directory containing user's fonts. This is a generic value. + Note that installing fonts may require additional, platform-specific operations. + \value ApplicationsLocation Returns the directory containing the user applications + (either executables, application bundles, or shortcuts to them). This is a generic value. + Note that installing applications may require additional, platform-specific operations. + Files, folders or shortcuts in this directory are platform-specific. + \value MusicLocation Returns the directory containing the user's music or other audio files. + This is a generic value. If no directory specific for music files exists, a sensible + fallback for storing user documents is returned. + \value MoviesLocation Returns the directory containing the user's movies and videos. + This is a generic value. If no directory specific for movie files exists, a sensible + fallback for storing user documents is returned. + \value PicturesLocation Returns the directory containing the user's pictures or photos. + This is a generic value. If no directory specific for picture files exists, a sensible + fallback for storing user documents is returned. + \value TempLocation Returns a directory where temporary files can be stored. The returned value + might be application-specific, shared among other applications for this user, or even + system-wide. The returned path is never empty. + \value HomeLocation Returns the user's home directory (the same as QDir::homePath()). On Unix + systems, this is equal to the HOME environment variable. This value might be + generic or application-specific, but the returned path is never empty. \value DataLocation Returns a directory location where persistent - application data can be stored. QCoreApplication::organizationName - and QCoreApplication::applicationName are appended to the directory location - returned for GenericDataLocation. + application data can be stored. This is an application-specific directory. To obtain a + path to store data to be shared with other applications, use + QStandardPaths::GenericDataLocation. The returned path is never empty. \value CacheLocation Returns a directory location where user-specific - non-essential (cached) data should be written. - \value GenericCacheLocation Returns a directory location where user-specific - non-essential (cached) data, shared across applications, should be written. + non-essential (cached) data should be written. This is an application-specific directory. + The returned path is never empty. + \value GenericCacheLocation Returns a directory location where user-specific non-essential + (cached) data, shared across applications, should be written. This is a generic value. + Note that the returned path may be empty if the system has no concept of shared cache. \value GenericDataLocation Returns a directory location where persistent - data shared across applications can be stored. + data shared across applications can be stored. This is a generic value. The returned + path is never empty. \value RuntimeLocation Returns a directory location where runtime communication - files should be written. For instance unix local sockets. + files should be written, like Unix local sockets. This is a generic value. + The returned path may be empty on some systems. \value ConfigLocation Returns a directory location where user-specific - configuration files should be written. + configuration files should be written. This may be either a generic value + or application-specific, and the returned path is never empty. + \value DownloadLocation Returns a directory for user's downloaded files. This is a generic value. + If no directory specific for downloads exists, a sensible fallback for storing user + documents is returned. \value GenericConfigLocation Returns a directory location where user-specific configuration files shared between multiple applications should be written. This is a generic value and the returned path is never empty. - \value DownloadLocation Returns a directory for user's downloaded files. + The following table gives examples of paths on different operating systems. + The first path is the writable path (unless noted). Other, additional + paths, if any, represent non-writable locations. + + \table + \header \li Path type \li OS X \li Windows + \row \li DesktopLocation + \li "~/Desktop" + \li "C:/Users/<USER>/Desktop" + \row \li DocumentsLocation + \li "~/Documents" + \li "C:/Users/<USER>/Documents" + \row \li FontsLocation + \li "/System/Library/Fonts" (not writable) + \li "C:/Windows/Fonts" (not writable) + \row \li ApplicationsLocation + \li "/Applications" (not writable) + \li "C:/Users/<USER>/AppData/Roaming/Microsoft/Windows/Start Menu/Programs" + \row \li MusicLocation + \li "~/Music" + \li "C:/Users/<USER>/Music" + \row \li MoviesLocation + \li "~/Movies" + \li "C:/Users/<USER>/Videos" + \row \li PicturesLocation + \li "~/Pictures" + \li "C:/Users/<USER>/Pictures" + \row \li TempLocation + \li randomly generated by the OS + \li "C:/Users/<USER>/AppData/Local/Temp" + \row \li HomeLocation + \li "~" + \li "C:/Users/<USER>" + \row \li DataLocation + \li "~/Library/Application Support/<APPNAME>", "/Library/Application Support/<APPNAME>". "<APPDIR>/../Resources" + \li "C:/Users/<USER>/AppData/Local/<APPNAME>", "C:/ProgramData/<APPNAME>", "<APPDIR>", "<APPDIR>/data" + \row \li CacheLocation + \li "~/Library/Caches/<APPNAME>", "/Library/Caches/<APPNAME>" + \li "C:/Users/<USER>/AppData/Local/<APPNAME>/cache" + \row \li GenericDataLocation + \li "~/Library/Application Support", "/Library/Application Support" + \li "C:/Users/<USER>/AppData/Local", "C:/ProgramData" + \row \li RuntimeLocation + \li "~/Library/Application Support" + \li "C:/Users/<USER>" + \row \li ConfigLocation + \li "~/Library/Preferences" + \li "C:/Users/<USER>/AppData/Local/<APPNAME>", "C:/ProgramData/<APPNAME>" + \row \li GenericConfigLocation + \li "~/Library/Preferences" + \li "C:/Users/<USER>/AppData/Local", "C:/ProgramData" + \row \li DownloadLocation + \li "~/Documents" + \li "C:/Users/<USER>/Documents" + \row \li GenericCacheLocation + \li "~/Library/Caches", "/Library/Caches" + \li "C:/Users/<USER>/AppData/Local/cache" + \endtable + + \table + \header \li Path type \li Blackberry \li Linux (including Android) + \row \li DesktopLocation + \li "<APPROOT>/data" + \li "~/Desktop" + \row \li DocumentsLocation + \li "<APPROOT>/shared/documents" + \li "~/Documents" + \row \li FontsLocation + \li "/base/usr/fonts" (not writable) + \li "~/.fonts" + \row \li ApplicationsLocation + \li not supported (directory not readable) + \li "~/.local/share/applications", "/usr/local/share/applications", "/usr/share/applications" + \row \li MusicLocation + \li "<APPROOT>/shared/music" + \li "~/Music" + \row \li MoviesLocation + \li "<APPROOT>/shared/videos" + \li "~/Videos" + \row \li PicturesLocation + \li "<APPROOT>/shared/photos" + \li "~/Pictures" + \row \li TempLocation + \li "/var/tmp" + \li "/tmp" + \row \li HomeLocation + \li "<APPROOT>/data" + \li "~" + \row \li DataLocation + \li "<APPROOT>/data", "<APPROOT>/app/native/assets" + \li "~/.local/share/<APPNAME>", "/usr/local/share/<APPNAME>", "/usr/share/<APPNAME>" + \row \li CacheLocation + \li "<APPROOT>/data/Cache" + \li "~/.cache/<APPNAME>" + \row \li GenericDataLocation + \li "<APPROOT>/shared/misc" + \li "~/.local/share", "/usr/local/share", "/usr/share" + \row \li RuntimeLocation + \li "/var/tmp" + \li "/run/user/<USER>" + \row \li ConfigLocation + \li "<APPROOT>/data/Settings" + \li "~/.config", "/etc/xdg" + \row \li GenericConfigLocation + \li "<APPROOT>/data/Settings" + \li "~/.config", "/etc/xdg" + \row \li DownloadLocation + \li "<APPROOT>/shared/downloads" + \li "~/Downloads" + \row \li GenericCacheLocation + \li "<APPROOT>/data/Cache" (there is no shared cache) + \li "~/.cache" + \endtable + + In the table above, \c <APPNAME> is usually the organization name, the + application name, or both, or a unique name generated at packaging. + Similarly, <APPROOT> is the location where this application is installed + (often a sandbox). <APPDIR> is the directory containing the application + executable. + + The paths above should not be relied upon, as they may change according to + OS configuration, locale, or they may change in future Qt versions. \sa writableLocation(), standardLocations(), displayName(), locate(), locateAll() */ diff --git a/src/corelib/io/qstandardpaths_blackberry.cpp b/src/corelib/io/qstandardpaths_blackberry.cpp index 815756ff9a..ec2e61bd15 100644 --- a/src/corelib/io/qstandardpaths_blackberry.cpp +++ b/src/corelib/io/qstandardpaths_blackberry.cpp @@ -103,10 +103,17 @@ QString QStandardPaths::writableLocation(StandardLocation type) QStringList QStandardPaths::standardLocations(StandardLocation type) { + QStringList dirs; + if (type == FontsLocation) return QStringList(QLatin1String("/base/usr/fonts")); - return QStringList(writableLocation(type)); + if (type == DataLocation) + dirs.append(QDir::homePath() + testModeInsert() + QLatin1String("native/assets")); + + const QString localDir = writableLocation(type); + dirs.prepend(localDir); + return dirs; } QT_END_NAMESPACE diff --git a/src/corelib/io/qstandardpaths_mac.cpp b/src/corelib/io/qstandardpaths_mac.cpp index 0efdfae253..aff9112fb7 100644 --- a/src/corelib/io/qstandardpaths_mac.cpp +++ b/src/corelib/io/qstandardpaths_mac.cpp @@ -47,6 +47,7 @@ #include <qcoreapplication.h> #endif +#include <CoreFoundation/CoreFoundation.h> #include <ApplicationServices/ApplicationServices.h> QT_BEGIN_NAMESPACE @@ -184,6 +185,30 @@ QStringList QStandardPaths::standardLocations(StandardLocation type) dirs.append(path); } + if (type == DataLocation) { + CFBundleRef mainBundle = CFBundleGetMainBundle(); + if (mainBundle) { + CFURLRef bundleUrl = CFBundleCopyBundleURL(mainBundle); + CFStringRef cfBundlePath = CFURLCopyPath(bundleUrl); + QString bundlePath = QCFString::toQString(cfBundlePath); + CFRelease(cfBundlePath); + CFRelease(bundleUrl); + + CFURLRef resourcesUrl = CFBundleCopyResourcesDirectoryURL(mainBundle); + CFStringRef cfResourcesPath = CFURLCopyPath(bundleUrl); + QString resourcesPath = QCFString::toQString(cfResourcesPath); + CFRelease(cfResourcesPath); + CFRelease(resourcesUrl); + + // Handle bundled vs unbundled executables. CFBundleGetMainBundle() returns + // a valid bundle in both cases. CFBundleCopyResourcesDirectoryURL() returns + // an absolute path for unbundled executables. + if (resourcesPath.startsWith(QLatin1Char('/'))) + dirs.append(resourcesPath); + else + dirs.append(bundlePath + resourcesPath); + } + } const QString localDir = writableLocation(type); dirs.prepend(localDir); return dirs; diff --git a/src/corelib/io/qstandardpaths_win.cpp b/src/corelib/io/qstandardpaths_win.cpp index 6a79c7c00b..a0344a0206 100644 --- a/src/corelib/io/qstandardpaths_win.cpp +++ b/src/corelib/io/qstandardpaths_win.cpp @@ -68,21 +68,6 @@ QT_BEGIN_NAMESPACE -typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, LPWSTR, int, BOOL); -static GetSpecialFolderPath resolveGetSpecialFolderPath() -{ - static GetSpecialFolderPath gsfp = 0; - if (!gsfp) { -#ifndef Q_OS_WINCE - QSystemLibrary library(QLatin1String("shell32")); -#else - QSystemLibrary library(QLatin1String("coredll")); -#endif // Q_OS_WINCE - gsfp = (GetSpecialFolderPath)library.resolve("SHGetSpecialFolderPathW"); - } - return gsfp; -} - static QString convertCharArray(const wchar_t *path) { return QDir::fromNativeSeparators(QString::fromWCharArray(path)); @@ -92,10 +77,6 @@ QString QStandardPaths::writableLocation(StandardLocation type) { QString result; - static GetSpecialFolderPath SHGetSpecialFolderPath = resolveGetSpecialFolderPath(); - if (!SHGetSpecialFolderPath) - return QString(); - wchar_t path[MAX_PATH]; switch (type) { @@ -185,8 +166,7 @@ QStringList QStandardPaths::standardLocations(StandardLocation type) // type-specific handling goes here #ifndef Q_OS_WINCE - static GetSpecialFolderPath SHGetSpecialFolderPath = resolveGetSpecialFolderPath(); - if (SHGetSpecialFolderPath) { + { wchar_t path[MAX_PATH]; switch (type) { case ConfigLocation: // same as DataLocation, on Windows (oversight, but too late to fix it) @@ -204,6 +184,12 @@ QStringList QStandardPaths::standardLocations(StandardLocation type) #endif } dirs.append(result); +#ifndef QT_BOOTSTRAPPED + if (type != GenericDataLocation) { + dirs.append(QCoreApplication::applicationDirPath()); + dirs.append(QCoreApplication::applicationDirPath() + QLatin1String("/data")); + } +#endif } break; default: diff --git a/src/corelib/io/qstandardpaths_winrt.cpp b/src/corelib/io/qstandardpaths_winrt.cpp new file mode 100644 index 0000000000..9b6a088a30 --- /dev/null +++ b/src/corelib/io/qstandardpaths_winrt.cpp @@ -0,0 +1,127 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qstandardpaths.h" + +#include <qdir.h> +#include <private/qsystemlibrary_p.h> +#include <qcoreapplication.h> +#include <qstringlist.h> + +#include <qt_windows.h> + +#include <wrl.h> +#include <windows.foundation.h> +#include <windows.storage.h> +#include <Windows.ApplicationModel.h> + +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Storage; +using namespace ABI::Windows::ApplicationModel; + +#ifndef QT_NO_STANDARDPATHS + +QT_BEGIN_NAMESPACE + +static QString convertCharArray(const wchar_t *path) +{ + return QDir::fromNativeSeparators(QString::fromWCharArray(path)); +} + +QString QStandardPaths::writableLocation(StandardLocation type) +{ + QString result; + + switch (type) { + case ConfigLocation: // same as DataLocation, on Windows + case DataLocation: + case GenericDataLocation: { + ComPtr<IApplicationDataStatics> applicationDataStatics; + if (FAILED(GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_ApplicationData).Get(), &applicationDataStatics))) + break; + ComPtr<IApplicationData> applicationData; + if (FAILED(applicationDataStatics->get_Current(&applicationData))) + break; + ComPtr<IStorageFolder> settingsFolder; + if (FAILED(applicationData->get_LocalFolder(&settingsFolder))) + break; + ComPtr<IStorageItem> settingsFolderItem; + if (FAILED(settingsFolder.As(&settingsFolderItem))) + break; + HSTRING path; + if (FAILED(settingsFolderItem->get_Path(&path))) + break; + result = convertCharArray(WindowsGetStringRawBuffer(path, nullptr)); + if (isTestModeEnabled()) + result += QLatin1String("/qttest"); + break; + } + case CacheLocation: + return writableLocation(DataLocation) + QLatin1String("/cache"); + + case GenericCacheLocation: + return writableLocation(GenericDataLocation) + QLatin1String("/cache"); + + case RuntimeLocation: + case HomeLocation: + result = QDir::homePath(); + break; + + case TempLocation: + result = QDir::tempPath(); + break; + default: + Q_UNIMPLEMENTED(); + } + return result; + +} + +QStringList QStandardPaths::standardLocations(StandardLocation type) +{ + return QStringList(writableLocation(type)); +} + +QT_END_NAMESPACE + +#endif // QT_NO_STANDARDPATHS diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp index b3cb4e43f8..b3a17eae7e 100644 --- a/src/corelib/io/qtemporaryfile.cpp +++ b/src/corelib/io/qtemporaryfile.cpp @@ -151,18 +151,27 @@ static bool createFileFromTemplate(NativeFileHandle &file, for (;;) { // Atomically create file and obtain handle #if defined(Q_OS_WIN) +# ifndef Q_OS_WINRT file = CreateFile((const wchar_t *)path.constData(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); +# else // !Q_OS_WINRT + file = CreateFile2((const wchar_t *)path.constData(), + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, CREATE_NEW, + NULL); +# endif // Q_OS_WINRT if (file != INVALID_HANDLE_VALUE) return true; DWORD err = GetLastError(); if (err == ERROR_ACCESS_DENIED) { - DWORD attributes = GetFileAttributes((const wchar_t *)path.constData()); - if (attributes == INVALID_FILE_ATTRIBUTES) { + WIN32_FILE_ATTRIBUTE_DATA attributes; + if (!GetFileAttributesEx((const wchar_t *)path.constData(), + GetFileExInfoStandard, &attributes) + || attributes.dwFileAttributes == INVALID_FILE_ATTRIBUTES) { // Potential write error (read-only parent directory, etc.). error = QSystemError(err, QSystemError::NativeError); return false; @@ -336,7 +345,7 @@ bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode) d->fileEntry = QFileSystemEntry(filename, QFileSystemEntry::FromNativePath()); -#if !defined(Q_OS_WIN) +#if !defined(Q_OS_WIN) || defined(Q_OS_WINRT) d->closeFileHandle = true; #endif diff --git a/src/corelib/io/qurlrecode.cpp b/src/corelib/io/qurlrecode.cpp index 80fc0319fe..74a981b654 100644 --- a/src/corelib/io/qurlrecode.cpp +++ b/src/corelib/io/qurlrecode.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include "qurl.h" +#include "private/qutfcodec_p.h" QT_BEGIN_NAMESPACE @@ -232,110 +233,73 @@ static void ensureDetached(QString &result, ushort *&output, const ushort *begin } } -// returns true if we performed an UTF-8 decoding -static bool encodedUtf8ToUtf16(QString &result, ushort *&output, const ushort *begin, const ushort *&input, - const ushort *end, ushort decoded) +namespace { +struct QUrlUtf8Traits : public QUtf8BaseTraitsNoAscii { - int charsNeeded; - uint min_uc; - uint uc; - - if (decoded <= 0xC1) { - // an UTF-8 first character must be at least 0xC0 - // however, all 0xC0 and 0xC1 first bytes can only produce overlong sequences - return false; - } else if (decoded < 0xe0) { - charsNeeded = 2; - min_uc = 0x80; - uc = decoded & 0x1f; - } else if (decoded < 0xf0) { - charsNeeded = 3; - min_uc = 0x800; - uc = decoded & 0x0f; - } else if (decoded < 0xf5) { - charsNeeded = 4; - min_uc = 0x10000; - uc = decoded & 0x07; - } else { - // the last Unicode character is U+10FFFF - // it's encoded in UTF-8 as "\xF4\x8F\xBF\xBF" - // therefore, a byte higher than 0xF4 is not the UTF-8 first byte - return false; + // override: our "bytes" are three percent-encoded UTF-16 characters + static void appendByte(ushort *&ptr, uchar b) + { + // b >= 0x80, by construction, so percent-encode + *ptr++ = '%'; + *ptr++ = encodeNibble(b >> 4); + *ptr++ = encodeNibble(b & 0xf); } - // are there enough remaining? - if (end - input < 3*charsNeeded) - return false; + static uchar peekByte(const ushort *ptr, int n = 0) + { + // decodePercentEncoding returns ushort(-1) if it can't decode, + // which means we return 0xff, which is not a valid continuation byte. + // If ptr[i * 3] is not '%', we'll multiply by zero and return 0, + // also not a valid continuation byte (if it's '%', we multiply by 1). + return uchar(decodePercentEncoding(ptr + n * 3)) + * uchar(ptr[n * 3] == '%'); + } - if (input[3] != '%') - return false; + static qptrdiff availableBytes(const ushort *ptr, const ushort *end) + { + return (end - ptr) / 3; + } - // first continuation character - decoded = decodePercentEncoding(input + 3); - if ((decoded & 0xc0) != 0x80) - return false; - uc <<= 6; - uc |= decoded & 0x3f; - - if (charsNeeded > 2) { - if (input[6] != '%') - return false; - - // second continuation character - decoded = decodePercentEncoding(input + 6); - if ((decoded & 0xc0) != 0x80) - return false; - uc <<= 6; - uc |= decoded & 0x3f; - - if (charsNeeded > 3) { - if (input[9] != '%') - return false; - - // third continuation character - decoded = decodePercentEncoding(input + 9); - if ((decoded & 0xc0) != 0x80) - return false; - uc <<= 6; - uc |= decoded & 0x3f; - } + static void advanceByte(const ushort *&ptr, int n = 1) + { + ptr += n * 3; } +}; +} - // we've decoded something; safety-check it - if (uc < min_uc) - return false; - if (QChar::isSurrogate(uc) || uc > QChar::LastValidCodePoint) +// returns true if we performed an UTF-8 decoding +static bool encodedUtf8ToUtf16(QString &result, ushort *&output, const ushort *begin, const ushort *&input, + const ushort *end, ushort decoded) +{ + uint ucs4, *dst = &ucs4; + const ushort *src = input + 3;// skip the %XX that yielded \a decoded + int charsNeeded = QUtf8Functions::fromUtf8<QUrlUtf8Traits>(decoded, dst, src, end); + if (charsNeeded < 0) return false; - if (!QChar::requiresSurrogates(uc)) { + if (!QChar::requiresSurrogates(ucs4)) { // UTF-8 decoded and no surrogates are required // detach if necessary - ensureDetached(result, output, begin, input, end, -9 * charsNeeded + 1); - *output++ = uc; + // possibilities are: 6 chars (%XX%XX) -> one char; 9 chars (%XX%XX%XX) -> one char + ensureDetached(result, output, begin, input, end, -3 * charsNeeded + 1); + *output++ = ucs4; } else { // UTF-8 decoded to something that requires a surrogate pair - ensureDetached(result, output, begin, input, end, -9 * charsNeeded + 2); - *output++ = QChar::highSurrogate(uc); - *output++ = QChar::lowSurrogate(uc); + // compressing from %XX%XX%XX%XX (12 chars) to two + ensureDetached(result, output, begin, input, end, -10); + *output++ = QChar::highSurrogate(ucs4); + *output++ = QChar::lowSurrogate(ucs4); } - input += charsNeeded * 3 - 1; + + input = src - 1; return true; } static void unicodeToEncodedUtf8(QString &result, ushort *&output, const ushort *begin, const ushort *&input, const ushort *end, ushort decoded) { - uint uc = decoded; - if (QChar::isHighSurrogate(uc)) { - if (input < end && QChar::isLowSurrogate(input[1])) - uc = QChar::surrogateToUcs4(uc, input[1]); - } - - // note: we will encode bad UTF-16 to UTF-8 - // but they don't get decoded back - - // calculate the utf8 length - int utf8len = uc >= 0x10000 ? 4 : uc >= 0x800 ? 3 : 2; + // calculate the utf8 length and ensure enough space is available + int utf8len = QChar::isHighSurrogate(decoded) ? 4 : decoded >= 0x800 ? 3 : 2; // detach if (!output) { @@ -357,50 +321,32 @@ static void unicodeToEncodedUtf8(QString &result, ushort *&output, const ushort } } - // write the sequence - if (uc < 0x800) { - // first of two bytes - uchar c = 0xc0 | uchar(uc >> 6); + ++input; + int res = QUtf8Functions::toUtf8<QUrlUtf8Traits>(decoded, output, input, end); + --input; + if (res < 0) { + // bad surrogate pair sequence + // we will encode bad UTF-16 to UTF-8 + // but they don't get decoded back + + // first of three bytes + uchar c = 0xe0 | uchar(decoded >> 12); *output++ = '%'; - *output++ = encodeNibble(c >> 4); + *output++ = 'E'; *output++ = encodeNibble(c & 0xf); - } else { - uchar c; - if (uc > 0xFFFF) { - // first two of four bytes - c = 0xf0 | uchar(uc >> 18); - *output++ = '%'; - *output++ = 'F'; - *output++ = encodeNibble(c & 0xf); - // continuation byte - c = 0x80 | (uchar(uc >> 12) & 0x3f); - *output++ = '%'; - *output++ = encodeNibble(c >> 4); - *output++ = encodeNibble(c & 0xf); - - // this was a surrogate pair - ++input; - } else { - // first of three bytes - c = 0xe0 | uchar(uc >> 12); - *output++ = '%'; - *output++ = 'E'; - *output++ = encodeNibble(c & 0xf); - } + // second byte + c = 0x80 | (uchar(decoded >> 6) & 0x3f); + *output++ = '%'; + *output++ = encodeNibble(c >> 4); + *output++ = encodeNibble(c & 0xf); - // continuation byte - c = 0x80 | (uchar(uc >> 6) & 0x3f); + // third byte + c = 0x80 | (decoded & 0x3f); *output++ = '%'; *output++ = encodeNibble(c >> 4); *output++ = encodeNibble(c & 0xf); } - - // continuation byte - uchar c = 0x80 | (uc & 0x3f); - *output++ = '%'; - *output++ = encodeNibble(c >> 4); - *output++ = encodeNibble(c & 0xf); } static int recode(QString &result, const ushort *begin, const ushort *end, QUrl::ComponentFormattingOptions encoding, diff --git a/src/corelib/itemmodels/qitemselectionmodel.cpp b/src/corelib/itemmodels/qitemselectionmodel.cpp index aff9939b87..883aa5b982 100644 --- a/src/corelib/itemmodels/qitemselectionmodel.cpp +++ b/src/corelib/itemmodels/qitemselectionmodel.cpp @@ -1271,9 +1271,8 @@ void QItemSelectionModel::clearCurrentIndex() */ void QItemSelectionModel::reset() { - bool block = blockSignals(true); + const QSignalBlocker blocker(this); clear(); - blockSignals(block); } /*! diff --git a/src/corelib/json/qjsonparser.cpp b/src/corelib/json/qjsonparser.cpp index 516c53775c..0c61718843 100644 --- a/src/corelib/json/qjsonparser.cpp +++ b/src/corelib/json/qjsonparser.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2013 Intel Corporation ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -45,6 +46,7 @@ #include <qdebug.h> #include "qjsonparser_p.h" #include "qjson_p.h" +#include "private/qutfcodec_p.h" //#define PARSER_DEBUG #ifdef PARSER_DEBUG @@ -820,45 +822,16 @@ static inline bool scanEscapeSequence(const char *&json, const char *end, uint * static inline bool scanUtf8Char(const char *&json, const char *end, uint *result) { - int need; - uint min_uc; - uint uc; - uchar ch = *json++; - if (ch < 128) { - *result = ch; - return true; - } else if ((ch & 0xe0) == 0xc0) { - uc = ch & 0x1f; - need = 1; - min_uc = 0x80; - } else if ((ch & 0xf0) == 0xe0) { - uc = ch & 0x0f; - need = 2; - min_uc = 0x800; - } else if ((ch&0xf8) == 0xf0) { - uc = ch & 0x07; - need = 3; - min_uc = 0x10000; - } else { - return false; - } - - if (json >= end - need) - return false; - - for (int i = 0; i < need; ++i) { - ch = *json++; - if ((ch&0xc0) != 0x80) - return false; - uc = (uc << 6) | (ch & 0x3f); - } - - if (uc < min_uc || - QChar::isSurrogate(uc) || uc > QChar::LastValidCodePoint) { + const uchar *&src = reinterpret_cast<const uchar *&>(json); + const uchar *uend = reinterpret_cast<const uchar *>(end); + uchar b = *src++; + int res = QUtf8Functions::fromUtf8<QUtf8BaseTraits>(b, result, src, uend); + if (res < 0) { + // decoding error, backtrack the character we read above + --json; return false; } - *result = uc; return true; } diff --git a/src/corelib/json/qjsonwriter.cpp b/src/corelib/json/qjsonwriter.cpp index 86cca4bb26..5defd497b1 100644 --- a/src/corelib/json/qjsonwriter.cpp +++ b/src/corelib/json/qjsonwriter.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2013 Intel Corporation ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -41,6 +42,7 @@ #include "qjsonwriter_p.h" #include "qjson_p.h" +#include "private/qutfcodec_p.h" QT_BEGIN_NAMESPACE @@ -59,15 +61,12 @@ static QByteArray escapedString(const QString &s) const uchar replacement = '?'; QByteArray ba(s.length(), Qt::Uninitialized); - uchar *cursor = (uchar *)ba.data(); + uchar *cursor = reinterpret_cast<uchar *>(const_cast<char *>(ba.constData())); const uchar *ba_end = cursor + ba.length(); + const ushort *src = reinterpret_cast<const ushort *>(s.constBegin()); + const ushort *const end = reinterpret_cast<const ushort *>(s.constEnd()); - const QChar *ch = (const QChar *)s.constData(); - const QChar *end = ch + s.length(); - - int surrogate_high = -1; - - while (ch < end) { + while (src != end) { if (cursor >= ba_end - 6) { // ensure we have enough space int pos = cursor - (const uchar *)ba.constData(); @@ -76,29 +75,7 @@ static QByteArray escapedString(const QString &s) ba_end = (const uchar *)ba.constData() + ba.length(); } - uint u = ch->unicode(); - if (surrogate_high >= 0) { - if (ch->isLowSurrogate()) { - u = QChar::surrogateToUcs4(surrogate_high, u); - surrogate_high = -1; - } else { - // high surrogate without low - *cursor = replacement; - ++ch; - surrogate_high = -1; - continue; - } - } else if (ch->isLowSurrogate()) { - // low surrogate without high - *cursor = replacement; - ++ch; - continue; - } else if (ch->isHighSurrogate()) { - surrogate_high = u; - ++ch; - continue; - } - + uint u = *src++; if (u < 0x80) { if (u < 0x20 || u == 0x22 || u == 0x5c) { *cursor++ = '\\'; @@ -135,20 +112,9 @@ static QByteArray escapedString(const QString &s) *cursor++ = (uchar)u; } } else { - if (u < 0x0800) { - *cursor++ = 0xc0 | ((uchar) (u >> 6)); - } else { - if (QChar::requiresSurrogates(u)) { - *cursor++ = 0xf0 | ((uchar) (u >> 18)); - *cursor++ = 0x80 | (((uchar) (u >> 12)) & 0x3f); - } else { - *cursor++ = 0xe0 | (((uchar) (u >> 12)) & 0x3f); - } - *cursor++ = 0x80 | (((uchar) (u >> 6)) & 0x3f); - } - *cursor++ = 0x80 | ((uchar) (u&0x3f)); + if (QUtf8Functions::toUtf8<QUtf8BaseTraits>(u, cursor, src, end) < 0) + *cursor++ = replacement; } - ++ch; } ba.resize(cursor - (const uchar *)ba.constData()); diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri index 7625a74381..4c43f292fb 100644 --- a/src/corelib/kernel/kernel.pri +++ b/src/corelib/kernel/kernel.pri @@ -68,16 +68,21 @@ SOURCES += \ win32 { SOURCES += \ - kernel/qeventdispatcher_win.cpp \ kernel/qcoreapplication_win.cpp \ kernel/qwineventnotifier.cpp \ kernel/qsharedmemory_win.cpp \ kernel/qsystemsemaphore_win.cpp HEADERS += \ - kernel/qeventdispatcher_win_p.h \ kernel/qwineventnotifier.h -} + winrt { + SOURCES += kernel/qeventdispatcher_winrt.cpp + HEADERS += kernel/qeventdispatcher_winrt_p.h + } else { + SOURCES += kernel/qeventdispatcher_win.cpp + HEADERS += kernel/qeventdispatcher_win_p.h + } +} wince*: { SOURCES += \ @@ -86,6 +91,13 @@ wince*: { kernel/qfunctions_wince.h } +winrt { + SOURCES += \ + kernel/qfunctions_winrt.cpp + HEADERS += \ + kernel/qfunctions_winrt.h +} + mac { SOURCES += \ kernel/qcoreapplication_mac.cpp diff --git a/src/corelib/kernel/qcore_unix_p.h b/src/corelib/kernel/qcore_unix_p.h index 8c0589fdc6..7ab632d7a0 100644 --- a/src/corelib/kernel/qcore_unix_p.h +++ b/src/corelib/kernel/qcore_unix_p.h @@ -117,6 +117,8 @@ inline bool operator<(const timespec &t1, const timespec &t2) { return t1.tv_sec < t2.tv_sec || (t1.tv_sec == t2.tv_sec && t1.tv_nsec < t2.tv_nsec); } inline bool operator==(const timespec &t1, const timespec &t2) { return t1.tv_sec == t2.tv_sec && t1.tv_nsec == t2.tv_nsec; } +inline bool operator!=(const timespec &t1, const timespec &t2) +{ return !(t1 == t2); } inline timespec &operator+=(timespec &t1, const timespec &t2) { t1.tv_sec += t2.tv_sec; diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index e77d6894d0..2dd56423ac 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -85,7 +85,11 @@ # endif #endif #ifdef Q_OS_WIN +# ifdef Q_OS_WINRT +# include "qeventdispatcher_winrt_p.h" +# else # include "qeventdispatcher_win_p.h" +# endif #endif #endif // QT_NO_QOBJECT @@ -98,6 +102,7 @@ #ifdef Q_OS_UNIX # include <locale.h> # include <unistd.h> +# include <sys/types.h> #endif #ifdef Q_OS_VXWORKS @@ -134,6 +139,8 @@ extern QString qAppFileName(); #endif int QCoreApplicationPrivate::app_compile_version = 0x050000; //we don't know exactly, but it's at least 5.0.0 +bool QCoreApplicationPrivate::setuidAllowed = false; + #if !defined(Q_OS_WIN) #ifdef Q_OS_MAC QString QCoreApplicationPrivate::macMenuBarName() @@ -410,6 +417,11 @@ QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint QCoreApplicationPrivate::is_app_closing = false; # if defined(Q_OS_UNIX) + if (!setuidAllowed && (geteuid() != getuid())) + qFatal("FATAL: The application binary appears to be running setuid, this is a security hole."); +# endif // Q_OS_UNIX + +# if defined(Q_OS_UNIX) qt_application_thread_id = QThread::currentThreadId(); # endif @@ -471,6 +483,8 @@ void QCoreApplicationPrivate::createEventDispatcher() # endif eventDispatcher = new QEventDispatcherUNIX(q); # endif +#elif defined(Q_OS_WINRT) + eventDispatcher = new QEventDispatcherWinRT(q); #elif defined(Q_OS_WIN) eventDispatcher = new QEventDispatcherWin32(q); #else @@ -518,6 +532,10 @@ void QCoreApplicationPrivate::appendApplicationPathToLibraryPaths() coreappdata()->app_libpaths = app_libpaths = new QStringList; QString app_location = QCoreApplication::applicationFilePath(); app_location.truncate(app_location.lastIndexOf(QLatin1Char('/'))); +#ifdef Q_OS_WINRT + if (app_location.isEmpty()) + app_location.append(QLatin1Char('/')); +#endif app_location = QDir(app_location).canonicalPath(); if (QFile::exists(app_location) && !app_libpaths->contains(app_location)) app_libpaths->append(app_location); @@ -786,6 +804,44 @@ QCoreApplication::~QCoreApplication() #endif } +/*! + \since 5.3 + + Allows the application to run setuid on UNIX platforms if \a allow + is true. + + If \a allow is false (the default) and Qt detects the application is + running with an effective user id different than the real user id, + the application will be aborted when a QCoreApplication instance is + created. + + Qt is not an appropriate solution for setuid programs due to its + large attack surface. However some applications may be required + to run in this manner for historical reasons. This flag will + prevent Qt from aborting the application when this is detected, + and must be set before a QCoreApplication instance is created. + + \note It is strongly recommended not to enable this option since + it introduces security risks. +*/ +void QCoreApplication::setSetuidAllowed(bool allow) +{ + QCoreApplicationPrivate::setuidAllowed = allow; +} + +/*! + \since 5.3 + + Returns true if the application is allowed to run setuid on UNIX + platforms. + + \sa QCoreApplication::setSetuidAllowed() +*/ +bool QCoreApplication::isSetuidAllowed() +{ + return QCoreApplicationPrivate::setuidAllowed; +} + /*! Sets the attribute \a attribute if \a on is true; diff --git a/src/corelib/kernel/qcoreapplication.h b/src/corelib/kernel/qcoreapplication.h index ae17aeec0e..c2843030fd 100644 --- a/src/corelib/kernel/qcoreapplication.h +++ b/src/corelib/kernel/qcoreapplication.h @@ -112,6 +112,9 @@ public: static void setApplicationVersion(const QString &version); static QString applicationVersion(); + static void setSetuidAllowed(bool allow); + static bool isSetuidAllowed(); + static QCoreApplication *instance() { return self; } #ifndef QT_NO_QOBJECT diff --git a/src/corelib/kernel/qcoreapplication_p.h b/src/corelib/kernel/qcoreapplication_p.h index 0c00f396b5..c3d83112ae 100644 --- a/src/corelib/kernel/qcoreapplication_p.h +++ b/src/corelib/kernel/qcoreapplication_p.h @@ -153,6 +153,7 @@ public: static bool is_app_closing; #endif + static bool setuidAllowed; static uint attribs; static inline bool testAttribute(uint flag) { return attribs & (1 << flag); } static int app_compile_version; diff --git a/src/corelib/kernel/qeventdispatcher_glib_p.h b/src/corelib/kernel/qeventdispatcher_glib_p.h index 933faff5a5..a2e7b6b33e 100644 --- a/src/corelib/kernel/qeventdispatcher_glib_p.h +++ b/src/corelib/kernel/qeventdispatcher_glib_p.h @@ -77,19 +77,19 @@ public: bool processEvents(QEventLoop::ProcessEventsFlags flags); bool hasPendingEvents(); - void registerSocketNotifier(QSocketNotifier *socketNotifier); - void unregisterSocketNotifier(QSocketNotifier *socketNotifier); + void registerSocketNotifier(QSocketNotifier *socketNotifier) Q_DECL_FINAL; + void unregisterSocketNotifier(QSocketNotifier *socketNotifier) Q_DECL_FINAL; - void registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object); - bool unregisterTimer(int timerId); - bool unregisterTimers(QObject *object); - QList<TimerInfo> registeredTimers(QObject *object) const; + void registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object) Q_DECL_FINAL; + bool unregisterTimer(int timerId) Q_DECL_FINAL; + bool unregisterTimers(QObject *object) Q_DECL_FINAL; + QList<TimerInfo> registeredTimers(QObject *object) const Q_DECL_FINAL; - int remainingTime(int timerId); + int remainingTime(int timerId) Q_DECL_FINAL; - void wakeUp(); - void interrupt(); - void flush(); + void wakeUp() Q_DECL_FINAL; + void interrupt() Q_DECL_FINAL; + void flush() Q_DECL_FINAL; static bool versionSupported(); diff --git a/src/corelib/kernel/qeventdispatcher_unix_p.h b/src/corelib/kernel/qeventdispatcher_unix_p.h index 5d69d5e396..242aa9e695 100644 --- a/src/corelib/kernel/qeventdispatcher_unix_p.h +++ b/src/corelib/kernel/qeventdispatcher_unix_p.h @@ -94,6 +94,12 @@ public: class QEventDispatcherUNIXPrivate; +#ifdef Q_OS_QNX +# define FINAL_EXCEPT_BLACKBERRY +#else +# define FINAL_EXCEPT_BLACKBERRY Q_DECL_FINAL +#endif + class Q_CORE_EXPORT QEventDispatcherUNIX : public QAbstractEventDispatcher { Q_OBJECT @@ -106,18 +112,18 @@ public: bool processEvents(QEventLoop::ProcessEventsFlags flags); bool hasPendingEvents(); - void registerSocketNotifier(QSocketNotifier *notifier); - void unregisterSocketNotifier(QSocketNotifier *notifier); + void registerSocketNotifier(QSocketNotifier *notifier) FINAL_EXCEPT_BLACKBERRY; + void unregisterSocketNotifier(QSocketNotifier *notifier) FINAL_EXCEPT_BLACKBERRY; - void registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object); - bool unregisterTimer(int timerId); - bool unregisterTimers(QObject *object); - QList<TimerInfo> registeredTimers(QObject *object) const; + void registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object) Q_DECL_FINAL; + bool unregisterTimer(int timerId) Q_DECL_FINAL; + bool unregisterTimers(QObject *object) Q_DECL_FINAL; + QList<TimerInfo> registeredTimers(QObject *object) const Q_DECL_FINAL; - int remainingTime(int timerId); + int remainingTime(int timerId) Q_DECL_FINAL; - void wakeUp(); - void interrupt(); + void wakeUp() FINAL_EXCEPT_BLACKBERRY; + void interrupt() Q_DECL_FINAL; void flush(); protected: @@ -130,7 +136,7 @@ protected: virtual int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, - timespec *timeout); + timespec *timeout) Q_DECL_FINAL; }; class Q_CORE_EXPORT QEventDispatcherUNIXPrivate : public QAbstractEventDispatcherPrivate @@ -142,8 +148,8 @@ public: ~QEventDispatcherUNIXPrivate(); int doSelect(QEventLoop::ProcessEventsFlags flags, timespec *timeout); - virtual int initThreadWakeUp(); - virtual int processThreadWakeUp(int nsel); + virtual int initThreadWakeUp() FINAL_EXCEPT_BLACKBERRY; + virtual int processThreadWakeUp(int nsel) FINAL_EXCEPT_BLACKBERRY; bool mainThread; @@ -165,6 +171,8 @@ public: QAtomicInt interrupt; // bool }; +#undef FINAL_EXCEPT_BLACKBERRY + QT_END_NAMESPACE #endif // QEVENTDISPATCHER_UNIX_P_H diff --git a/src/corelib/kernel/qeventdispatcher_winrt.cpp b/src/corelib/kernel/qeventdispatcher_winrt.cpp new file mode 100644 index 0000000000..8639e925cd --- /dev/null +++ b/src/corelib/kernel/qeventdispatcher_winrt.cpp @@ -0,0 +1,402 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qeventdispatcher_winrt_p.h" + +#include <QtCore/QCoreApplication> +#include <QtCore/QThread> +#include <QtCore/QHash> + +#include <private/qcoreapplication_p.h> +#include <private/qthread_p.h> +#include <private/qabstracteventdispatcher_p.h> + +#include <wrl.h> +#include <windows.foundation.h> +#include <windows.system.threading.h> +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows::System::Threading; +using namespace ABI::Windows::Foundation; + +QT_BEGIN_NAMESPACE + +class QZeroTimerEvent : public QTimerEvent +{ +public: + explicit inline QZeroTimerEvent(int timerId) + : QTimerEvent(timerId) + { t = QEvent::ZeroTimerEvent; } +}; + +struct WinRTTimerInfo // internal timer info +{ + WinRTTimerInfo() : timer(0) {} + + int id; + int interval; + Qt::TimerType timerType; + quint64 timeout; // - when to actually fire + QObject *obj; // - object to receive events + bool inTimerEvent; + ComPtr<IThreadPoolTimer> timer; +}; + +class QEventDispatcherWinRTPrivate : public QAbstractEventDispatcherPrivate +{ + Q_DECLARE_PUBLIC(QEventDispatcherWinRT) + +public: + QEventDispatcherWinRTPrivate(); + ~QEventDispatcherWinRTPrivate(); + + void registerTimer(WinRTTimerInfo *t); + void unregisterTimer(WinRTTimerInfo *t); + void sendTimerEvent(int timerId); + + +private: + static HRESULT timerExpiredCallback(ABI::Windows::System::Threading::IThreadPoolTimer *source); + static int idForTimer(IThreadPoolTimer *timer) + { + QAbstractEventDispatcher *eventDispatcher = QCoreApplication::eventDispatcher(); + if (!eventDispatcher) + return -1; + if (QEventDispatcherWinRTPrivate *that = static_cast<QEventDispatcherWinRTPrivate *>(get(eventDispatcher))) + return that->timerIds.value(timer, -1); + return -1; + } + + QHash<int, WinRTTimerInfo*> timerDict; + QHash<IThreadPoolTimer *, int> timerIds; + + ComPtr<IThreadPoolTimerStatics> timerFactory; +}; + +QEventDispatcherWinRT::QEventDispatcherWinRT(QObject *parent) + : QAbstractEventDispatcher(*new QEventDispatcherWinRTPrivate, parent) +{ +} + +QEventDispatcherWinRT::QEventDispatcherWinRT(QEventDispatcherWinRTPrivate &dd, QObject *parent) + : QAbstractEventDispatcher(dd, parent) +{ } + +QEventDispatcherWinRT::~QEventDispatcherWinRT() +{ +} + +bool QEventDispatcherWinRT::processEvents(QEventLoop::ProcessEventsFlags flags) +{ + Q_UNUSED(flags); + + // we are awake, broadcast it + emit awake(); + QCoreApplicationPrivate::sendPostedEvents(0, 0, QThreadData::current()); + + return false; +} + +bool QEventDispatcherWinRT::hasPendingEvents() +{ + return qGlobalPostedEventsCount(); +} + +void QEventDispatcherWinRT::registerSocketNotifier(QSocketNotifier *notifier) +{ + Q_UNUSED(notifier); + Q_UNIMPLEMENTED(); +} +void QEventDispatcherWinRT::unregisterSocketNotifier(QSocketNotifier *notifier) +{ + Q_UNUSED(notifier); + Q_UNIMPLEMENTED(); +} + +void QEventDispatcherWinRT::registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object) +{ + Q_UNUSED(timerType); + + if (timerId < 1 || interval < 0 || !object) { + qWarning("QEventDispatcherWinRT::registerTimer: invalid arguments"); + return; + } else if (object->thread() != thread() || thread() != QThread::currentThread()) { + qWarning("QObject::startTimer: timers cannot be started from another thread"); + return; + } + + Q_D(QEventDispatcherWinRT); + WinRTTimerInfo *t = new WinRTTimerInfo(); + t->id = timerId; + t->interval = interval; + t->timerType = timerType; + t->obj = object; + t->inTimerEvent = false; + + d->registerTimer(t); + d->timerDict.insert(t->id, t); +} + +bool QEventDispatcherWinRT::unregisterTimer(int timerId) +{ + if (timerId < 1) { + qWarning("QEventDispatcherWinRT::unregisterTimer: invalid argument"); + return false; + } + if (thread() != QThread::currentThread()) { + qWarning("QObject::killTimer: timers cannot be stopped from another thread"); + return false; + } + + Q_D(QEventDispatcherWinRT); + + WinRTTimerInfo *t = d->timerDict.value(timerId); + if (!t) + return false; + + d->unregisterTimer(t); + return true; +} + +bool QEventDispatcherWinRT::unregisterTimers(QObject *object) +{ + if (!object) { + qWarning("QEventDispatcherWinRT::unregisterTimers: invalid argument"); + return false; + } + QThread *currentThread = QThread::currentThread(); + if (object->thread() != thread() || thread() != currentThread) { + qWarning("QObject::killTimers: timers cannot be stopped from another thread"); + return false; + } + + Q_D(QEventDispatcherWinRT); + foreach (WinRTTimerInfo *t, d->timerDict) { + if (t->obj == object) + d->unregisterTimer(t); + } + return true; +} + +QList<QAbstractEventDispatcher::TimerInfo> QEventDispatcherWinRT::registeredTimers(QObject *object) const +{ + if (!object) { + qWarning("QEventDispatcherWinRT:registeredTimers: invalid argument"); + return QList<TimerInfo>(); + } + + Q_D(const QEventDispatcherWinRT); + QList<TimerInfo> list; + foreach (const WinRTTimerInfo *t, d->timerDict) { + if (t->obj == object) + list.append(TimerInfo(t->id, t->interval, t->timerType)); + } + return list; +} + +bool QEventDispatcherWinRT::registerEventNotifier(QWinEventNotifier *notifier) +{ + Q_UNUSED(notifier); + Q_UNIMPLEMENTED(); + return false; +} + +void QEventDispatcherWinRT::unregisterEventNotifier(QWinEventNotifier *notifier) +{ + Q_UNUSED(notifier); + Q_UNIMPLEMENTED(); +} + +int QEventDispatcherWinRT::remainingTime(int timerId) +{ +#ifndef QT_NO_DEBUG + if (timerId < 1) { + qWarning("QEventDispatcherWinRT::remainingTime: invalid argument"); + return -1; + } +#endif + + Q_D(QEventDispatcherWinRT); + if (WinRTTimerInfo *t = d->timerDict.value(timerId)) { + const quint64 currentTime = qt_msectime(); + if (currentTime < t->timeout) { + // time to wait + return t->timeout - currentTime; + } else { + return 0; + } + } + +#ifndef QT_NO_DEBUG + qWarning("QEventDispatcherWinRT::remainingTime: timer id %d not found", timerId); +#endif + return -1; +} + +void QEventDispatcherWinRT::wakeUp() +{ +} + +void QEventDispatcherWinRT::interrupt() +{ +} + +void QEventDispatcherWinRT::flush() +{ +} + +void QEventDispatcherWinRT::startingUp() +{ +} + +void QEventDispatcherWinRT::closingDown() +{ + Q_D(QEventDispatcherWinRT); + foreach (WinRTTimerInfo *t, d->timerDict) + d->unregisterTimer(t); + d->timerDict.clear(); + d->timerIds.clear(); +} + +bool QEventDispatcherWinRT::event(QEvent *e) +{ + Q_D(QEventDispatcherWinRT); + if (e->type() == QEvent::ZeroTimerEvent) { + QZeroTimerEvent *zte = static_cast<QZeroTimerEvent*>(e); + WinRTTimerInfo *t = d->timerDict.value(zte->timerId()); + if (t) { + t->inTimerEvent = true; + + QTimerEvent te(zte->timerId()); + QCoreApplication::sendEvent(t->obj, &te); + + t = d->timerDict.value(zte->timerId()); + if (t) { + if (t->interval == 0 && t->inTimerEvent) { + // post the next zero timer event as long as the timer was not restarted + QCoreApplication::postEvent(this, new QZeroTimerEvent(zte->timerId())); + } + + t->inTimerEvent = false; + } + } + return true; + } else if (e->type() == QEvent::Timer) { + QTimerEvent *te = static_cast<QTimerEvent*>(e); + d->sendTimerEvent(te->timerId()); + } + return QAbstractEventDispatcher::event(e); +} + +QEventDispatcherWinRTPrivate::QEventDispatcherWinRTPrivate() +{ + CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + HRESULT hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_System_Threading_ThreadPoolTimer).Get(), &timerFactory); + if (FAILED(hr)) + qWarning("QEventDispatcherWinRTPrivate::QEventDispatcherWinRTPrivate: Could not obtain timer factory: %lx", hr); +} + +QEventDispatcherWinRTPrivate::~QEventDispatcherWinRTPrivate() +{ + CoUninitialize(); +} + +void QEventDispatcherWinRTPrivate::registerTimer(WinRTTimerInfo *t) +{ + Q_Q(QEventDispatcherWinRT); + + bool ok = false; + uint interval = t->interval; + if (interval == 0u) { + // optimization for single-shot-zero-timer + QCoreApplication::postEvent(q, new QZeroTimerEvent(t->id)); + ok = true; + } else { + TimeSpan period; + period.Duration = interval * 10000; // TimeSpan is based on 100-nanosecond units + ok = SUCCEEDED(timerFactory->CreatePeriodicTimer( + Callback<ITimerElapsedHandler>(&QEventDispatcherWinRTPrivate::timerExpiredCallback).Get(), period, &t->timer)); + if (ok) + timerIds.insert(t->timer.Get(), t->id); + } + t->timeout = qt_msectime() + interval; + if (!ok) + qErrnoWarning("QEventDispatcherWinRT::registerTimer: Failed to create a timer"); +} + +void QEventDispatcherWinRTPrivate::unregisterTimer(WinRTTimerInfo *t) +{ + if (t->timer) { + t->timer->Cancel(); + timerIds.remove(t->timer.Get()); + } + timerDict.remove(t->id); + delete t; +} + +void QEventDispatcherWinRTPrivate::sendTimerEvent(int timerId) +{ + WinRTTimerInfo *t = timerDict.value(timerId); + if (t && !t->inTimerEvent) { + // send event, but don't allow it to recurse + t->inTimerEvent = true; + + QTimerEvent e(t->id); + QCoreApplication::sendEvent(t->obj, &e); + + // timer could have been removed + t = timerDict.value(timerId); + if (t) + t->inTimerEvent = false; + } +} + +HRESULT QEventDispatcherWinRTPrivate::timerExpiredCallback(IThreadPoolTimer *source) +{ + int timerId = idForTimer(source); + if (timerId > 0) + QCoreApplication::postEvent(QCoreApplication::eventDispatcher(), new QTimerEvent(timerId)); + else + qWarning("QEventDispatcherWinRT::timerExpiredCallback: Could not find timer %d in timer list", source); + return S_OK; +} + +QT_END_NAMESPACE diff --git a/src/corelib/kernel/qeventdispatcher_winrt_p.h b/src/corelib/kernel/qeventdispatcher_winrt_p.h new file mode 100644 index 0000000000..0631b2ea33 --- /dev/null +++ b/src/corelib/kernel/qeventdispatcher_winrt_p.h @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QEVENTDISPATCHER_WINRT_P_H +#define QEVENTDISPATCHER_WINRT_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 "QtCore/qabstracteventdispatcher.h" + +#include <qt_windows.h> + +QT_BEGIN_NAMESPACE + +int qt_msectime(); + +class QEventDispatcherWinRTPrivate; + +class Q_CORE_EXPORT QEventDispatcherWinRT : public QAbstractEventDispatcher +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QEventDispatcherWinRT) + +public: + explicit QEventDispatcherWinRT(QObject *parent = 0); + ~QEventDispatcherWinRT(); + + bool processEvents(QEventLoop::ProcessEventsFlags flags); + bool hasPendingEvents(); + + void registerSocketNotifier(QSocketNotifier *notifier); + void unregisterSocketNotifier(QSocketNotifier *notifier); + + void registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object); + bool unregisterTimer(int timerId); + bool unregisterTimers(QObject *object); + QList<TimerInfo> registeredTimers(QObject *object) const; + + int remainingTime(int timerId); + + bool registerEventNotifier(QWinEventNotifier *notifier); + void unregisterEventNotifier(QWinEventNotifier *notifier); + + void wakeUp(); + void interrupt(); + void flush(); + + void startingUp(); + void closingDown(); + +protected: + QEventDispatcherWinRT(QEventDispatcherWinRTPrivate &dd, QObject *parent = 0); + + bool event(QEvent *); + int activateTimers(); +}; + +QT_END_NAMESPACE + +#endif // QEVENTDISPATCHER_WINRT_P_H diff --git a/src/corelib/kernel/qfunctions_p.h b/src/corelib/kernel/qfunctions_p.h index 6e094f1ed3..e3014a0dcf 100644 --- a/src/corelib/kernel/qfunctions_p.h +++ b/src/corelib/kernel/qfunctions_p.h @@ -61,6 +61,8 @@ # include "QtCore/qfunctions_vxworks.h" #elif defined(Q_OS_NACL) # include "QtCore/qfunctions_nacl.h" +#elif defined(Q_OS_WINRT) +# include "QtCore/qfunctions_winrt.h" #endif #ifdef Q_CC_RVCT diff --git a/src/corelib/kernel/qfunctions_winrt.cpp b/src/corelib/kernel/qfunctions_winrt.cpp new file mode 100644 index 0000000000..1348af2acb --- /dev/null +++ b/src/corelib/kernel/qfunctions_winrt.cpp @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifdef Q_OS_WINRT + +#include "qfunctions_winrt.h" +#include "qstring.h" +#include "qbytearray.h" +#include "qhash.h" + +QT_USE_NAMESPACE + +// Environment ------------------------------------------------------ +inline QHash<QByteArray, QByteArray> &qt_app_environment() +{ + static QHash<QByteArray, QByteArray> internalEnvironment; + return internalEnvironment; +} + +errno_t qt_winrt_getenv_s(size_t* sizeNeeded, char* buffer, size_t bufferSize, const char* varName) +{ + if (!sizeNeeded) + return EINVAL; + + if (!qt_app_environment().contains(varName)) { + if (buffer) + buffer[0] = '\0'; + return ENOENT; + } + + QByteArray value = qt_app_environment().value(varName); + if (!value.endsWith('\0')) // win32 guarantees terminated string + value.append('\0'); + + if (bufferSize < (size_t)value.size()) { + *sizeNeeded = value.size(); + return ERANGE; + } + + strcpy(buffer, value.constData()); + return 0; +} + +errno_t qt_winrt__putenv_s(const char* varName, const char* value) +{ + QByteArray input = value; + if (input.isEmpty()) { + if (qt_app_environment().contains(varName)) + qt_app_environment().remove(varName); + } else { + // win32 on winrt guarantees terminated string + if (!input.endsWith('\0')) + input.append('\0'); + qt_app_environment()[varName] = input; + } + + return 0; +} + +void qt_winrt_tzset() +{ +} + +void qt_winrt__tzset() +{ +} + +#endif // Q_OS_WINRT diff --git a/src/corelib/kernel/qfunctions_winrt.h b/src/corelib/kernel/qfunctions_winrt.h new file mode 100644 index 0000000000..fa2b2e12ff --- /dev/null +++ b/src/corelib/kernel/qfunctions_winrt.h @@ -0,0 +1,122 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QFUNCTIONS_WINRT_H +#define QFUNCTIONS_WINRT_H + +#include <QtCore/qglobal.h> + +#ifdef Q_OS_WINRT + +QT_BEGIN_NAMESPACE + +#ifdef QT_BUILD_CORE_LIB +#endif + +QT_END_NAMESPACE + +// Environment ------------------------------------------------------ +errno_t qt_winrt_getenv_s(size_t*, char*, size_t, const char*); +errno_t qt_winrt__putenv_s(const char*, const char*); +void qt_winrt_tzset(); +void qt_winrt__tzset(); + +// As Windows Runtime lacks some standard functions used in Qt, these got +// reimplemented. Other projects do this as well. Inline functions are used +// that there is a central place to disable functions for newer versions if +// they get available. There are no defines used anymore, because this +// will break member functions of classes which are called like these +// functions. +// The other declarations available in this file are being used per +// define inside qplatformdefs.h of the corresponding WinRT mkspec. + +#define generate_inline_return_func0(funcname, returntype) \ + inline returntype funcname() \ + { \ + return qt_winrt_##funcname(); \ + } +#define generate_inline_return_func1(funcname, returntype, param1) \ + inline returntype funcname(param1 p1) \ + { \ + return qt_winrt_##funcname(p1); \ + } +#define generate_inline_return_func2(funcname, returntype, param1, param2) \ + inline returntype funcname(param1 p1, param2 p2) \ + { \ + return qt_winrt_##funcname(p1, p2); \ + } +#define generate_inline_return_func3(funcname, returntype, param1, param2, param3) \ + inline returntype funcname(param1 p1, param2 p2, param3 p3) \ + { \ + return qt_winrt_##funcname(p1, p2, p3); \ + } +#define generate_inline_return_func4(funcname, returntype, param1, param2, param3, param4) \ + inline returntype funcname(param1 p1, param2 p2, param3 p3, param4 p4) \ + { \ + return qt_winrt_##funcname(p1, p2, p3, p4); \ + } +#define generate_inline_return_func5(funcname, returntype, param1, param2, param3, param4, param5) \ + inline returntype funcname(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5) \ + { \ + return qt_winrt_##funcname(p1, p2, p3, p4, p5); \ + } +#define generate_inline_return_func6(funcname, returntype, param1, param2, param3, param4, param5, param6) \ + inline returntype funcname(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6) \ + { \ + return qt_winrt_##funcname(p1, p2, p3, p4, p5, p6); \ + } +#define generate_inline_return_func7(funcname, returntype, param1, param2, param3, param4, param5, param6, param7) \ + inline returntype funcname(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7) \ + { \ + return qt_winrt_##funcname(p1, p2, p3, p4, p5, p6, p7); \ + } + +typedef unsigned (__stdcall *StartAdressExFunc)(void *); +typedef void(*StartAdressFunc)(void *); +typedef int ( __cdecl *CompareFunc ) (const void *, const void *) ; + +generate_inline_return_func4(getenv_s, errno_t, size_t *, char *, size_t, const char *) +generate_inline_return_func2(_putenv_s, errno_t, const char *, const char *) +generate_inline_return_func0(tzset, void) +generate_inline_return_func0(_tzset, void) + +#endif // Q_OS_WINRT +#endif // QFUNCTIONS_WINRT_H diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index ff2675dfc8..0e38f2a2bf 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -942,7 +942,7 @@ static const QMetaObject *QMetaObject_findMetaObject(const QMetaObject *self, co return self; if (self->d.relatedMetaObjects) { Q_ASSERT(priv(self->d.data)->revision >= 2); - const QMetaObject **e = self->d.relatedMetaObjects; + const QMetaObject * const *e = self->d.relatedMetaObjects; if (e) { while (*e) { if (const QMetaObject *m =QMetaObject_findMetaObject((*e), name)) @@ -2694,10 +2694,14 @@ int QMetaProperty::userType() const if (type != QMetaType::UnknownType) return type; if (isEnumType()) { - int enumMetaTypeId = QMetaType::type(qualifiedName(menum)); - if (enumMetaTypeId == QMetaType::UnknownType) - return QVariant::Int; // Match behavior of QMetaType::type() - return enumMetaTypeId; + type = QMetaType::type(qualifiedName(menum)); + if (type == QMetaType::UnknownType) { + void *argv[] = { &type }; + mobj->static_metacall(QMetaObject::RegisterPropertyMetaType, idx, argv); + if (type == -1 || type == QMetaType::UnknownType) + return QVariant::Int; // Match behavior of QMetaType::type() + } + return type; } type = QMetaType::type(typeName()); if (type != QMetaType::UnknownType) diff --git a/src/corelib/kernel/qmetaobjectbuilder.cpp b/src/corelib/kernel/qmetaobjectbuilder.cpp index 11ab39af1a..09d8271413 100644 --- a/src/corelib/kernel/qmetaobjectbuilder.cpp +++ b/src/corelib/kernel/qmetaobjectbuilder.cpp @@ -741,7 +741,7 @@ void QMetaObjectBuilder::addMetaObject if ((members & RelatedMetaObjects) != 0) { Q_ASSERT(priv(prototype->d.data)->revision >= 2); - const QMetaObject **objects = prototype->d.relatedMetaObjects; + const QMetaObject * const *objects = prototype->d.relatedMetaObjects; if (objects) { while (*objects != 0) { addRelatedMetaObject(*objects); diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index f1351f5a07..40e1e8bcc5 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -491,6 +491,100 @@ void QMetaCallEvent::placeMetaCall(QObject *object) } /*! + \class QSignalBlocker + \brief Exception-safe wrapper around QObject::blockSignals() + \since 5.3 + \ingroup objectmodel + + \reentrant + + QSignalBlocker can be used whereever you would otherwise use a + pair of calls to blockSignals(). It blocks signals in its + constructor and in the destructor it resets the state to what + it was before the constructor ran. + + \code + { + const QSignalBlocker blocker(someQObject); + // no signals here + } + \endcode + is thus equivalent to + \code + const bool wasBlocked = someQObject->blockSignals(true); + // no signals here + someQObject->blockSignals(false); + \endcode + + except the code using QSignalBlocker is safe in the face of + exceptions. + + \sa QMutexLocker, QEventLoopLocker +*/ + +/*! + \fn QSignalBlocker::QSignalBlocker(QObject *object) + + Constructor. Calls \a{object}->blockSignals(true). +*/ + +/*! + \fn QSignalBlocker::QSignalBlocker(QObject &object) + \overload + + Calls \a{object}.blockSignals(true). +*/ + +/*! + \fn QSignalBlocker::QSignalBlocker(QSignalBlocker &&other) + + Move-constructs a signal blocker from \a other. \a other will have + a no-op destructor, while repsonsibility for restoring the + QObject::signalsBlocked() state is transferred to the new object. +*/ + +/*! + \fn QSignalBlocker &QSignalBlocker::operator=(QSignalBlocker &&other) + + Move-assigns this signal blocker from \a other. \a other will have + a no-op destructor, while repsonsibility for restoring the + QObject::signalsBlocked() state is transferred to this object. + + The object's signals this signal blocker was blocking prior to + being moved to, if any, are unblocked \em except in the case where + both instances block the same object's signals and \c *this is + unblocked while \a other is not, at the time of the move. +*/ + +/*! + \fn QSignalBlocker::~QSignalBlocker() + + Destructor. Restores the QObject::signalsBlocked() state to what it + was before the constructor ran, unless unblock() has been called + without a following reblock(), in which case it does nothing. +*/ + +/*! + \fn void QSignalBlocker::reblock() + + Re-blocks signals after a previous unblock(). + + The numbers of reblock() and unblock() calls are not counted, so + every reblock() undoes any number of unblock() calls. +*/ + +/*! + \fn void QSignalBlocker::unblock() + + Temporarily restores the QObject::signalsBlocked() state to what + it was before this QSignaBlocker's constructor ran. To undo, use + reblock(). + + The numbers of reblock() and unblock() calls are not counted, so + every unblock() undoes any number of reblock() calls. +*/ + +/*! \class QObject \inmodule QtCore \brief The QObject class is the base class of all Qt objects. @@ -2233,11 +2327,19 @@ QObject *QObject::sender() const int QObject::senderSignalIndex() const { Q_D(const QObject); - int signal_index = d->senderSignalIndex(); - if (signal_index < 0) - return signal_index; - // Convert from signal range to method range - return QMetaObjectPrivate::signal(sender()->metaObject(), signal_index).methodIndex(); + + QMutexLocker locker(signalSlotLock(this)); + if (!d->currentSender) + return -1; + + for (QObjectPrivate::Connection *c = d->senders; c; c = c->next) { + if (c->sender == d->currentSender->sender) { + // Convert from signal range to method range + return QMetaObjectPrivate::signal(c->sender->metaObject(), d->currentSender->signal).methodIndex(); + } + } + + return -1; } /*! @@ -3620,25 +3722,6 @@ void QMetaObject::activate(QObject *sender, int signal_index, void **argv) /*! \internal - Implementation of QObject::senderSignalIndex() -*/ -int QObjectPrivate::senderSignalIndex() const -{ - Q_Q(const QObject); - QMutexLocker locker(signalSlotLock(q)); - if (!currentSender) - return -1; - - for (QObjectPrivate::Connection *c = senders; c; c = c->next) { - if (c->sender == currentSender->sender) - return currentSender->signal; - } - - return -1; -} - -/*! - \internal Returns the signal index used in the internal connectionLists vector. It is different from QMetaObject::indexOfSignal(): indexOfSignal is the same as indexOfMethod @@ -3715,6 +3798,8 @@ bool QObject::setProperty(const char *name, const QVariant &value) d->extraData->propertyNames.append(name); d->extraData->propertyValues.append(value); } else { + if (value == d->extraData->propertyValues.at(idx)) + return false; d->extraData->propertyValues[idx] = value; } } diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index e2000afc82..5197d98f19 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -549,6 +549,83 @@ template <class T> inline const char * qobject_interface_iid() Q_CORE_EXPORT QDebug operator<<(QDebug, const QObject *); #endif +class Q_CORE_EXPORT QSignalBlocker +{ +public: + inline explicit QSignalBlocker(QObject *o); + inline explicit QSignalBlocker(QObject &o); + inline ~QSignalBlocker(); + +#ifdef Q_COMPILER_RVALUE_REFS + inline QSignalBlocker(QSignalBlocker &&other); + inline QSignalBlocker &operator=(QSignalBlocker &&other); +#endif + + inline void reblock(); + inline void unblock(); +private: + Q_DISABLE_COPY(QSignalBlocker) + QObject * m_o; + bool m_blocked; + bool m_inhibited; +}; + +QSignalBlocker::QSignalBlocker(QObject *o) + : m_o(o), + m_blocked(o && o->blockSignals(true)), + m_inhibited(false) +{} + +QSignalBlocker::QSignalBlocker(QObject &o) + : m_o(&o), + m_blocked(o.blockSignals(true)), + m_inhibited(false) +{} + +#ifdef Q_COMPILER_RVALUE_REFS +QSignalBlocker::QSignalBlocker(QSignalBlocker &&other) + : m_o(other.m_o), + m_blocked(other.m_blocked), + m_inhibited(other.m_inhibited) +{ + other.m_o = 0; +} + +QSignalBlocker &QSignalBlocker::operator=(QSignalBlocker &&other) +{ + if (this != &other) { + // if both *this and other block the same object's signals: + // unblock *this iff our dtor would unblock, but other's wouldn't + if (m_o != other.m_o || (!m_inhibited && other.m_inhibited)) + unblock(); + m_o = other.m_o; + m_blocked = other.m_blocked; + m_inhibited = other.m_inhibited; + // disable other: + other.m_o = 0; + } + return *this; +} +#endif + +QSignalBlocker::~QSignalBlocker() +{ + if (m_o && !m_inhibited) + m_o->blockSignals(m_blocked); +} + +void QSignalBlocker::reblock() +{ + if (m_o) m_o->blockSignals(true); + m_inhibited = false; +} + +void QSignalBlocker::unblock() +{ + if (m_o) m_o->blockSignals(m_blocked); + m_inhibited = true; +} + namespace QtPrivate { inline QObject & deref_for_methodcall(QObject &o) { return o; } inline QObject & deref_for_methodcall(QObject *o) { return *o; } diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index 011e140e3b..193fa78403 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -199,7 +199,6 @@ public: return o->d_func(); } - int senderSignalIndex() const; int signalIndex(const char *signalName, const QMetaObject **meta = 0) const; inline bool isSignalConnected(uint signalIdx) const; diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h index 7354c3f0d0..c3141c1abb 100644 --- a/src/corelib/kernel/qobjectdefs.h +++ b/src/corelib/kernel/qobjectdefs.h @@ -447,7 +447,7 @@ struct Q_CORE_EXPORT QMetaObject const uint *data; typedef void (*StaticMetacallFunction)(QObject *, QMetaObject::Call, int, void **); StaticMetacallFunction static_metacall; - const QMetaObject **relatedMetaObjects; + const QMetaObject * const *relatedMetaObjects; void *extradata; //reserved for future use } d; }; diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index 69cfa7888f..91ccf3996e 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -868,7 +868,7 @@ static void customConstruct(QVariant::Private *d, const void *copy) // this logic should match with QVariantIntegrator::CanUseInternalSpace if (size <= sizeof(QVariant::Private::Data) - && (type.flags() & QMetaType::MovableType)) { + && (type.flags() & (QMetaType::MovableType | QMetaType::IsEnumeration))) { type.construct(&d->data.ptr, copy); d->is_shared = false; } else { diff --git a/src/corelib/kernel/qvariant_p.h b/src/corelib/kernel/qvariant_p.h index 4ec049e20d..b523d19187 100644 --- a/src/corelib/kernel/qvariant_p.h +++ b/src/corelib/kernel/qvariant_p.h @@ -67,7 +67,7 @@ template<typename T> struct QVariantIntegrator { static const bool CanUseInternalSpace = sizeof(T) <= sizeof(QVariant::Private::Data) - && (!QTypeInfo<T>::isStatic); + && ((!QTypeInfo<T>::isStatic) || Q_IS_ENUM(T)); }; Q_STATIC_ASSERT(QVariantIntegrator<double>::CanUseInternalSpace); Q_STATIC_ASSERT(QVariantIntegrator<long int>::CanUseInternalSpace); diff --git a/src/corelib/kernel/qwineventnotifier.cpp b/src/corelib/kernel/qwineventnotifier.cpp index eab5a37645..c694237dc3 100644 --- a/src/corelib/kernel/qwineventnotifier.cpp +++ b/src/corelib/kernel/qwineventnotifier.cpp @@ -41,7 +41,11 @@ #include "qwineventnotifier.h" +#ifdef Q_OS_WINRT +#include "qeventdispatcher_winrt_p.h" +#else #include "qeventdispatcher_win_p.h" +#endif #include "qcoreapplication.h" #include <private/qthread_p.h> diff --git a/src/corelib/plugin/qlibrary_win.cpp b/src/corelib/plugin/qlibrary_win.cpp index 928f2c5eb1..b9494a3041 100644 --- a/src/corelib/plugin/qlibrary_win.cpp +++ b/src/corelib/plugin/qlibrary_win.cpp @@ -107,12 +107,16 @@ bool QLibraryPrivate::load_sys() attempts.append(QFileInfo(fileName).absoluteFilePath()); #endif } +#ifdef Q_OS_WINRT + if (fileName.startsWith(QLatin1Char('/'))) + attempts.prepend(QDir::rootPath() + fileName); +#endif Q_FOREACH (const QString &attempt, attempts) { #ifndef Q_OS_WINRT pHnd = LoadLibrary((wchar_t*)QDir::toNativeSeparators(attempt).utf16()); #else // Q_OS_WINRT - QString path = QDir::toNativeSeparators(QDir::current().relativeFilePath(fileName)); + QString path = QDir::toNativeSeparators(QDir::current().relativeFilePath(attempt)); pHnd = LoadPackagedLibrary((LPCWSTR)path.utf16(), 0); if (pHnd) qualifiedFileName = attempt; diff --git a/src/corelib/thread/qatomic.cpp b/src/corelib/thread/qatomic.cpp index 39d136c006..b2e19dc6dc 100644 --- a/src/corelib/thread/qatomic.cpp +++ b/src/corelib/thread/qatomic.cpp @@ -39,6 +39,8 @@ ** ****************************************************************************/ +#include "qatomic.h" + /*! \class QAtomicInt \inmodule QtCore @@ -1126,3 +1128,8 @@ Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE to indicate that the atomic fetch-and-add on pointers is wait-free. */ + +// static checks +#ifndef Q_ATOMIC_INT32_IS_SUPPORTED +# error "Q_ATOMIC_INT32_IS_SUPPORTED must be defined" +#endif diff --git a/src/corelib/thread/qatomic.h b/src/corelib/thread/qatomic.h index 1ccaecc135..78eff2a710 100644 --- a/src/corelib/thread/qatomic.h +++ b/src/corelib/thread/qatomic.h @@ -59,7 +59,7 @@ class QAtomicInt : public QBasicAtomicInt { public: // Non-atomic API -#ifdef Q_BASIC_ATOMIC_HAS_CONSTRUCTORS +#ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS constexpr QAtomicInt(int value = 0) Q_DECL_NOTHROW : QBasicAtomicInt(value) {} #else inline QAtomicInt(int value = 0) Q_DECL_NOTHROW diff --git a/src/corelib/thread/qbasicatomic.h b/src/corelib/thread/qbasicatomic.h index 782ae90698..9fa12ba811 100644 --- a/src/corelib/thread/qbasicatomic.h +++ b/src/corelib/thread/qbasicatomic.h @@ -51,33 +51,17 @@ #elif defined(Q_CC_MSVC) # include <QtCore/qatomic_msvc.h> -// Operating system dependent implementation -#elif defined(Q_OS_INTEGRITY) -# include "QtCore/qatomic_integrity.h" -#elif defined(Q_OS_VXWORKS) -# include "QtCore/qatomic_vxworks.h" - // Processor dependent implementation -#elif defined(Q_PROCESSOR_ALPHA) -# include "QtCore/qatomic_alpha.h" #elif defined(Q_PROCESSOR_ARM_V7) && defined(Q_PROCESSOR_ARM_32) # include "QtCore/qatomic_armv7.h" #elif defined(Q_PROCESSOR_ARM_V6) && defined(Q_PROCESSOR_ARM_32) # include "QtCore/qatomic_armv6.h" #elif defined(Q_PROCESSOR_ARM_V5) && defined(Q_PROCESSOR_ARM_32) # include "QtCore/qatomic_armv5.h" -#elif defined(Q_PROCESSOR_BFIN) -# include "QtCore/qatomic_bfin.h" #elif defined(Q_PROCESSOR_IA64) # include "QtCore/qatomic_ia64.h" #elif defined(Q_PROCESSOR_MIPS) # include "QtCore/qatomic_mips.h" -#elif defined(Q_PROCESSOR_POWER) -# include "QtCore/qatomic_power.h" -#elif defined(Q_PROCESSOR_S390) -# include "QtCore/qatomic_s390.h" -#elif defined(Q_PROCESSOR_SH4A) -# include "QtCore/qatomic_sh4a.h" #elif defined(Q_PROCESSOR_SPARC) # include "QtCore/qatomic_sparc.h" #elif defined(Q_PROCESSOR_X86) @@ -98,9 +82,6 @@ # error "Qt has not been ported to this platform" #endif -// Only include if the implementation has been ported to QAtomicOps -#ifndef QOLDBASICATOMIC_H - QT_BEGIN_NAMESPACE #if 0 @@ -133,7 +114,7 @@ class QBasicAtomicInteger public: typedef QAtomicOps<T> Ops; // static check that this is a valid integer - typedef char PermittedIntegerType[QAtomicIntegerTraits<T>::IsInteger ? 1 : -1]; + Q_STATIC_ASSERT_X(QAtomicIntegerTraits<T>::IsInteger, "Template parameter is not a supported integer on this platform"); typename Ops::Type _q_value; @@ -266,6 +247,4 @@ public: QT_END_NAMESPACE -#endif // QOLDBASICATOMIC_H - #endif // QBASICATOMIC_H diff --git a/src/corelib/thread/qmutex_win.cpp b/src/corelib/thread/qmutex_win.cpp index 14b7f34008..a8cdf85fb6 100644 --- a/src/corelib/thread/qmutex_win.cpp +++ b/src/corelib/thread/qmutex_win.cpp @@ -48,7 +48,12 @@ QT_BEGIN_NAMESPACE QMutexPrivate::QMutexPrivate() { +#ifndef Q_OS_WINRT event = CreateEvent(0, FALSE, FALSE, 0); +#else + event = CreateEventEx(0, NULL, 0, EVENT_ALL_ACCESS); +#endif + if (!event) qWarning("QMutexData::QMutexData: Cannot create event"); } @@ -58,7 +63,11 @@ QMutexPrivate::~QMutexPrivate() bool QMutexPrivate::wait(int timeout) { +#ifndef Q_OS_WINRT return (WaitForSingleObject(event, timeout < 0 ? INFINITE : timeout) == WAIT_OBJECT_0); +#else + return (WaitForSingleObjectEx(event, timeout < 0 ? INFINITE : timeout, FALSE) == WAIT_OBJECT_0); +#endif } void QMutexPrivate::wakeUp() Q_DECL_NOTHROW diff --git a/src/corelib/thread/qoldbasicatomic.h b/src/corelib/thread/qoldbasicatomic.h deleted file mode 100644 index b755256ff7..0000000000 --- a/src/corelib/thread/qoldbasicatomic.h +++ /dev/null @@ -1,143 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QOLDBASICATOMIC_H -#define QOLDBASICATOMIC_H - -#include <QtCore/qglobal.h> - -QT_BEGIN_NAMESPACE - - -#if 0 -// silence syncqt warnings -QT_END_NAMESPACE -#pragma qt_sync_skip_header_check -#pragma qt_no_master_include -#pragma qt_sync_stop_processing -#endif - -class Q_CORE_EXPORT QBasicAtomicInt -{ -public: - volatile int _q_value; - - // Atomic API, implemented in qatomic_XXX.h - - int load() const { return _q_value; } - int loadAcquire() { return _q_value; } - void store(int newValue) { _q_value = newValue; } - void storeRelease(int newValue) { _q_value = newValue; } - - static bool isReferenceCountingNative(); - static bool isReferenceCountingWaitFree(); - - bool ref(); - bool deref(); - - static bool isTestAndSetNative(); - static bool isTestAndSetWaitFree(); - - bool testAndSetRelaxed(int expectedValue, int newValue); - bool testAndSetAcquire(int expectedValue, int newValue); - bool testAndSetRelease(int expectedValue, int newValue); - bool testAndSetOrdered(int expectedValue, int newValue); - - static bool isFetchAndStoreNative(); - static bool isFetchAndStoreWaitFree(); - - int fetchAndStoreRelaxed(int newValue); - int fetchAndStoreAcquire(int newValue); - int fetchAndStoreRelease(int newValue); - int fetchAndStoreOrdered(int newValue); - - static bool isFetchAndAddNative(); - static bool isFetchAndAddWaitFree(); - - int fetchAndAddRelaxed(int valueToAdd); - int fetchAndAddAcquire(int valueToAdd); - int fetchAndAddRelease(int valueToAdd); - int fetchAndAddOrdered(int valueToAdd); -}; - -template <typename T> -class QBasicAtomicPointer -{ -public: - T * volatile _q_value; - - // Atomic API, implemented in qatomic_XXX.h - - T *load() const { return _q_value; } - T *loadAcquire() { return _q_value; } - void store(T *newValue) { _q_value = newValue; } - void storeRelease(T *newValue) { _q_value = newValue; } - - static bool isTestAndSetNative(); - static bool isTestAndSetWaitFree(); - - bool testAndSetRelaxed(T *expectedValue, T *newValue); - bool testAndSetAcquire(T *expectedValue, T *newValue); - bool testAndSetRelease(T *expectedValue, T *newValue); - bool testAndSetOrdered(T *expectedValue, T *newValue); - - static bool isFetchAndStoreNative(); - static bool isFetchAndStoreWaitFree(); - - T *fetchAndStoreRelaxed(T *newValue); - T *fetchAndStoreAcquire(T *newValue); - T *fetchAndStoreRelease(T *newValue); - T *fetchAndStoreOrdered(T *newValue); - - static bool isFetchAndAddNative(); - static bool isFetchAndAddWaitFree(); - - T *fetchAndAddRelaxed(qptrdiff valueToAdd); - T *fetchAndAddAcquire(qptrdiff valueToAdd); - T *fetchAndAddRelease(qptrdiff valueToAdd); - T *fetchAndAddOrdered(qptrdiff valueToAdd); -}; - -#define Q_BASIC_ATOMIC_INITIALIZER(a) { (a) } - -QT_END_NAMESPACE - -#endif // QOLDBASICATOMIC_H diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp index 50ccca9eda..adad4b81a1 100644 --- a/src/corelib/thread/qthread.cpp +++ b/src/corelib/thread/qthread.cpp @@ -154,7 +154,9 @@ QThreadPrivate::QThreadPrivate(QThreadData *d) thread_id = 0; #elif defined (Q_OS_WIN) handle = 0; +# ifndef Q_OS_WINRT id = 0; +# endif waiters = 0; #endif #if defined (Q_OS_WIN) diff --git a/src/corelib/thread/qthread_p.h b/src/corelib/thread/qthread_p.h index 8429e41433..c9b98ac5c0 100644 --- a/src/corelib/thread/qthread_p.h +++ b/src/corelib/thread/qthread_p.h @@ -66,6 +66,10 @@ #include <algorithm> +#ifdef Q_OS_WINRT +#include <thread> +#endif + QT_BEGIN_NAMESPACE class QAbstractEventDispatcher; @@ -173,8 +177,13 @@ public: static unsigned int __stdcall start(void *); static void finish(void *, bool lockAnyway=true); +# ifndef Q_OS_WINRT Qt::HANDLE handle; unsigned int id; +# else + std::thread *handle; + std::thread::id id; +# endif int waiters; bool terminationEnabled, terminatePending; # endif diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp index 037343c996..2c3ff879e4 100644 --- a/src/corelib/thread/qthread_win.cpp +++ b/src/corelib/thread/qthread_win.cpp @@ -40,7 +40,7 @@ ****************************************************************************/ //#define WINVER 0x0500 -#if _WIN32_WINNT < 0x0400 +#if (_WIN32_WINNT < 0x0400) && !defined(Q_OS_WINRT) #define _WIN32_WINNT 0x0400 #endif @@ -54,10 +54,17 @@ #include <qpointer.h> #include <private/qcoreapplication_p.h> +#ifdef Q_OS_WINRT +#include <private/qeventdispatcher_winrt_p.h> +#else #include <private/qeventdispatcher_win_p.h> +#endif #include <qt_windows.h> +#ifdef Q_OS_WINRT +#include <thread> +#endif #ifndef Q_OS_WINCE #ifndef _MT @@ -71,6 +78,7 @@ #ifndef QT_NO_THREAD QT_BEGIN_NAMESPACE +#ifndef Q_OS_WINRT void qt_watch_adopted_thread(const HANDLE adoptedThreadHandle, QThread *qthread); DWORD WINAPI qt_adopted_thread_watcher_function(LPVOID); @@ -92,6 +100,38 @@ static void qt_free_tls() } } Q_DESTRUCTOR_FUNCTION(qt_free_tls) +#else // !Q_OS_WINRT + +__declspec(thread) static QThreadData* qt_current_thread_data_tls_index = 0; +void qt_create_tls() +{ +} + +static void qt_free_tls() +{ + if (qt_current_thread_data_tls_index) { + qt_current_thread_data_tls_index->deref(); + qt_current_thread_data_tls_index = 0; + } +} + +QThreadData* TlsGetValue(QThreadData*& tls) +{ + Q_ASSERT(tls == qt_current_thread_data_tls_index); + return tls; +} + +void TlsSetValue(QThreadData*& tls, QThreadData* data) +{ + Q_ASSERT(tls == qt_current_thread_data_tls_index); + if (tls) + tls->deref(); + tls = data; + if (tls) + tls->ref(); +} +Q_DESTRUCTOR_FUNCTION(qt_free_tls) +#endif // Q_OS_WINRT /* QThreadData @@ -124,6 +164,9 @@ QThreadData *QThreadData::current() if (!QCoreApplicationPrivate::theMainThread) { QCoreApplicationPrivate::theMainThread = threadData->thread; +#ifndef Q_OS_WINRT + // TODO: is there a way to reflect the branch's behavior using + // WinRT API? } else { HANDLE realHandle = INVALID_HANDLE_VALUE; #if !defined(Q_OS_WINCE) || (defined(_WIN32_WCE) && (_WIN32_WCE>=0x600)) @@ -138,6 +181,7 @@ QThreadData *QThreadData::current() realHandle = reinterpret_cast<HANDLE>(GetCurrentThreadId()); #endif qt_watch_adopted_thread(realHandle, threadData->thread); +#endif // !Q_OS_WINRT } } return threadData; @@ -145,10 +189,16 @@ QThreadData *QThreadData::current() void QAdoptedThread::init() { +#ifndef Q_OS_WINRT d_func()->handle = GetCurrentThread(); d_func()->id = GetCurrentThreadId(); +#else + d_func()->handle = nullptr; + d_func()->id = std::this_thread::get_id(); +#endif } +#ifndef Q_OS_WINRT static QVector<HANDLE> qt_adopted_thread_handles; static QVector<QThread *> qt_adopted_qthreads; static QMutex qt_adopted_thread_watcher_mutex; @@ -301,6 +351,7 @@ void qt_set_thread_name(HANDLE threadId, LPCSTR threadName) } } #endif // !QT_NO_DEBUG && Q_CC_MSVC && !Q_OS_WINCE +#endif // !Q_OS_WINRT /************************************************************************** ** QThreadPrivate @@ -310,7 +361,11 @@ void qt_set_thread_name(HANDLE threadId, LPCSTR threadName) void QThreadPrivate::createEventDispatcher(QThreadData *data) { +#ifdef Q_OS_WINRT + QEventDispatcherWinRT *theEventDispatcher = new QEventDispatcherWinRT; +#else QEventDispatcherWin32 *theEventDispatcher = new QEventDispatcherWin32; +#endif data->eventDispatcher.storeRelease(theEventDispatcher); theEventDispatcher->startingUp(); } @@ -338,7 +393,7 @@ unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSE QThreadPrivate::start(voi else createEventDispatcher(data); -#if !defined(QT_NO_DEBUG) && defined(Q_CC_MSVC) && !defined(Q_OS_WINCE) +#if !defined(QT_NO_DEBUG) && defined(Q_CC_MSVC) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) // sets the name of the current thread. QByteArray objectName = thr->objectName().toLocal8Bit(); qt_set_thread_name((HANDLE)-1, @@ -384,11 +439,20 @@ void QThreadPrivate::finish(void *arg, bool lockAnyway) d->interruptionRequested = false; if (!d->waiters) { +#ifndef Q_OS_WINRT CloseHandle(d->handle); +#else + CloseHandle(d->handle->native_handle()); + delete d->handle; +#endif d->handle = 0; } +#ifndef Q_OS_WINRT d->id = 0; +#else + d->id = std::thread::id(); +#endif } @@ -404,10 +468,15 @@ Qt::HANDLE QThread::currentThreadId() Q_DECL_NOTHROW int QThread::idealThreadCount() Q_DECL_NOTHROW { SYSTEM_INFO sysinfo; +#ifndef Q_OS_WINRT GetSystemInfo(&sysinfo); +#else + GetNativeSystemInfo(&sysinfo); +#endif return sysinfo.dwNumberOfProcessors; } +#ifndef Q_OS_WINRT void QThread::yieldCurrentThread() { #ifndef Q_OS_WINCE @@ -431,7 +500,28 @@ void QThread::usleep(unsigned long usecs) { ::Sleep((usecs / 1000) + 1); } +#else // !Q_OS_WINRT + +void QThread::yieldCurrentThread() +{ + std::this_thread::yield(); +} +void QThread::sleep(unsigned long secs) +{ + std::this_thread::sleep_for(std::chrono::seconds(secs)); +} + +void QThread::msleep(unsigned long msecs) +{ + std::this_thread::sleep_for(std::chrono::milliseconds(msecs)); +} + +void QThread::usleep(unsigned long usecs) +{ + std::this_thread::sleep_for(std::chrono::microseconds(usecs)); +} +#endif // Q_OS_WINRT void QThread::start(Priority priority) { @@ -453,6 +543,7 @@ void QThread::start(Priority priority) d->returnCode = 0; d->interruptionRequested = false; +#ifndef Q_OS_WINRT /* NOTE: we create the thread in the suspended state, set the priority and then resume the thread. @@ -517,6 +608,23 @@ void QThread::start(Priority priority) if (ResumeThread(d->handle) == (DWORD) -1) { qErrnoWarning("QThread::start: Failed to resume new thread"); } +#else // !Q_OS_WINRT + d->handle = new std::thread(QThreadPrivate::start, this); + + if (!d->handle) { + qErrnoWarning(errno, "QThread::start: Failed to create thread"); + d->running = false; + d->finished = true; + return; + } + + d->id = d->handle->get_id(); + + if (priority != NormalPriority || priority != InheritPriority) { + qWarning("QThread::start: Failed to set thread priority (not implemented)"); + d->priority = NormalPriority; + } +#endif // Q_OS_WINRT } void QThread::terminate() @@ -529,7 +637,14 @@ void QThread::terminate() d->terminatePending = true; return; } + +#ifndef Q_OS_WINRT TerminateThread(d->handle, 0); +#else // !Q_OS_WINRT + qWarning("QThread::terminate: Terminate is not supported on WinRT"); + CloseHandle(d->handle->native_handle()); + d->handle = 0; +#endif // Q_OS_WINRT QThreadPrivate::finish(this, false); } @@ -538,7 +653,11 @@ bool QThread::wait(unsigned long time) Q_D(QThread); QMutexLocker locker(&d->mutex); +#ifndef Q_OS_WINRT if (d->id == GetCurrentThreadId()) { +#else + if (d->id == std::this_thread::get_id()) { +#endif qWarning("QThread::wait: Thread tried to wait on itself"); return false; } @@ -549,6 +668,7 @@ bool QThread::wait(unsigned long time) locker.mutex()->unlock(); bool ret = false; +#ifndef Q_OS_WINRT switch (WaitForSingleObject(d->handle, time)) { case WAIT_OBJECT_0: ret = true; @@ -561,6 +681,23 @@ bool QThread::wait(unsigned long time) default: break; } +#else // !Q_OS_WINRT + if (d->handle->joinable()) { + switch (WaitForSingleObjectEx(d->handle->native_handle(), time, FALSE)) { + case WAIT_OBJECT_0: + ret = true; + d->handle->join(); + break; + case WAIT_FAILED: + qErrnoWarning("QThread::wait: WaitForSingleObjectEx() failed"); + break; + case WAIT_ABANDONED: + case WAIT_TIMEOUT: + default: + break; + } + } +#endif // Q_OS_WINRT locker.mutex()->lock(); --d->waiters; @@ -572,7 +709,11 @@ bool QThread::wait(unsigned long time) } if (d->finished && !d->waiters) { +#ifndef Q_OS_WINRT CloseHandle(d->handle); +#else + delete d->handle; +#endif d->handle = 0; } @@ -590,13 +731,16 @@ void QThread::setTerminationEnabled(bool enabled) if (enabled && d->terminatePending) { QThreadPrivate::finish(thr, false); locker.unlock(); // don't leave the mutex locked! +#ifndef Q_OS_WINRT _endthreadex(0); +#endif } } // Caller must hold the mutex void QThreadPrivate::setPriority(QThread::Priority threadPriority) { +#ifndef Q_OS_WINRT // copied from start() with a few modifications: int prio; @@ -639,6 +783,12 @@ void QThreadPrivate::setPriority(QThread::Priority threadPriority) if (!SetThreadPriority(handle, prio)) { qErrnoWarning("QThread::setPriority: Failed to set thread priority"); } +#else // !Q_OS_WINRT + if (priority != threadPriority) { + qWarning("QThread::setPriority: Failed to set thread priority (not implemented)"); + return; + } +#endif // Q_OS_WINRT } QT_END_NAMESPACE diff --git a/src/corelib/thread/qthreadpool.cpp b/src/corelib/thread/qthreadpool.cpp index fb1d1ee7cc..269f561a91 100644 --- a/src/corelib/thread/qthreadpool.cpp +++ b/src/corelib/thread/qthreadpool.cpp @@ -61,6 +61,7 @@ public: void run(); void registerThreadInactive(); + QWaitCondition runnableReady; QThreadPoolPrivate *manager; QRunnable *runnable; }; @@ -128,14 +129,13 @@ void QThreadPoolThread::run() // if too many threads are active, expire this thread bool expired = manager->tooManyThreadsActive(); if (!expired) { - ++manager->waitingThreads; + manager->waitingThreads.enqueue(this); registerThreadInactive(); // wait for work, exiting after the expiry timeout is reached - expired = !manager->runnableReady.wait(locker.mutex(), manager->expiryTimeout); + runnableReady.wait(locker.mutex(), manager->expiryTimeout); ++manager->activeThreads; - - if (expired) - --manager->waitingThreads; + if (manager->waitingThreads.removeOne(this)) + expired = true; } if (expired) { manager->expiredThreads.enqueue(this); @@ -160,7 +160,6 @@ QThreadPoolPrivate:: QThreadPoolPrivate() expiryTimeout(30000), maxThreadCount(qAbs(QThread::idealThreadCount())), reservedThreads(0), - waitingThreads(0), activeThreads(0) { } @@ -176,11 +175,10 @@ bool QThreadPoolPrivate::tryStart(QRunnable *task) if (activeThreadCount() >= maxThreadCount) return false; - if (waitingThreads > 0) { + if (waitingThreads.count() > 0) { // recycle an available thread - --waitingThreads; enqueueTask(task); - runnableReady.wakeOne(); + waitingThreads.takeFirst()->runnableReady.wakeOne(); return true; } @@ -225,7 +223,7 @@ int QThreadPoolPrivate::activeThreadCount() const { return (allThreads.count() - expiredThreads.count() - - waitingThreads + - waitingThreads.count() + reservedThreads); } @@ -266,7 +264,6 @@ void QThreadPoolPrivate::reset() { QMutexLocker locker(&mutex); isExiting = true; - runnableReady.wakeAll(); while (!allThreads.empty()) { // move the contents of the set out so that we can iterate without the lock @@ -275,6 +272,7 @@ void QThreadPoolPrivate::reset() locker.unlock(); foreach (QThreadPoolThread *thread, allThreadsCopy) { + thread->runnableReady.wakeAll(); thread->wait(); delete thread; } @@ -283,7 +281,7 @@ void QThreadPoolPrivate::reset() // repeat until all newly arrived threads have also completed } - waitingThreads = 0; + waitingThreads.clear(); expiredThreads.clear(); isExiting = false; @@ -459,10 +457,8 @@ void QThreadPool::start(QRunnable *runnable, int priority) if (!d->tryStart(runnable)) { d->enqueueTask(runnable, priority); - if (d->waitingThreads > 0) { - --d->waitingThreads; - d->runnableReady.wakeOne(); - } + if (!d->waitingThreads.isEmpty()) + d->waitingThreads.takeFirst()->runnableReady.wakeOne(); } } diff --git a/src/corelib/thread/qthreadpool_p.h b/src/corelib/thread/qthreadpool_p.h index ba77f7e57c..bd5f546fdb 100644 --- a/src/corelib/thread/qthreadpool_p.h +++ b/src/corelib/thread/qthreadpool_p.h @@ -87,8 +87,8 @@ public: void stealRunnable(QRunnable *); mutable QMutex mutex; - QWaitCondition runnableReady; QSet<QThreadPoolThread *> allThreads; + QQueue<QThreadPoolThread *> waitingThreads; QQueue<QThreadPoolThread *> expiredThreads; QList<QPair<QRunnable *, int> > queue; QWaitCondition noActiveThreads; @@ -97,7 +97,6 @@ public: int expiryTimeout; int maxThreadCount; int reservedThreads; - int waitingThreads; int activeThreads; }; diff --git a/src/corelib/thread/qwaitcondition_win.cpp b/src/corelib/thread/qwaitcondition_win.cpp index 1cb1f82b03..f09667a364 100644 --- a/src/corelib/thread/qwaitcondition_win.cpp +++ b/src/corelib/thread/qwaitcondition_win.cpp @@ -64,7 +64,11 @@ class QWaitConditionEvent public: inline QWaitConditionEvent() : priority(0), wokenUp(false) { +#ifndef Q_OS_WINRT event = CreateEvent(NULL, TRUE, FALSE, NULL); +#else + event = CreateEventEx(NULL, NULL, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS); +#endif } inline ~QWaitConditionEvent() { CloseHandle(event); } int priority; @@ -91,7 +95,9 @@ QWaitConditionEvent *QWaitConditionPrivate::pre() mtx.lock(); QWaitConditionEvent *wce = freeQueue.isEmpty() ? new QWaitConditionEvent : freeQueue.takeFirst(); +#ifndef Q_OS_WINRT wce->priority = GetThreadPriority(GetCurrentThread()); +#endif wce->wokenUp = false; // insert 'wce' into the queue (sorted by priority) @@ -111,7 +117,12 @@ bool QWaitConditionPrivate::wait(QWaitConditionEvent *wce, unsigned long time) { // wait for the event bool ret = false; +#ifndef Q_OS_WINRT switch (WaitForSingleObject(wce->event, time)) { +#else + switch (WaitForSingleObjectEx(wce->event, time, FALSE)) { +#endif + default: break; case WAIT_OBJECT_0: diff --git a/src/corelib/thread/thread.pri b/src/corelib/thread/thread.pri index 13f0502b62..3c1ddd984a 100644 --- a/src/corelib/thread/thread.pri +++ b/src/corelib/thread/thread.pri @@ -17,8 +17,7 @@ HEADERS += thread/qmutex.h \ thread/qfuturesynchronizer.h \ thread/qfuturewatcher.h \ thread/qbasicatomic.h \ - thread/qgenericatomic.h \ - thread/qoldbasicatomic.h + thread/qgenericatomic.h # private headers HEADERS += thread/qmutex_p.h \ diff --git a/src/corelib/tools/qalgorithms.h b/src/corelib/tools/qalgorithms.h index c6eede05cb..f75f33f25c 100644 --- a/src/corelib/tools/qalgorithms.h +++ b/src/corelib/tools/qalgorithms.h @@ -55,28 +55,28 @@ namespace QAlgorithmsPrivate { #if QT_DEPRECATED_SINCE(5, 2) template <typename RandomAccessIterator, typename T, typename LessThan> -QT_DEPRECATED Q_OUTOFLINE_TEMPLATE void qSortHelper(RandomAccessIterator start, RandomAccessIterator end, const T &t, LessThan lessThan); +QT_DEPRECATED_X("Use std::sort") Q_OUTOFLINE_TEMPLATE void qSortHelper(RandomAccessIterator start, RandomAccessIterator end, const T &t, LessThan lessThan); template <typename RandomAccessIterator, typename T> -QT_DEPRECATED inline void qSortHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &dummy); +QT_DEPRECATED_X("Use std::sort") inline void qSortHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &dummy); template <typename RandomAccessIterator, typename T, typename LessThan> -QT_DEPRECATED Q_OUTOFLINE_TEMPLATE void qStableSortHelper(RandomAccessIterator start, RandomAccessIterator end, const T &t, LessThan lessThan); +QT_DEPRECATED_X("Use std::stable_sort") Q_OUTOFLINE_TEMPLATE void qStableSortHelper(RandomAccessIterator start, RandomAccessIterator end, const T &t, LessThan lessThan); template <typename RandomAccessIterator, typename T> -QT_DEPRECATED inline void qStableSortHelper(RandomAccessIterator, RandomAccessIterator, const T &); +QT_DEPRECATED_X("Use std::stable_sort") inline void qStableSortHelper(RandomAccessIterator, RandomAccessIterator, const T &); template <typename RandomAccessIterator, typename T, typename LessThan> -QT_DEPRECATED Q_OUTOFLINE_TEMPLATE RandomAccessIterator qLowerBoundHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan); +QT_DEPRECATED_X("Use std::lower_bound") Q_OUTOFLINE_TEMPLATE RandomAccessIterator qLowerBoundHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan); template <typename RandomAccessIterator, typename T, typename LessThan> -QT_DEPRECATED Q_OUTOFLINE_TEMPLATE RandomAccessIterator qUpperBoundHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan); +QT_DEPRECATED_X("Use std::upper_bound") Q_OUTOFLINE_TEMPLATE RandomAccessIterator qUpperBoundHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan); template <typename RandomAccessIterator, typename T, typename LessThan> -QT_DEPRECATED Q_OUTOFLINE_TEMPLATE RandomAccessIterator qBinaryFindHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan); +QT_DEPRECATED_X("Use std::binary_search") Q_OUTOFLINE_TEMPLATE RandomAccessIterator qBinaryFindHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan); #endif // QT_DEPRECATED_SINCE(5, 2) } #if QT_DEPRECATED_SINCE(5, 2) template <typename InputIterator, typename OutputIterator> -QT_DEPRECATED inline OutputIterator qCopy(InputIterator begin, InputIterator end, OutputIterator dest) +QT_DEPRECATED_X("Use std::copy") inline OutputIterator qCopy(InputIterator begin, InputIterator end, OutputIterator dest) { while (begin != end) *dest++ = *begin++; @@ -84,7 +84,7 @@ QT_DEPRECATED inline OutputIterator qCopy(InputIterator begin, InputIterator end } template <typename BiIterator1, typename BiIterator2> -QT_DEPRECATED inline BiIterator2 qCopyBackward(BiIterator1 begin, BiIterator1 end, BiIterator2 dest) +QT_DEPRECATED_X("Use std::copy_backward") inline BiIterator2 qCopyBackward(BiIterator1 begin, BiIterator1 end, BiIterator2 dest) { while (begin != end) *--dest = *--end; @@ -92,7 +92,7 @@ QT_DEPRECATED inline BiIterator2 qCopyBackward(BiIterator1 begin, BiIterator1 en } template <typename InputIterator1, typename InputIterator2> -QT_DEPRECATED inline bool qEqual(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2) +QT_DEPRECATED_X("Use std::equal") inline bool qEqual(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2) { for (; first1 != last1; ++first1, ++first2) if (!(*first1 == *first2)) @@ -101,20 +101,20 @@ QT_DEPRECATED inline bool qEqual(InputIterator1 first1, InputIterator1 last1, In } template <typename ForwardIterator, typename T> -QT_DEPRECATED inline void qFill(ForwardIterator first, ForwardIterator last, const T &val) +QT_DEPRECATED_X("Use std::fill") inline void qFill(ForwardIterator first, ForwardIterator last, const T &val) { for (; first != last; ++first) *first = val; } template <typename Container, typename T> -QT_DEPRECATED inline void qFill(Container &container, const T &val) +QT_DEPRECATED_X("Use std::fill") inline void qFill(Container &container, const T &val) { qFill(container.begin(), container.end(), val); } template <typename InputIterator, typename T> -QT_DEPRECATED inline InputIterator qFind(InputIterator first, InputIterator last, const T &val) +QT_DEPRECATED_X("Use std::find") inline InputIterator qFind(InputIterator first, InputIterator last, const T &val) { while (first != last && !(*first == val)) ++first; @@ -122,13 +122,13 @@ QT_DEPRECATED inline InputIterator qFind(InputIterator first, InputIterator last } template <typename Container, typename T> -QT_DEPRECATED inline typename Container::const_iterator qFind(const Container &container, const T &val) +QT_DEPRECATED_X("Use std::find") inline typename Container::const_iterator qFind(const Container &container, const T &val) { return qFind(container.constBegin(), container.constEnd(), val); } template <typename InputIterator, typename T, typename Size> -QT_DEPRECATED inline void qCount(InputIterator first, InputIterator last, const T &value, Size &n) +QT_DEPRECATED_X("Use std::count") inline void qCount(InputIterator first, InputIterator last, const T &value, Size &n) { for (; first != last; ++first) if (*first == value) @@ -136,7 +136,7 @@ QT_DEPRECATED inline void qCount(InputIterator first, InputIterator last, const } template <typename Container, typename T, typename Size> -QT_DEPRECATED inline void qCount(const Container &container, const T &value, Size &n) +QT_DEPRECATED_X("Use std::count") inline void qCount(const Container &container, const T &value, Size &n) { qCount(container.constBegin(), container.constEnd(), value, n); } @@ -153,7 +153,7 @@ LessThan qGreater() } #else template <typename T> -class QT_DEPRECATED qLess +class QT_DEPRECATED_X("Use std::less") qLess { public: inline bool operator()(const T &t1, const T &t2) const @@ -163,7 +163,7 @@ public: }; template <typename T> -class QT_DEPRECATED qGreater +class QT_DEPRECATED_X("Use std::greater") qGreater { public: inline bool operator()(const T &t1, const T &t2) const @@ -174,21 +174,21 @@ public: #endif template <typename RandomAccessIterator> -QT_DEPRECATED inline void qSort(RandomAccessIterator start, RandomAccessIterator end) +QT_DEPRECATED_X("Use std::sort") inline void qSort(RandomAccessIterator start, RandomAccessIterator end) { if (start != end) QAlgorithmsPrivate::qSortHelper(start, end, *start); } template <typename RandomAccessIterator, typename LessThan> -QT_DEPRECATED inline void qSort(RandomAccessIterator start, RandomAccessIterator end, LessThan lessThan) +QT_DEPRECATED_X("Use std::sort") inline void qSort(RandomAccessIterator start, RandomAccessIterator end, LessThan lessThan) { if (start != end) QAlgorithmsPrivate::qSortHelper(start, end, *start, lessThan); } template<typename Container> -QT_DEPRECATED inline void qSort(Container &c) +QT_DEPRECATED_X("Use std::sort") inline void qSort(Container &c) { #ifdef Q_CC_BOR // Work around Borland 5.5 optimizer bug @@ -199,21 +199,21 @@ QT_DEPRECATED inline void qSort(Container &c) } template <typename RandomAccessIterator> -QT_DEPRECATED inline void qStableSort(RandomAccessIterator start, RandomAccessIterator end) +QT_DEPRECATED_X("Use std::stable_sort") inline void qStableSort(RandomAccessIterator start, RandomAccessIterator end) { if (start != end) QAlgorithmsPrivate::qStableSortHelper(start, end, *start); } template <typename RandomAccessIterator, typename LessThan> -QT_DEPRECATED inline void qStableSort(RandomAccessIterator start, RandomAccessIterator end, LessThan lessThan) +QT_DEPRECATED_X("Use std::stable_sort") inline void qStableSort(RandomAccessIterator start, RandomAccessIterator end, LessThan lessThan) { if (start != end) QAlgorithmsPrivate::qStableSortHelper(start, end, *start, lessThan); } template<typename Container> -QT_DEPRECATED inline void qStableSort(Container &c) +QT_DEPRECATED_X("Use std::stable_sort") inline void qStableSort(Container &c) { #ifdef Q_CC_BOR // Work around Borland 5.5 optimizer bug @@ -224,7 +224,7 @@ QT_DEPRECATED inline void qStableSort(Container &c) } template <typename RandomAccessIterator, typename T> -QT_DEPRECATED Q_OUTOFLINE_TEMPLATE RandomAccessIterator qLowerBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value) +QT_DEPRECATED_X("Use std::lower_bound") Q_OUTOFLINE_TEMPLATE RandomAccessIterator qLowerBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value) { // Implementation is duplicated from QAlgorithmsPrivate to keep existing code // compiling. We have to allow using *begin and value with different types, @@ -247,19 +247,19 @@ QT_DEPRECATED Q_OUTOFLINE_TEMPLATE RandomAccessIterator qLowerBound(RandomAccess } template <typename RandomAccessIterator, typename T, typename LessThan> -QT_DEPRECATED Q_OUTOFLINE_TEMPLATE RandomAccessIterator qLowerBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan) +QT_DEPRECATED_X("Use std::lower_bound") Q_OUTOFLINE_TEMPLATE RandomAccessIterator qLowerBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan) { return QAlgorithmsPrivate::qLowerBoundHelper(begin, end, value, lessThan); } template <typename Container, typename T> -QT_DEPRECATED Q_OUTOFLINE_TEMPLATE typename Container::const_iterator qLowerBound(const Container &container, const T &value) +QT_DEPRECATED_X("Use std::lower_bound") Q_OUTOFLINE_TEMPLATE typename Container::const_iterator qLowerBound(const Container &container, const T &value) { return QAlgorithmsPrivate::qLowerBoundHelper(container.constBegin(), container.constEnd(), value, qLess<T>()); } template <typename RandomAccessIterator, typename T> -QT_DEPRECATED Q_OUTOFLINE_TEMPLATE RandomAccessIterator qUpperBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value) +QT_DEPRECATED_X("Use std::upper_bound") Q_OUTOFLINE_TEMPLATE RandomAccessIterator qUpperBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value) { // Implementation is duplicated from QAlgorithmsPrivate. RandomAccessIterator middle; @@ -280,19 +280,19 @@ QT_DEPRECATED Q_OUTOFLINE_TEMPLATE RandomAccessIterator qUpperBound(RandomAccess } template <typename RandomAccessIterator, typename T, typename LessThan> -QT_DEPRECATED Q_OUTOFLINE_TEMPLATE RandomAccessIterator qUpperBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan) +QT_DEPRECATED_X("Use std::upper_bound") Q_OUTOFLINE_TEMPLATE RandomAccessIterator qUpperBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan) { return QAlgorithmsPrivate::qUpperBoundHelper(begin, end, value, lessThan); } template <typename Container, typename T> -QT_DEPRECATED Q_OUTOFLINE_TEMPLATE typename Container::const_iterator qUpperBound(const Container &container, const T &value) +QT_DEPRECATED_X("Use std::upper_bound") Q_OUTOFLINE_TEMPLATE typename Container::const_iterator qUpperBound(const Container &container, const T &value) { return QAlgorithmsPrivate::qUpperBoundHelper(container.constBegin(), container.constEnd(), value, qLess<T>()); } template <typename RandomAccessIterator, typename T> -QT_DEPRECATED Q_OUTOFLINE_TEMPLATE RandomAccessIterator qBinaryFind(RandomAccessIterator begin, RandomAccessIterator end, const T &value) +QT_DEPRECATED_X("Use std::binary_search") Q_OUTOFLINE_TEMPLATE RandomAccessIterator qBinaryFind(RandomAccessIterator begin, RandomAccessIterator end, const T &value) { // Implementation is duplicated from QAlgorithmsPrivate. RandomAccessIterator it = qLowerBound(begin, end, value); @@ -304,13 +304,13 @@ QT_DEPRECATED Q_OUTOFLINE_TEMPLATE RandomAccessIterator qBinaryFind(RandomAccess } template <typename RandomAccessIterator, typename T, typename LessThan> -QT_DEPRECATED Q_OUTOFLINE_TEMPLATE RandomAccessIterator qBinaryFind(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan) +QT_DEPRECATED_X("Use std::binary_search") Q_OUTOFLINE_TEMPLATE RandomAccessIterator qBinaryFind(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan) { return QAlgorithmsPrivate::qBinaryFindHelper(begin, end, value, lessThan); } template <typename Container, typename T> -QT_DEPRECATED Q_OUTOFLINE_TEMPLATE typename Container::const_iterator qBinaryFind(const Container &container, const T &value) +QT_DEPRECATED_X("Use std::binary_search") Q_OUTOFLINE_TEMPLATE typename Container::const_iterator qBinaryFind(const Container &container, const T &value) { return QAlgorithmsPrivate::qBinaryFindHelper(container.constBegin(), container.constEnd(), value, qLess<T>()); } @@ -340,7 +340,7 @@ namespace QAlgorithmsPrivate { #if QT_DEPRECATED_SINCE(5, 2) template <typename RandomAccessIterator, typename T, typename LessThan> -QT_DEPRECATED Q_OUTOFLINE_TEMPLATE void qSortHelper(RandomAccessIterator start, RandomAccessIterator end, const T &t, LessThan lessThan) +QT_DEPRECATED_X("Use std::sort") Q_OUTOFLINE_TEMPLATE void qSortHelper(RandomAccessIterator start, RandomAccessIterator end, const T &t, LessThan lessThan) { top: int span = int(end - start); @@ -393,13 +393,13 @@ top: } template <typename RandomAccessIterator, typename T> -QT_DEPRECATED inline void qSortHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &dummy) +QT_DEPRECATED_X("Use std::sort") inline void qSortHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &dummy) { qSortHelper(begin, end, dummy, qLess<T>()); } template <typename RandomAccessIterator> -QT_DEPRECATED Q_OUTOFLINE_TEMPLATE void qReverse(RandomAccessIterator begin, RandomAccessIterator end) +QT_DEPRECATED_X("Use std::reverse") Q_OUTOFLINE_TEMPLATE void qReverse(RandomAccessIterator begin, RandomAccessIterator end) { --end; while (begin < end) @@ -407,7 +407,7 @@ QT_DEPRECATED Q_OUTOFLINE_TEMPLATE void qReverse(RandomAccessIterator begin, Ran } template <typename RandomAccessIterator> -QT_DEPRECATED Q_OUTOFLINE_TEMPLATE void qRotate(RandomAccessIterator begin, RandomAccessIterator middle, RandomAccessIterator end) +QT_DEPRECATED_X("Use std::rotate") Q_OUTOFLINE_TEMPLATE void qRotate(RandomAccessIterator begin, RandomAccessIterator middle, RandomAccessIterator end) { qReverse(begin, middle); qReverse(middle, end); @@ -415,7 +415,7 @@ QT_DEPRECATED Q_OUTOFLINE_TEMPLATE void qRotate(RandomAccessIterator begin, Rand } template <typename RandomAccessIterator, typename T, typename LessThan> -QT_DEPRECATED Q_OUTOFLINE_TEMPLATE void qMerge(RandomAccessIterator begin, RandomAccessIterator pivot, RandomAccessIterator end, T &t, LessThan lessThan) +QT_DEPRECATED_X("Use std::merge") Q_OUTOFLINE_TEMPLATE void qMerge(RandomAccessIterator begin, RandomAccessIterator pivot, RandomAccessIterator end, T &t, LessThan lessThan) { const int len1 = pivot - begin; const int len2 = end - pivot; @@ -450,7 +450,7 @@ QT_DEPRECATED Q_OUTOFLINE_TEMPLATE void qMerge(RandomAccessIterator begin, Rando } template <typename RandomAccessIterator, typename T, typename LessThan> -QT_DEPRECATED Q_OUTOFLINE_TEMPLATE void qStableSortHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &t, LessThan lessThan) +QT_DEPRECATED_X("Use std::stable_sort") Q_OUTOFLINE_TEMPLATE void qStableSortHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &t, LessThan lessThan) { const int span = end - begin; if (span < 2) @@ -463,13 +463,13 @@ QT_DEPRECATED Q_OUTOFLINE_TEMPLATE void qStableSortHelper(RandomAccessIterator b } template <typename RandomAccessIterator, typename T> -QT_DEPRECATED inline void qStableSortHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &dummy) +QT_DEPRECATED_X("Use std::stable_sort") inline void qStableSortHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &dummy) { qStableSortHelper(begin, end, dummy, qLess<T>()); } template <typename RandomAccessIterator, typename T, typename LessThan> -QT_DEPRECATED Q_OUTOFLINE_TEMPLATE RandomAccessIterator qLowerBoundHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan) +QT_DEPRECATED_X("Use std::lower_bound") Q_OUTOFLINE_TEMPLATE RandomAccessIterator qLowerBoundHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan) { RandomAccessIterator middle; int n = int(end - begin); @@ -490,7 +490,7 @@ QT_DEPRECATED Q_OUTOFLINE_TEMPLATE RandomAccessIterator qLowerBoundHelper(Random template <typename RandomAccessIterator, typename T, typename LessThan> -QT_DEPRECATED Q_OUTOFLINE_TEMPLATE RandomAccessIterator qUpperBoundHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan) +QT_DEPRECATED_X("Use std::upper_bound") Q_OUTOFLINE_TEMPLATE RandomAccessIterator qUpperBoundHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan) { RandomAccessIterator middle; int n = end - begin; @@ -510,7 +510,7 @@ QT_DEPRECATED Q_OUTOFLINE_TEMPLATE RandomAccessIterator qUpperBoundHelper(Random } template <typename RandomAccessIterator, typename T, typename LessThan> -QT_DEPRECATED Q_OUTOFLINE_TEMPLATE RandomAccessIterator qBinaryFindHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan) +QT_DEPRECATED_X("Use std::binary_search") Q_OUTOFLINE_TEMPLATE RandomAccessIterator qBinaryFindHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan) { RandomAccessIterator it = qLowerBoundHelper(begin, end, value, lessThan); diff --git a/src/corelib/tools/qcollator_win.cpp b/src/corelib/tools/qcollator_win.cpp index 8e59000946..9a672a0505 100644 --- a/src/corelib/tools/qcollator_win.cpp +++ b/src/corelib/tools/qcollator_win.cpp @@ -125,9 +125,15 @@ int QCollator::compare(const QChar *s1, int len1, const QChar *s2, int len2) con // comparing strings, the value 2 can be subtracted from a nonzero return value. Then, the // meaning of <0, ==0, and >0 is consistent with the C runtime. +#ifndef Q_OS_WINRT return CompareString(LOCALE_USER_DEFAULT, d->collator, reinterpret_cast<const wchar_t*>(s1), len1, reinterpret_cast<const wchar_t*>(s2), len2) - 2; +#else // !Q_OS_WINRT + return CompareStringEx(LOCALE_NAME_USER_DEFAULT, d->collator, + reinterpret_cast<LPCWSTR>(s1), len1, + reinterpret_cast<LPCWSTR>(s2), len2, NULL, NULL, 0) - 2; +#endif // Q_OS_WINRT } int QCollator::compare(const QString &str1, const QString &str2) const @@ -142,13 +148,31 @@ int QCollator::compare(const QStringRef &s1, const QStringRef &s2) const QCollatorSortKey QCollator::sortKey(const QString &string) const { +#ifndef Q_OS_WINRT int size = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | d->collator, reinterpret_cast<const wchar_t*>(string.constData()), string.size(), 0, 0); +#elif defined(Q_OS_WINPHONE) + int size = 0; + Q_UNIMPLEMENTED(); +#else // Q_OS_WINPHONE + int size = LCMapStringEx(LOCALE_NAME_USER_DEFAULT, LCMAP_SORTKEY | d->collator, + reinterpret_cast<LPCWSTR>(string.constData()), string.size(), + 0, 0, NULL, NULL, 0); +#endif // !Q_OS_WINPHONE QString ret(size, Qt::Uninitialized); +#ifndef Q_OS_WINRT int finalSize = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | d->collator, reinterpret_cast<const wchar_t*>(string.constData()), string.size(), reinterpret_cast<wchar_t*>(ret.data()), ret.size()); +#elif defined(Q_OS_WINPHONE) + int finalSize = 0; +#else // Q_OS_WINPHONE + int finalSize = LCMapStringEx(LOCALE_NAME_USER_DEFAULT, LCMAP_SORTKEY | d->collator, + reinterpret_cast<LPCWSTR>(string.constData()), string.size(), + reinterpret_cast<LPWSTR>(ret.data()), ret.size(), + NULL, NULL, 0); +#endif // !Q_OS_WINPHONE if (finalSize == 0) { qWarning() << "there were problems when generating the ::sortKey by LCMapStringW with error:" << GetLastError(); } diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index 42721c018f..a95c7f53f7 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -61,6 +61,9 @@ # ifdef Q_OS_WINCE # include "qfunctions_wince.h" # endif +# ifdef Q_OS_WINRT +# include "qfunctions_winrt.h" +# endif #endif #if defined(Q_OS_MAC) diff --git a/src/corelib/tools/qlocale_win.cpp b/src/corelib/tools/qlocale_win.cpp index 3a083582c9..885c77c46d 100644 --- a/src/corelib/tools/qlocale_win.cpp +++ b/src/corelib/tools/qlocale_win.cpp @@ -55,12 +55,32 @@ # include <time.h> #endif +#ifdef Q_OS_WINRT +#include <wrl.h> +#include <windows.foundation.h> +#include <windows.foundation.collections.h> +#ifndef Q_OS_WINPHONE +#include <windows.globalization.h> +#endif +#endif // Q_OS_WINRT + QT_BEGIN_NAMESPACE +#ifndef Q_OS_WINRT static QByteArray getWinLocaleName(LCID id = LOCALE_USER_DEFAULT); static const char *winLangCodeToIsoName(int code); static QString winIso639LangName(LCID id = LOCALE_USER_DEFAULT); static QString winIso3116CtryName(LCID id = LOCALE_USER_DEFAULT); +#else // !Q_OS_WINRT +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows::Foundation; + +static QByteArray getWinLocaleName(LPWSTR id = LOCALE_NAME_USER_DEFAULT); +static const char *winLangCodeToIsoName(int code); +static QString winIso639LangName(LPWSTR id = LOCALE_NAME_USER_DEFAULT); +static QString winIso3116CtryName(LPWSTR id = LOCALE_NAME_USER_DEFAULT); +#endif // Q_OS_WINRT #ifndef QT_NO_SYSTEMLOCALE @@ -124,14 +144,23 @@ private: }; // cached values: +#ifndef Q_OS_WINRT LCID lcid; +#else + WCHAR lcName[LOCALE_NAME_MAX_LENGTH]; +#endif SubstitutionType substitutionType; QChar zero; + int getLocaleInfo(LCTYPE type, LPWSTR data, int size); QString getLocaleInfo(LCTYPE type, int maxlen = 0); int getLocaleInfo_int(LCTYPE type, int maxlen = 0); QChar getLocaleInfo_qchar(LCTYPE type); + int getCurrencyFormat(DWORD flags, LPCWSTR value, const CURRENCYFMTW *format, LPWSTR data, int size); + int getDateFormat(DWORD flags, const SYSTEMTIME * date, LPCWSTR format, LPWSTR data, int size); + int getTimeFormat(DWORD flags, const SYSTEMTIME *date, LPCWSTR format, LPWSTR data, int size); + SubstitutionType substitution(); QString &substituteDigits(QString &string); @@ -143,20 +172,60 @@ Q_GLOBAL_STATIC(QSystemLocalePrivate, systemLocalePrivate) QSystemLocalePrivate::QSystemLocalePrivate() : substitutionType(SUnknown) { +#ifndef Q_OS_WINRT lcid = GetUserDefaultLCID(); +#else + GetUserDefaultLocaleName(lcName, LOCALE_NAME_MAX_LENGTH); +#endif +} + +inline int QSystemLocalePrivate::getCurrencyFormat(DWORD flags, LPCWSTR value, const CURRENCYFMTW *format, LPWSTR data, int size) +{ +#ifndef Q_OS_WINRT + return GetCurrencyFormat(lcid, flags, value, format, data, size); +#else + return GetCurrencyFormatEx(lcName, flags, value, format, data, size); +#endif +} + +inline int QSystemLocalePrivate::getDateFormat(DWORD flags, const SYSTEMTIME * date, LPCWSTR format, LPWSTR data, int size) +{ +#ifndef Q_OS_WINRT + return GetDateFormat(lcid, flags, date, format, data, size); +#else + return GetDateFormatEx(lcName, flags, date, format, data, size, NULL); +#endif +} + +inline int QSystemLocalePrivate::getTimeFormat(DWORD flags, const SYSTEMTIME *date, LPCWSTR format, LPWSTR data, int size) +{ +#ifndef Q_OS_WINRT + return GetTimeFormat(lcid, flags, date, format, data, size); +#else + return GetTimeFormatEx(lcName, flags, date, format, data, size); +#endif +} + +inline int QSystemLocalePrivate::getLocaleInfo(LCTYPE type, LPWSTR data, int size) +{ +#ifndef Q_OS_WINRT + return GetLocaleInfo(lcid, type, data, size); +#else + return GetLocaleInfoEx(lcName, type, data, size); +#endif } QString QSystemLocalePrivate::getLocaleInfo(LCTYPE type, int maxlen) { QVarLengthArray<wchar_t, 64> buf(maxlen ? maxlen : 64); - if (!GetLocaleInfo(lcid, type, buf.data(), buf.size())) + if (!getLocaleInfo(type, buf.data(), buf.size())) return QString(); if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { - int cnt = GetLocaleInfo(lcid, type, 0, 0); + int cnt = getLocaleInfo(type, 0, 0); if (cnt == 0) return QString(); buf.resize(cnt); - if (!GetLocaleInfo(lcid, type, buf.data(), buf.size())) + if (!getLocaleInfo(type, buf.data(), buf.size())) return QString(); } return QString::fromWCharArray(buf.data()); @@ -180,7 +249,7 @@ QSystemLocalePrivate::SubstitutionType QSystemLocalePrivate::substitution() { if (substitutionType == SUnknown) { wchar_t buf[8]; - if (!GetLocaleInfo(lcid, LOCALE_IDIGITSUBSTITUTION, buf, 8)) { + if (!getLocaleInfo(LOCALE_IDIGITSUBSTITUTION, buf, 8)) { substitutionType = QSystemLocalePrivate::SNever; return substitutionType; } @@ -192,7 +261,7 @@ QSystemLocalePrivate::SubstitutionType QSystemLocalePrivate::substitution() substitutionType = QSystemLocalePrivate::SAlways; else { wchar_t digits[11]; - if (!GetLocaleInfo(lcid, LOCALE_SNATIVEDIGITS, digits, 11)) { + if (!getLocaleInfo(LOCALE_SNATIVEDIGITS, digits, 11)) { substitutionType = QSystemLocalePrivate::SNever; return substitutionType; } @@ -337,7 +406,7 @@ QVariant QSystemLocalePrivate::toString(const QDate &date, QLocale::FormatType t DWORD flags = (type == QLocale::LongFormat ? DATE_LONGDATE : DATE_SHORTDATE); wchar_t buf[255]; - if (GetDateFormat(lcid, flags, &st, NULL, buf, 255)) { + if (getDateFormat(flags, &st, NULL, buf, 255)) { QString format = QString::fromWCharArray(buf); if (substitution() == SAlways) substituteDigits(format); @@ -361,7 +430,7 @@ QVariant QSystemLocalePrivate::toString(const QTime &time, QLocale::FormatType t flags = TIME_NOSECONDS; wchar_t buf[255]; - if (GetTimeFormat(lcid, flags, &st, NULL, buf, 255)) { + if (getTimeFormat(flags, &st, NULL, buf, 255)) { QString format = QString::fromWCharArray(buf); if (substitution() == SAlways) substituteDigits(format); @@ -379,7 +448,7 @@ QVariant QSystemLocalePrivate::measurementSystem() { wchar_t output[2]; - if (GetLocaleInfo(lcid, LOCALE_IMEASURE, output, 2)) { + if (getLocaleInfo(LOCALE_IMEASURE, output, 2)) { QString iMeasure = QString::fromWCharArray(output); if (iMeasure == QLatin1String("1")) { return QLocale::ImperialSystem; @@ -393,7 +462,7 @@ QVariant QSystemLocalePrivate::amText() { wchar_t output[15]; // maximum length including terminating zero character for Win2003+ - if (GetLocaleInfo(lcid, LOCALE_S1159, output, 15)) { + if (getLocaleInfo(LOCALE_S1159, output, 15)) { return QString::fromWCharArray(output); } @@ -404,7 +473,7 @@ QVariant QSystemLocalePrivate::pmText() { wchar_t output[15]; // maximum length including terminating zero character for Win2003+ - if (GetLocaleInfo(lcid, LOCALE_S2359, output, 15)) { + if (getLocaleInfo(LOCALE_S2359, output, 15)) { return QString::fromWCharArray(output); } @@ -415,7 +484,7 @@ QVariant QSystemLocalePrivate::firstDayOfWeek() { wchar_t output[4]; // maximum length including terminating zero character for Win2003+ - if (GetLocaleInfo(lcid, LOCALE_IFIRSTDAYOFWEEK, output, 4)) + if (getLocaleInfo(LOCALE_IFIRSTDAYOFWEEK, output, 4)) return QString::fromWCharArray(output).toUInt()+1; return 1; @@ -426,20 +495,20 @@ QVariant QSystemLocalePrivate::currencySymbol(QLocale::CurrencySymbolFormat form wchar_t buf[13]; switch (format) { case QLocale::CurrencySymbol: - if (GetLocaleInfo(lcid, LOCALE_SCURRENCY, buf, 13)) + if (getLocaleInfo(LOCALE_SCURRENCY, buf, 13)) return QString::fromWCharArray(buf); break; case QLocale::CurrencyIsoCode: - if (GetLocaleInfo(lcid, LOCALE_SINTLSYMBOL, buf, 9)) + if (getLocaleInfo(LOCALE_SINTLSYMBOL, buf, 9)) return QString::fromWCharArray(buf); break; case QLocale::CurrencyDisplayName: { QVarLengthArray<wchar_t, 64> buf(64); - if (!GetLocaleInfo(lcid, LOCALE_SNATIVECURRNAME, buf.data(), buf.size())) { + if (!getLocaleInfo(LOCALE_SNATIVECURRNAME, buf.data(), buf.size())) { if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) break; buf.resize(255); // should be large enough, right? - if (!GetLocaleInfo(lcid, LOCALE_SNATIVECURRNAME, buf.data(), buf.size())) + if (!getLocaleInfo(LOCALE_SNATIVECURRNAME, buf.data(), buf.size())) break; } return QString::fromWCharArray(buf.data()); @@ -486,14 +555,14 @@ QVariant QSystemLocalePrivate::toCurrencyString(const QSystemLocale::CurrencyToS CURRENCYFMT format; CURRENCYFMT *pformat = NULL; if (!arg.symbol.isEmpty()) { - format.NumDigits = getLocaleInfo_int(lcid, LOCALE_ICURRDIGITS); - format.LeadingZero = getLocaleInfo_int(lcid, LOCALE_ILZERO); - decimalSep = getLocaleInfo(lcid, LOCALE_SMONDECIMALSEP); + format.NumDigits = getLocaleInfo_int(LOCALE_ICURRDIGITS); + format.LeadingZero = getLocaleInfo_int(LOCALE_ILZERO); + decimalSep = getLocaleInfo(LOCALE_SMONDECIMALSEP); format.lpDecimalSep = (wchar_t *)decimalSep.utf16(); - thousandSep = getLocaleInfo(lcid, LOCALE_SMONTHOUSANDSEP); + thousandSep = getLocaleInfo(LOCALE_SMONTHOUSANDSEP); format.lpThousandSep = (wchar_t *)thousandSep.utf16(); - format.NegativeOrder = getLocaleInfo_int(lcid, LOCALE_INEGCURR); - format.PositiveOrder = getLocaleInfo_int(lcid, LOCALE_ICURRENCY); + format.NegativeOrder = getLocaleInfo_int(LOCALE_INEGCURR); + format.PositiveOrder = getLocaleInfo_int(LOCALE_ICURRENCY); format.lpCurrencySymbol = (wchar_t *)arg.symbol.utf16(); // grouping is complicated and ugly: @@ -502,7 +571,7 @@ QVariant QSystemLocalePrivate::toCurrencyString(const QSystemLocale::CurrencyToS // int(30) == "123456,789.00" == string("3;0;0") // int(32) == "12,34,56,789.00" == string("3;2;0") // int(320)== "1234,56,789.00" == string("3;2") - QString groupingStr = getLocaleInfo(lcid, LOCALE_SMONGROUPING); + QString groupingStr = getLocaleInfo(LOCALE_SMONGROUPING); format.Grouping = groupingStr.remove(QLatin1Char(';')).toInt(); if (format.Grouping % 10 == 0) // magic format.Grouping /= 10; @@ -511,13 +580,13 @@ QVariant QSystemLocalePrivate::toCurrencyString(const QSystemLocale::CurrencyToS pformat = &format; } - int ret = ::GetCurrencyFormat(lcid, 0, reinterpret_cast<const wchar_t *>(value.utf16()), + int ret = getCurrencyFormat(0, reinterpret_cast<const wchar_t *>(value.utf16()), pformat, out.data(), out.size()); if (ret == 0 && GetLastError() == ERROR_INSUFFICIENT_BUFFER) { - ret = ::GetCurrencyFormat(lcid, 0, reinterpret_cast<const wchar_t *>(value.utf16()), + ret = getCurrencyFormat(0, reinterpret_cast<const wchar_t *>(value.utf16()), pformat, out.data(), 0); out.resize(ret); - ::GetCurrencyFormat(lcid, 0, reinterpret_cast<const wchar_t *>(value.utf16()), + getCurrencyFormat(0, reinterpret_cast<const wchar_t *>(value.utf16()), pformat, out.data(), out.size()); } @@ -536,11 +605,13 @@ QVariant QSystemLocalePrivate::uiLanguages() PWSTR pwszLanguagesBuffer, PULONG pcchLanguagesBuffer); static GetUserPreferredUILanguagesFunc GetUserPreferredUILanguages_ptr = 0; +#ifndef Q_OS_WINRT if (!GetUserPreferredUILanguages_ptr) { QSystemLibrary lib(QLatin1String("kernel32")); if (lib.load()) GetUserPreferredUILanguages_ptr = (GetUserPreferredUILanguagesFunc)lib.resolve("GetUserPreferredUILanguages"); } +#endif // !Q_OS_WINRT if (GetUserPreferredUILanguages_ptr) { unsigned long cnt = 0; QVarLengthArray<wchar_t, 64> buf(64); @@ -568,8 +639,39 @@ QVariant QSystemLocalePrivate::uiLanguages() } } +#ifndef Q_OS_WINRT // old Windows before Vista return QStringList(QString::fromLatin1(winLangCodeToIsoName(GetUserDefaultUILanguage()))); +#else // !Q_OS_WINRT + QStringList result; +#ifndef Q_OS_WINPHONE + ComPtr<ABI::Windows::Globalization::IApplicationLanguagesStatics> appLanguagesStatics; + if (FAILED(GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Globalization_ApplicationLanguages).Get(), &appLanguagesStatics))) { + qWarning("Could not obtain ApplicationLanguagesStatic"); + return QStringList(); + } + + ComPtr<ABI::Windows::Foundation::Collections::IVectorView<HSTRING> > languageList; + appLanguagesStatics->get_ManifestLanguages(&languageList); + + if (!languageList) + return QStringList(); + + unsigned int size; + languageList->get_Size(&size); + for (unsigned int i = 0; i < size; ++i) { + HSTRING language; + languageList->GetAt(i, &language); + UINT32 length; + PCWSTR rawString = WindowsGetStringRawBuffer(language, &length); + result << QString::fromWCharArray(rawString, length); + } +#else // !Q_OS_WINPHONE + result << QString::fromWCharArray(lcName); +#endif // Q_OS_WINPHONE + + return result; +#endif // Q_OS_WINRT } QVariant QSystemLocalePrivate::nativeLanguageName() @@ -589,7 +691,11 @@ QVariant QSystemLocalePrivate::nativeCountryName() void QSystemLocalePrivate::update() { +#ifndef Q_OS_WINRT lcid = GetUserDefaultLCID(); +#else + GetUserDefaultLocaleName(lcName, LOCALE_NAME_MAX_LENGTH); +#endif substitutionType = SUnknown; zero = QChar(); } @@ -903,7 +1009,11 @@ static const char *winLangCodeToIsoName(int code) } +#ifndef Q_OS_WINRT static QString winIso639LangName(LCID id) +#else +static QString winIso639LangName(LPWSTR id) +#endif { QString result; @@ -911,7 +1021,11 @@ static QString winIso639LangName(LCID id) // the language code QString lang_code; wchar_t out[256]; - if (GetLocaleInfo(id, LOCALE_ILANGUAGE, out, 255)) // ### shouldn't use them according to msdn +#ifndef Q_OS_WINRT + if (GetLocaleInfo(id, LOCALE_ILANGUAGE, out, 255)) +#else + if (GetLocaleInfoEx(id, LOCALE_ILANGUAGE, out, 255)) +#endif lang_code = QString::fromWCharArray(out); if (!lang_code.isEmpty()) { @@ -934,27 +1048,47 @@ static QString winIso639LangName(LCID id) return result; // not one of the problematic languages - do the usual lookup - if (GetLocaleInfo(id, LOCALE_SISO639LANGNAME , out, 255)) +#ifndef Q_OS_WINRT + if (GetLocaleInfo(id, LOCALE_SISO639LANGNAME, out, 255)) +#else + if (GetLocaleInfoEx(id, LOCALE_SISO639LANGNAME, out, 255)) +#endif result = QString::fromWCharArray(out); return result; } +#ifndef Q_OS_WINRT static QString winIso3116CtryName(LCID id) +#else +static QString winIso3116CtryName(LPWSTR id) +#endif { QString result; wchar_t out[256]; +#ifndef Q_OS_WINRT if (GetLocaleInfo(id, LOCALE_SISO3166CTRYNAME, out, 255)) +#else + if (GetLocaleInfoEx(id, LOCALE_SISO3166CTRYNAME, out, 255)) +#endif result = QString::fromWCharArray(out); return result; } +#ifndef Q_OS_WINRT static QByteArray getWinLocaleName(LCID id) +#else +static QByteArray getWinLocaleName(LPWSTR id) +#endif { QByteArray result; +#ifndef Q_OS_WINRT if (id == LOCALE_USER_DEFAULT) { +#else + if (QString::fromWCharArray(id) == QString::fromWCharArray(LOCALE_NAME_USER_DEFAULT)) { +#endif static QByteArray langEnvVar = qgetenv("LANG"); result = langEnvVar; QString lang, script, cntry; @@ -972,9 +1106,17 @@ static QByteArray getWinLocaleName(LCID id) #if defined(Q_OS_WINCE) result = winLangCodeToIsoName(id != LOCALE_USER_DEFAULT ? id : GetUserDefaultLCID()); -#else +#else // !Q_OS_WINCE +# ifndef Q_OS_WINRT if (id == LOCALE_USER_DEFAULT) id = GetUserDefaultLCID(); +# else // !Q_OS_WINRT + WCHAR lcName[LOCALE_NAME_MAX_LENGTH]; + if (QString::fromWCharArray(id) == QString::fromWCharArray(LOCALE_NAME_USER_DEFAULT)) { + GetUserDefaultLocaleName(lcName, LOCALE_NAME_MAX_LENGTH); + id = lcName; + } +# endif // Q_OS_WINRT QString resultuage = winIso639LangName(id); QString country = winIso3116CtryName(id); result = resultuage.toLatin1(); @@ -982,14 +1124,20 @@ static QByteArray getWinLocaleName(LCID id) result += '_'; result += country.toLatin1(); } -#endif +#endif // !Q_OS_WINCE return result; } Q_CORE_EXPORT QLocale qt_localeFromLCID(LCID id) { +#ifndef Q_OS_WINRT return QLocale(QString::fromLatin1(getWinLocaleName(id))); +#else // !Q_OS_WINRT + WCHAR name[LOCALE_NAME_MAX_LENGTH]; + LCIDToLocaleName(id, name, LOCALE_NAME_MAX_LENGTH, 0); + return QLocale(QString::fromLatin1(getWinLocaleName(name))); +#endif // Q_OS_WINRT } QT_END_NAMESPACE diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 3976f2cb6f..9544062dd9 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2013 Intel Corporation ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -3158,6 +3159,15 @@ int QString::count(const QStringRef &str, Qt::CaseSensitivity cs) const \sa indexOf(), count() */ +/*! \fn bool QString::contains(QLatin1String str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const + \since 5.3 + + \overload contains() + + Returns \c true if this string contains an occurrence of the latin-1 string + \a str; otherwise returns \c false. +*/ + /*! \fn bool QString::contains(QChar ch, Qt::CaseSensitivity cs = Qt::CaseSensitive) const \overload contains() @@ -3937,13 +3947,9 @@ static inline __m128i mergeQuestionMarks(__m128i chunk) } #endif -static QByteArray toLatin1_helper(const QChar *data, int length) +static void toLatin1_helper(uchar *dst, const ushort *src, int length) { - QByteArray ba; if (length) { - ba.resize(length); - const ushort *src = reinterpret_cast<const ushort *>(data); - uchar *dst = (uchar*) ba.data(); #if defined(__SSE2__) if (length >= 16) { const int chunkCount = length >> 4; // divided by 16 @@ -3994,10 +4000,60 @@ static QByteArray toLatin1_helper(const QChar *data, int length) ++src; } } +} + +QByteArray QString::toLatin1_helper(const QString &string) +{ + if (Q_UNLIKELY(string.isNull())) + return QByteArray(); + + return toLatin1_helper(string.constData(), string.length()); +} + +QByteArray QString::toLatin1_helper(const QChar *data, int length) +{ + QByteArray ba(length, Qt::Uninitialized); + + // since we own the only copy, we're going to const_cast the constData; + // that avoids an unnecessary call to detach() and expansion code that will never get used + QT_PREPEND_NAMESPACE(toLatin1_helper)(reinterpret_cast<uchar *>(const_cast<char *>(ba.constData())), + reinterpret_cast<const ushort *>(data), length); return ba; } +QByteArray QString::toLatin1_helper_inplace(QString &s) +{ + if (!s.isDetached()) + return s.toLatin1(); + + // We can return our own buffer to the caller. + // Conversion to Latin-1 always shrinks the buffer by half. + const ushort *data = reinterpret_cast<const ushort *>(s.constData()); + uint length = s.size(); + + // Swap the d pointers. + // Kids, avert your eyes. Don't try this at home. + QArrayData *ba_d = s.d; + + // multiply the allocated capacity by sizeof(ushort) + ba_d->alloc *= sizeof(ushort); + + // reset ourselves to QString() + s.d = QString().d; + + // do the in-place conversion + uchar *dst = reinterpret_cast<uchar *>(ba_d->data()); + QT_PREPEND_NAMESPACE(toLatin1_helper)(dst, data, length); + dst[length] = '\0'; + + QByteArrayDataPtr badptr = { ba_d }; + return QByteArray(badptr); +} + + /*! + \fn QByteArray QString::toLatin1() const + Returns a Latin-1 representation of the string as a QByteArray. The returned byte array is undefined if the string contains non-Latin1 @@ -4006,10 +4062,6 @@ static QByteArray toLatin1_helper(const QChar *data, int length) \sa fromLatin1(), toUtf8(), toLocal8Bit(), QTextCodec */ -QByteArray QString::toLatin1() const -{ - return toLatin1_helper(unicode(), length()); -} /*! \fn QByteArray QString::toAscii() const @@ -4024,19 +4076,9 @@ QByteArray QString::toLatin1() const \sa fromAscii(), toLatin1(), toUtf8(), toLocal8Bit(), QTextCodec */ -#if !defined(Q_OS_MAC) && defined(Q_OS_UNIX) && !defined(QT_USE_ICU) -static QByteArray toLocal8Bit_helper(const QChar *data, int length) -{ -#ifndef QT_NO_TEXTCODEC - QTextCodec *localeCodec = QTextCodec::codecForLocale(); - if (localeCodec) - return localeCodec->fromUnicode(data, length); -#endif // QT_NO_TEXTCODEC - return toLatin1_helper(data, length); -} -#endif - /*! + \fn QByteArray QString::toLocal8Bit() const + 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. @@ -4051,17 +4093,21 @@ static QByteArray toLocal8Bit_helper(const QChar *data, int length) \sa fromLocal8Bit(), toLatin1(), toUtf8(), QTextCodec */ -QByteArray QString::toLocal8Bit() const + +QByteArray QString::toLocal8Bit_helper(const QChar *data, int size) { #ifndef QT_NO_TEXTCODEC QTextCodec *localeCodec = QTextCodec::codecForLocale(); if (localeCodec) - return localeCodec->fromUnicode(*this); + return localeCodec->fromUnicode(data, size); #endif // QT_NO_TEXTCODEC - return toLatin1(); + return toLatin1_helper(data, size); } + /*! + \fn QByteArray QString::toUtf8() const + 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 @@ -4077,12 +4123,13 @@ QByteArray QString::toLocal8Bit() const \sa fromUtf8(), toLatin1(), toLocal8Bit(), QTextCodec */ -QByteArray QString::toUtf8() const + +QByteArray QString::toUtf8_helper(const QString &str) { - if (isNull()) + if (str.isNull()) return QByteArray(); - return QUtf8::convertFromUnicode(constData(), length(), 0); + return QUtf8::convertFromUnicode(str.constData(), str.length()); } /*! @@ -4270,7 +4317,7 @@ QString QString::fromUtf8_helper(const char *str, int size) return QString(); Q_ASSERT(size != -1); - return QUtf8::convertToUnicode(str, size, 0); + return QUtf8::convertToUnicode(str, size); } /*! @@ -5109,7 +5156,11 @@ int QString::localeAwareCompare_helper(const QChar *data1, int length1, return ucstrcmp(data1, length1, data2, length2); #if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) +#ifndef Q_OS_WINRT int res = CompareString(GetUserDefaultLCID(), 0, (wchar_t*)data1, length1, (wchar_t*)data2, length2); +#else + int res = CompareStringEx(LOCALE_NAME_USER_DEFAULT, 0, (LPCWSTR)data1, length1, (LPCWSTR)data2, length2, NULL, NULL, 0); +#endif switch (res) { case CSTR_LESS_THAN: @@ -9279,7 +9330,7 @@ static inline bool qt_ends_with(const QChar *haystack, int haystackLen, */ QByteArray QStringRef::toLatin1() const { - return toLatin1_helper(unicode(), length()); + return QString::toLatin1_helper(unicode(), length()); } /*! diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index 0a0a609728..01ddf669f5 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -316,6 +316,7 @@ public: inline bool contains(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; inline bool contains(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + inline bool contains(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; inline bool contains(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; int count(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; int count(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; @@ -460,9 +461,24 @@ public: const ushort *utf16() const; +#if defined(Q_COMPILER_REF_QUALIFIERS) && !defined(QT_COMPILING_QSTRING_COMPAT_CPP) + QByteArray toLatin1() const & Q_REQUIRED_RESULT + { return toLatin1_helper(*this); } + QByteArray toLatin1() && Q_REQUIRED_RESULT + { return toLatin1_helper_inplace(*this); } + QByteArray toUtf8() const & Q_REQUIRED_RESULT + { return toUtf8_helper(*this); } + QByteArray toUtf8() && Q_REQUIRED_RESULT + { return toUtf8_helper(*this); } + QByteArray toLocal8Bit() const & Q_REQUIRED_RESULT + { return toLocal8Bit_helper(constData(), size()); } + QByteArray toLocal8Bit() && Q_REQUIRED_RESULT + { return toLocal8Bit_helper(constData(), size()); } +#else QByteArray toLatin1() const Q_REQUIRED_RESULT; QByteArray toUtf8() const Q_REQUIRED_RESULT; QByteArray toLocal8Bit() const Q_REQUIRED_RESULT; +#endif QVector<uint> toUcs4() const Q_REQUIRED_RESULT; // note - this are all inline so we can benefit from strlen() compile time optimizations @@ -717,6 +733,11 @@ private: static Data *fromAscii_helper(const char *str, int size = -1); static QString fromUtf8_helper(const char *str, int size); static QString fromLocal8Bit_helper(const char *, int size); + static QByteArray toLatin1_helper(const QString &); + static QByteArray toLatin1_helper(const QChar *data, int size); + static QByteArray toLatin1_helper_inplace(QString &); + static QByteArray toUtf8_helper(const QString &); + static QByteArray toLocal8Bit_helper(const QChar *data, int size); static int toUcs4_helper(const ushort *uc, int length, uint *out); void replace_helper(uint *indices, int nIndices, int blen, const QChar *after, int alen); friend class QCharRef; @@ -969,6 +990,8 @@ inline bool QString::contains(const QString &s, Qt::CaseSensitivity cs) const { return indexOf(s, 0, cs) != -1; } inline bool QString::contains(const QStringRef &s, Qt::CaseSensitivity cs) const { return indexOf(s, 0, cs) != -1; } +inline bool QString::contains(QLatin1String s, Qt::CaseSensitivity cs) const +{ return indexOf(s, 0, cs) != -1; } inline bool QString::contains(QChar c, Qt::CaseSensitivity cs) const { return indexOf(c, 0, cs) != -1; } diff --git a/src/corelib/tools/qstring_compat.cpp b/src/corelib/tools/qstring_compat.cpp new file mode 100644 index 0000000000..34c37a9cb8 --- /dev/null +++ b/src/corelib/tools/qstring_compat.cpp @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Intel Corporation +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#if defined(QSTRING_H) && !defined(QT_BOOTSTRAPPED) +# error "This file cannot be compiled with pre-compiled headers" +// (unless it's configure.exe, which is bootstrapped) +#endif +#define QT_COMPILING_QSTRING_COMPAT_CPP + +#include "qstring.h" + +QT_BEGIN_NAMESPACE + +// all these implementations must be the same as the inline versions in qstring.h +QByteArray QString::toLatin1() const +{ + return toLatin1_helper(*this); +} + +QByteArray QString::toLocal8Bit() const +{ + return toLocal8Bit_helper(constData(), size()); +} + +QByteArray QString::toUtf8() const +{ + return toUtf8_helper(*this); +} + +QT_END_NAMESPACE diff --git a/src/corelib/tools/qtimezone.cpp b/src/corelib/tools/qtimezone.cpp index a8ed8739c3..d48c8da978 100644 --- a/src/corelib/tools/qtimezone.cpp +++ b/src/corelib/tools/qtimezone.cpp @@ -65,7 +65,8 @@ static QTimeZonePrivate *newBackendTimeZone() return new QMacTimeZonePrivate(); #elif defined Q_OS_UNIX return new QTzTimeZonePrivate(); -#elif defined Q_OS_WIN + // Registry based timezone backend not available on WinRT +#elif defined Q_OS_WIN && !defined Q_OS_WINRT return new QWinTimeZonePrivate(); #elif defined QT_USE_ICU return new QIcuTimeZonePrivate(); @@ -89,7 +90,8 @@ static QTimeZonePrivate *newBackendTimeZone(const QByteArray &olsenId) return new QMacTimeZonePrivate(olsenId); #elif defined Q_OS_UNIX return new QTzTimeZonePrivate(olsenId); -#elif defined Q_OS_WIN + // Registry based timezone backend not available on WinRT +#elif defined Q_OS_WIN && !defined Q_OS_WINRT return new QWinTimeZonePrivate(olsenId); #elif defined QT_USE_ICU return new QIcuTimeZonePrivate(olsenId); diff --git a/src/corelib/tools/qtimezoneprivate_tz.cpp b/src/corelib/tools/qtimezoneprivate_tz.cpp index 1fb6bb1b5a..a1607f6577 100644 --- a/src/corelib/tools/qtimezoneprivate_tz.cpp +++ b/src/corelib/tools/qtimezoneprivate_tz.cpp @@ -134,6 +134,8 @@ struct QTzType { bool tz_ttisgmt; // Is in UTC time bool tz_ttisstd; // Is in Standard time }; +Q_DECLARE_TYPEINFO(QTzType, Q_PRIMITIVE_TYPE); + // TZ File parsing diff --git a/src/corelib/tools/qvarlengtharray.h b/src/corelib/tools/qvarlengtharray.h index 309d2a2dca..bfa0bbbbb1 100644 --- a/src/corelib/tools/qvarlengtharray.h +++ b/src/corelib/tools/qvarlengtharray.h @@ -107,6 +107,10 @@ public: inline int capacity() const { return a; } inline void reserve(int size); + inline int indexOf(const T &t, int from = 0) const; + inline int lastIndexOf(const T &t, int from = -1) const; + inline bool contains(const T &t) const; + inline T &operator[](int idx) { Q_ASSERT(idx >= 0 && idx < s); return ptr[idx]; @@ -229,6 +233,51 @@ Q_INLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::reserve(int asize) { if (asize > a) realloc(s, asize); } template <class T, int Prealloc> +Q_INLINE_TEMPLATE int QVarLengthArray<T, Prealloc>::indexOf(const T &t, int from) const +{ + if (from < 0) + from = qMax(from + s, 0); + if (from < s) { + T *n = ptr + from - 1; + T *e = ptr + s; + while (++n != e) + if (*n == t) + return n - ptr; + } + return -1; +} + +template <class T, int Prealloc> +Q_INLINE_TEMPLATE int QVarLengthArray<T, Prealloc>::lastIndexOf(const T &t, int from) const +{ + if (from < 0) + from += s; + else if (from >= s) + from = s - 1; + if (from >= 0) { + T *b = ptr; + T *n = ptr + from + 1; + while (n != b) { + if (*--n == t) + return n - b; + } + } + return -1; +} + +template <class T, int Prealloc> +Q_INLINE_TEMPLATE bool QVarLengthArray<T, Prealloc>::contains(const T &t) const +{ + T *b = ptr; + T *i = ptr + s; + while (i != b) { + if (*--i == t) + return true; + } + return false; +} + +template <class T, int Prealloc> Q_OUTOFLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::append(const T *abuf, int increment) { Q_ASSERT(abuf); diff --git a/src/corelib/tools/qvarlengtharray.qdoc b/src/corelib/tools/qvarlengtharray.qdoc index db435739fc..05d9258c86 100644 --- a/src/corelib/tools/qvarlengtharray.qdoc +++ b/src/corelib/tools/qvarlengtharray.qdoc @@ -671,3 +671,42 @@ \sa append(), operator<<() */ +/*! \fn int QVarLengthArray::indexOf(const T &value, int from = 0) const + + \since 5.3 + Returns the index position of the first occurrence of \a value in + the array, searching forward from index position \a from. + Returns -1 if no item matched. + + This function requires the value type to have an implementation of + \c operator==(). + + \sa lastIndexOf(), contains() +*/ + +/*! \fn int QVarLengthArray::lastIndexOf(const T &value, int from = -1) const + + \since 5.3 + Returns the index position of the last occurrence of the value \a + value in the array, searching backward from index position \a + from. If \a from is -1 (the default), the search starts at the + last item. Returns -1 if no item matched. + + This function requires the value type to have an implementation of + \c operator==(). + + \sa indexOf(), contains() +*/ + +/*! \fn bool QVarLengthArray::contains(const T &value) const + + \since 5.3 + Returns \c true if the array contains an occurrence of \a value; + otherwise returns \c false. + + This function requires the value type to have an implementation of + \c operator==(). + + \sa indexOf(), lastIndexOf() +*/ + diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri index e4a7b02aee..ce3a6f9e8c 100644 --- a/src/corelib/tools/tools.pri +++ b/src/corelib/tools/tools.pri @@ -114,6 +114,9 @@ SOURCES += \ tools/qvector.cpp \ tools/qvsnprintf.cpp +NO_PCH_SOURCES = tools/qstring_compat.cpp +false: SOURCES += $$NO_PCH_SOURCES # Hack for QtCreator + !nacl:mac: { SOURCES += tools/qelapsedtimer_mac.cpp OBJECTIVE_SOURCES += tools/qlocale_mac.mm \ @@ -125,8 +128,11 @@ else:blackberry { HEADERS += tools/qlocale_blackberry.h } else:unix:SOURCES += tools/qelapsedtimer_unix.cpp tools/qlocale_unix.cpp tools/qtimezoneprivate_tz.cpp -else:win32:SOURCES += tools/qelapsedtimer_win.cpp tools/qlocale_win.cpp tools/qtimezoneprivate_win.cpp -else:integrity:SOURCES += tools/qelapsedtimer_unix.cpp tools/qlocale_unix.cpp +else:win32 { + SOURCES += tools/qelapsedtimer_win.cpp tools/qlocale_win.cpp + !winrt: SOURCES += tools/qtimezoneprivate_win.cpp + winphone: LIBS_PRIVATE += -lWindowsPhoneGlobalizationUtil +} else:integrity:SOURCES += tools/qelapsedtimer_unix.cpp tools/qlocale_unix.cpp else:SOURCES += tools/qelapsedtimer_generic.cpp contains(QT_CONFIG, zlib) { |