Add Mac type conversion functions to QtCore

New API:
    static QString QString::fromCFString(CFStringRef string);
    CFStringRef QString::toCFString() const;
    static QString QString::fromNSString(const NSString *string);
    NSString *QString::toNSString() const;

    static QUrl QUrl::fromCFURL(CFURLRef url);
    CFURLRef QUrl::toCFURL() const;
    static QUrl QUrl::fromNSURL(const NSURL *url);
    NSURL * QUrl::toNSURL() const;

Add Q_OS_MAC-protected function declarations to header
files, add implementation to _mm files.

CF and NS types are forward-declared in the header
files to avoid including the CoreFoundation and Foundation
headers. This prevents accidental use of native types
in application code. Add helper macros for forward-
declaration to qglobal.h

Add cf_returns_retained/ns_returns_autoreleased attributes
to toCFString() and toNSURL(). These attributes assists
the clang static analyzer. Add Q_DECL_ helper macros
to qcompilerdetection.h.

Add test functions (in _mac.mm files) to the QString
and QUrl tests. Split out the test class declarations
into a separate headers files.

Change-Id: I60fd5e93f042316196284c3db0595835fe8c4ad4
Reviewed-by: Gabriel de Dietrich <gabriel.dedietrich@digia.com>
This commit is contained in:
Morten Johan Sørvig 2013-09-02 10:12:07 +02:00 committed by The Qt Project
parent dd7bfffa77
commit 2b65bba77d
17 changed files with 458 additions and 2 deletions

View File

@ -620,6 +620,14 @@
# endif
#endif // Q_CC_CLANG
#if defined(Q_CC_CLANG) && defined(__APPLE__)
/* Apple/clang specific features */
# define Q_DECL_CF_RETURNS_RETAINED __attribute__((cf_returns_retained))
# ifdef __OBJC__
# define Q_DECL_NS_RETURNS_AUTORELEASED __attribute__((ns_returns_autoreleased))
# endif
#endif
#if defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && !defined(Q_CC_CLANG)
# if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 403
@ -849,6 +857,12 @@
# define Q_FUNC_INFO __FILE__ ":" QT_STRINGIFY(__LINE__)
# endif
#endif
#ifndef Q_DECL_CF_RETURNS_RETAINED
# define Q_DECL_CF_RETURNS_RETAINED
#endif
#ifndef Q_DECL_NS_RETURNS_AUTORELEASED
# define Q_DECL_NS_RETURNS_AUTORELEASED
#endif
/*
Workaround for static const members on MSVC++.

View File

@ -3361,4 +3361,36 @@ bool QInternal::activateCallbacks(Callback cb, void **parameters)
\sa Q_DECL_OVERRIDE
*/
/*!
\macro Q_FORWARD_DECLARE_OBJC_CLASS(classname)
\since 5.2
\relates <QtGlobal>
Forward-declares an Objective-C \a classname in a manner such that it can be
compiled as either Objective-C or C++.
This is primarily intended for use in header files that may be included by
both Objective-C and C++ source files.
*/
/*!
\macro Q_FORWARD_DECLARE_CF_TYPE(type)
\since 5.2
\relates <QtGlobal>
Forward-declares a Core Foundation \a type. This includes the actual
type and the ref type. For example, Q_FORWARD_DECLARE_CF_TYPE(CFString)
declares __CFString and CFStringRef.
*/
/*!
\macro Q_FORWARD_DECLARE_MUTABLE_CF_TYPE(type)
\since 5.2
\relates <QtGlobal>
Forward-declares a mutable Core Foundation \a type. This includes the actual
type and the ref type. For example, Q_FORWARD_DECLARE_CF_TYPE(CFString)
declares __CFMutableString and CFMutableStringRef.
*/
QT_END_NAMESPACE

View File

@ -993,6 +993,14 @@ template <bool B, typename T = void> struct QEnableIf;
template <typename T> struct QEnableIf<true, T> { typedef T Type; };
}
#ifdef __OBJC__
#define Q_FORWARD_DECLARE_OBJC_CLASS(classname) @class classname
#else
#define Q_FORWARD_DECLARE_OBJC_CLASS(classname) typedef struct objc_object classname
#endif
#define Q_FORWARD_DECLARE_CF_TYPE(type) typedef const struct __ ## type * type ## Ref
#define Q_FORWARD_DECLARE_MUTABLE_CF_TYPE(type) typedef struct __ ## type * type ## Ref
QT_END_NAMESPACE
// Q_GLOBAL_STATIC
#include <QtCore/qglobalstatic.h>

View File

@ -130,6 +130,7 @@ win32 {
!nacl:mac: {
SOURCES += io/qsettings_mac.cpp
OBJECTIVE_SOURCES += io/qurl_mac.mm
}
mac {
macx {

View File

@ -3319,6 +3319,33 @@ QByteArray QUrl::toPercentEncoding(const QString &input, const QByteArray &exclu
return input.toUtf8().toPercentEncoding(exclude, include);
}
/*! \fn QUrl QUrl::fromCFURL(CFURLRef url)
\since 5.2
Constructs a QUrl containing a copy of the CFURL \a url.
*/
/*! \fn CFURLRef QUrl::toCFURL() const
\since 5.2
Creates a CFURL from a QUrl. The caller owns the CFURL and is
responsible for releasing it.
*/
/*!
\fn QUrl QUrl::fromNSURL(const NSURL *url)
\since 5.2
Constructs a QUrl containing a copy of the NSURL \a url.
*/
/*!
\fn NSURL* QUrl::toNSURL() const
\since 5.2
Creates a NSURL from a QUrl. The NSURL is autoreleased.
*/
/*!
\internal
\since 5.0

View File

@ -50,6 +50,11 @@
#include <QtCore/qpair.h>
#include <QtCore/qglobal.h>
#ifdef Q_OS_MAC
Q_FORWARD_DECLARE_OBJC_CLASS(NSURL);
Q_FORWARD_DECLARE_CF_TYPE(CFURL);
#endif
QT_BEGIN_NAMESPACE
@ -257,6 +262,13 @@ public:
static QByteArray toPercentEncoding(const QString &,
const QByteArray &exclude = QByteArray(),
const QByteArray &include = QByteArray());
#if defined(Q_OS_MAC) || defined(Q_QDOC)
static QUrl fromCFURL(CFURLRef url);
CFURLRef toCFURL() const Q_DECL_CF_RETURNS_RETAINED;
static QUrl fromNSURL(const NSURL *url);
NSURL *toNSURL() const Q_DECL_NS_RETURNS_AUTORELEASED;
#endif
#if QT_DEPRECATED_SINCE(5,0)
QT_DEPRECATED static QString fromPunycode(const QByteArray &punycode)
{ return fromAce(punycode); }

View File

@ -0,0 +1,70 @@
/****************************************************************************
**
** 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 "qurl.h"
#ifdef Q_OS_MAC
#include <Foundation/Foundation.h>
#endif
QT_BEGIN_NAMESPACE
QUrl QUrl::fromCFURL(CFURLRef url)
{
return QUrl(QString::fromCFString(CFURLGetString(url)));
}
CFURLRef QUrl::toCFURL() const
{
return CFURLCreateWithString(0, toString(FullyEncoded).toCFString(), 0);
}
QUrl QUrl::fromNSURL(const NSURL *url)
{
return QUrl(QString::fromNSString([url absoluteString]));
}
NSURL *QUrl::toNSURL() const
{
return [NSURL URLWithString:toString(FullyEncoded).toNSString()];
}
QT_END_NAMESPACE

View File

@ -7367,6 +7367,31 @@ QString QString::multiArg(int numArgs, const QString **args) const
}
/*! \fn QString QString::fromCFString(CFStringRef string)
\since 5.2
Constructs a new QString containing a copy of the \a string CFString.
*/
/*! \fn CFStringRef QString::toCFString() const
\since 5.2
Creates a CFString from a QString. The caller owns the CFString and is
responsible for releasing it.
*/
/*! \fn QString QString::fromNSString(const NSString *string)
\since 5.2
Constructs a new QString containing a copy of the \a string NSString.
*/
/*! \fn NSString QString::toNSString() const
\since 5.2
Creates a NSString from a QString.g. The NSString is autoreleased.
*/
/*! \fn bool QString::isSimpleText() const
\internal

View File

@ -64,8 +64,12 @@ namespace std
#error qstring.h must be included before any header file that defines truncate
#endif
QT_BEGIN_NAMESPACE
#ifdef Q_OS_MAC
Q_FORWARD_DECLARE_OBJC_CLASS(NSString);
Q_FORWARD_DECLARE_CF_TYPE(CFString);
#endif
QT_BEGIN_NAMESPACE
class QCharRef;
class QRegExp;
@ -674,6 +678,12 @@ public:
static inline QString fromStdWString(const std::wstring &s);
inline std::wstring toStdWString() const;
#if defined(Q_OS_MAC) || defined(Q_QDOC)
static QString fromCFString(CFStringRef string);
CFStringRef toCFString() const Q_DECL_CF_RETURNS_RETAINED;
static QString fromNSString(const NSString *string);
NSString *toNSString() const Q_DECL_NS_RETURNS_AUTORELEASED;
#endif
// compatibility
struct Null { };
static const Null null;

View File

@ -0,0 +1,85 @@
/****************************************************************************
**
** 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 "qstring.h"
#import <Foundation/Foundation.h>
QT_BEGIN_NAMESPACE
QString QString::fromCFString(CFStringRef string)
{
if (!string)
return QString();
CFIndex length = CFStringGetLength(string);
// Fast path: CFStringGetCharactersPtr does not copy but may
// return null for any and no reason.
const UniChar *chars = CFStringGetCharactersPtr(string);
if (chars)
return QString(reinterpret_cast<const QChar *>(chars), length);
QString ret(length, Qt::Uninitialized);
CFStringGetCharacters(string, CFRangeMake(0, length), reinterpret_cast<UniChar *>(ret.data()));
return ret;
}
CFStringRef QString::toCFString() const
{
return CFStringCreateWithCharacters(0, reinterpret_cast<const UniChar *>(unicode()), length());
}
QString QString::fromNSString(const NSString *string)
{
if (!string)
return QString();
QString qstring;
qstring.resize([string length]);
[string getCharacters: reinterpret_cast<unichar*>(qstring.data()) range: NSMakeRange(0, [string length])];
return qstring;
}
NSString *QString::toNSString() const
{
return [NSString stringWithCharacters: reinterpret_cast<const UniChar*>(unicode()) length: length()];
}
QT_END_NAMESPACE

View File

@ -110,7 +110,8 @@ SOURCES += \
!nacl:mac: {
SOURCES += tools/qelapsedtimer_mac.cpp
OBJECTIVE_SOURCES += tools/qlocale_mac.mm
OBJECTIVE_SOURCES += tools/qlocale_mac.mm \
tools/qstring_mac.mm
}
else:blackberry {
SOURCES += tools/qelapsedtimer_unix.cpp tools/qlocale_blackberry.cpp

View File

@ -3,3 +3,5 @@ TARGET = tst_qurl
QT = core testlib concurrent
SOURCES = tst_qurl.cpp
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
mac: OBJECTIVE_SOURCES += tst_qurl_mac.mm

View File

@ -87,6 +87,7 @@ private slots:
void toLocalFile();
void fromLocalFile_data();
void fromLocalFile();
void macTypes();
void relative();
void compat_legacy();
void compat_constructor_01_data();
@ -1237,6 +1238,16 @@ void tst_QUrl::fromLocalFile()
QCOMPARE(url.path(), thePath);
}
void tst_QUrl::macTypes()
{
#ifndef Q_OS_MAC
QSKIP("This is a Mac-only test");
#else
extern void tst_QUrl_mactypes(); // in tst_qurl_mac.mm
void tst_QUrl_mactypes();
#endif
}
void tst_QUrl::compat_legacy()
{
{

View File

@ -0,0 +1,63 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtTest/QtTest>
#include <CoreFoundation/CoreFoundation.h>
#include <Foundation/Foundation.h>
void tst_QUrl_macTypes()
{
{
QUrl qtUrl("example.com");
const CFURLRef cfUrl = qtUrl.toCFURL();
QCOMPARE(QUrl::fromCFURL(cfUrl), qtUrl);
qtUrl.setUrl("www.example.com");
QVERIFY(QUrl::fromCFURL(cfUrl) != qtUrl);
}
{
QUrl qtUrl("example.com");
const NSURL *nsUrl = qtUrl.toNSURL();
QCOMPARE(QUrl::fromNSURL(nsUrl), qtUrl);
qtUrl.setUrl("www.example.com");
QVERIFY(QUrl::fromNSURL(nsUrl) != qtUrl);
}
}

View File

@ -5,3 +5,8 @@ SOURCES = tst_qstring.cpp
DEFINES += QT_NO_CAST_TO_ASCII
contains(QT_CONFIG,icu):DEFINES += QT_USE_ICU
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
mac {
OBJECTIVE_SOURCES += tst_qstring_mac.mm
LIBS += -framework Foundation
}

View File

@ -170,6 +170,7 @@ private slots:
void constructorQByteArray_data();
void constructorQByteArray();
void STL();
void macTypes();
void isEmpty();
void isNull();
void acc_01();
@ -939,6 +940,16 @@ void tst_QString::STL()
QCOMPARE(stlStr, s.toStdWString());
}
void tst_QString::macTypes()
{
#ifndef Q_OS_MAC
QSKIP("This is a Mac-only test");
#else
extern void tst_QString_macTypes(); // in qstring_mac.mm
tst_QString_macTypes();
#endif
}
void tst_QString::truncate()
{
QString e("String E");

View File

@ -0,0 +1,79 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the test suite 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 <QtCore/QString>
#include <QtTest/QtTest>
#include <CoreFoundation/CoreFoundation.h>
#include <Foundation/Foundation.h>
void tst_QString_macTypes()
{
// QString <-> CFString
{
QString qtString("test string");
const CFStringRef cfString = qtString.toCFString();
QCOMPARE(QString::fromCFString(cfString), qtString);
CFRelease(cfString);
}
{
QString qtString("test string");
const CFStringRef cfString = qtString.toCFString();
QString qtStringCopy(qtString);
qtString = qtString.toUpper(); // modify
QCOMPARE(QString::fromCFString(cfString), qtStringCopy);
}
// QString <-> NSString
{
QString qtString("test string");
const NSString *nsString = qtString.toNSString();
QCOMPARE(QString::fromNSString(nsString), qtString);
[nsString release];
}
{
QString qtString("test string");
const NSString *nsString = qtString.toNSString();
QString qtStringCopy(qtString);
qtString = qtString.toUpper(); // modify
QCOMPARE(QString::fromNSString(nsString), qtStringCopy);
[nsString release];
}
}