summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
authorNehme Bilal <nbilal@blackberry.com>2013-12-07 16:12:53 -0500
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-01-11 02:51:18 +0100
commit20a03d5612a5a7b763bfb0edbf9922ec4e50b25d (patch)
tree7bb2dd1a2391b69525c09affe7ef165ea80e3615 /src/corelib
parent151bea6aae9deec239ad7e56f060c108a08814ba (diff)
BlackBerry: Add a private PPS API
The PPS API is needed to implement other Qt APIs on BlackBerry. It is a private API that cannot be accessed from outside Qt (*_p). Change-Id: Id33d2f9a415f49d51812ae860a15e8cc5636676b Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@digia.com> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Fabian Bumberger <fbumberger@rim.com> Reviewed-by: Rafael Roquetto <rafael.roquetto@kdab.com>
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/kernel/kernel.pri10
-rw-r--r--src/corelib/kernel/qppsattribute.cpp308
-rw-r--r--src/corelib/kernel/qppsattribute_p.h139
-rw-r--r--src/corelib/kernel/qppsattributeprivate_p.h91
-rw-r--r--src/corelib/kernel/qppsobject.cpp964
-rw-r--r--src/corelib/kernel/qppsobject_p.h130
-rw-r--r--src/corelib/kernel/qppsobjectprivate_p.h128
7 files changed, 1768 insertions, 2 deletions
diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri
index 4c43f292fb..1fec528b31 100644
--- a/src/corelib/kernel/kernel.pri
+++ b/src/corelib/kernel/kernel.pri
@@ -164,9 +164,15 @@ vxworks {
blackberry {
SOURCES += \
- kernel/qeventdispatcher_blackberry.cpp
+ kernel/qeventdispatcher_blackberry.cpp \
+ kernel/qppsattribute.cpp \
+ kernel/qppsobject.cpp
HEADERS += \
- kernel/qeventdispatcher_blackberry_p.h
+ kernel/qeventdispatcher_blackberry_p.h \
+ kernel/qppsattribute_p.h \
+ kernel/qppsattributeprivate_p.h \
+ kernel/qppsobject_p.h \
+ kernel/qppsobjectprivate_p.h
}
android:!android-no-sdk {
diff --git a/src/corelib/kernel/qppsattribute.cpp b/src/corelib/kernel/qppsattribute.cpp
new file mode 100644
index 0000000000..f6745d2354
--- /dev/null
+++ b/src/corelib/kernel/qppsattribute.cpp
@@ -0,0 +1,308 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
+ ** 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 "qppsattribute_p.h"
+#include "qppsattributeprivate_p.h"
+
+#include <QDebug>
+#include <QVariant>
+
+///////////////////////////
+//
+// QPpsAttributePrivate
+//
+///////////////////////////
+
+QPpsAttributePrivate::QPpsAttributePrivate() : type(QPpsAttribute::None)
+{
+}
+
+QPpsAttribute QPpsAttributePrivate::createPpsAttribute(int value, QPpsAttribute::Flags flags)
+{
+ QPpsAttribute attribute;
+ attribute.d->type = QPpsAttribute::Number;
+ attribute.d->data = value;
+ attribute.d->flags = flags;
+ return attribute;
+}
+
+QPpsAttribute QPpsAttributePrivate::createPpsAttribute(long long value, QPpsAttribute::Flags flags)
+{
+ QPpsAttribute attribute;
+ attribute.d->type = QPpsAttribute::Number;
+ attribute.d->data = value;
+ attribute.d->flags = flags;
+ return attribute;
+}
+
+QPpsAttribute QPpsAttributePrivate::createPpsAttribute(double value, QPpsAttribute::Flags flags)
+{
+ QPpsAttribute attribute;
+ attribute.d->type = QPpsAttribute::Number;
+ attribute.d->data = value;
+ attribute.d->flags = flags;
+ return attribute;
+}
+
+QPpsAttribute QPpsAttributePrivate::createPpsAttribute(bool value, QPpsAttribute::Flags flags)
+{
+ QPpsAttribute attribute;
+ attribute.d->type = QPpsAttribute::Bool;
+ attribute.d->data = value;
+ attribute.d->flags = flags;
+ return attribute;
+}
+
+QPpsAttribute QPpsAttributePrivate::createPpsAttribute(const QString &value,
+ QPpsAttribute::Flags flags)
+{
+ QPpsAttribute attribute;
+ attribute.d->type = QPpsAttribute::String;
+ attribute.d->data = value;
+ attribute.d->flags = flags;
+ return attribute;
+}
+
+QPpsAttribute QPpsAttributePrivate::createPpsAttribute(const QPpsAttributeList &value,
+ QPpsAttribute::Flags flags)
+{
+ QPpsAttribute attribute;
+ attribute.d->type = QPpsAttribute::Array;
+ attribute.d->data = QVariant::fromValue(value);
+ attribute.d->flags = flags;
+ return attribute;
+}
+
+QPpsAttribute QPpsAttributePrivate::createPpsAttribute(const QPpsAttributeMap &value,
+ QPpsAttribute::Flags flags)
+{
+ QPpsAttribute attribute;
+ attribute.d->type = QPpsAttribute::Object;
+ attribute.d->data = QVariant::fromValue(value);
+ attribute.d->flags = flags;
+ return attribute;
+}
+
+///////////////////////////
+//
+// QPpsAttribute
+//
+///////////////////////////
+
+QPpsAttribute::QPpsAttribute():
+ d(new QPpsAttributePrivate())
+{
+}
+
+QPpsAttribute::~QPpsAttribute()
+{
+}
+
+QPpsAttribute::QPpsAttribute(const QPpsAttribute &other): d(other.d)
+{
+}
+
+QPpsAttribute &QPpsAttribute::operator=(const QPpsAttribute &other)
+{
+ d = other.d;
+ return *this;
+}
+
+#ifdef Q_COMPILER_RVALUE_REFS
+QPpsAttribute::QPpsAttribute(QPpsAttribute &&other): d(other.d)
+{
+ other.d->type = QPpsAttribute::None;
+}
+
+QPpsAttribute &QPpsAttribute::operator=(QPpsAttribute &&other)
+{
+ qSwap(d, other.d);
+ return *this;
+}
+#endif
+
+bool QPpsAttribute::operator==(const QPpsAttribute &other) const
+{
+ if (type() != other.type())
+ return false;
+ if (flags() != other.flags())
+ return false;
+
+ switch (type()) {
+ case QPpsAttribute::Number:
+ case QPpsAttribute::Bool:
+ case QPpsAttribute::String:
+ // QVariant can compare double, int, longlong, bool, and QString for us.
+ return d->data == other.d->data;
+ case QPpsAttribute::Array:
+ // QVariant can't compare custom types (like QPpsAttributeList), always returning false.
+ // So we pull the lists out manually and compare them.
+ return toList() == other.toList();
+ case QPpsAttribute::Object:
+ // QVariant can't compare custom types (like QPpsAttributeMap), always returning false.
+ // So we pull the maps out manually and compare them.
+ return toMap() == other.toMap();
+ case QPpsAttribute::None:
+ // Both are "None" type, so the actual content doesn't matter.
+ return true;
+ }
+ return d->data == other.d->data;
+}
+
+bool QPpsAttribute::isValid() const
+{
+ return d->type != QPpsAttribute::None;
+}
+
+QPpsAttribute::Type QPpsAttribute::type() const
+{
+ return d->type;
+}
+
+bool QPpsAttribute::isNumber() const
+{
+ return type() == QPpsAttribute::Number;
+}
+
+bool QPpsAttribute::isBool() const
+{
+ return type() == QPpsAttribute::Bool;
+}
+
+bool QPpsAttribute::isString() const
+{
+ return type() == QPpsAttribute::String;
+}
+
+bool QPpsAttribute::isArray() const
+{
+ return type() == QPpsAttribute::Array;
+}
+
+bool QPpsAttribute::isObject() const
+{
+ return type() == QPpsAttribute::Object;
+}
+
+double QPpsAttribute::toDouble() const
+{
+ return d->data.toDouble();
+}
+
+qlonglong QPpsAttribute::toLongLong() const
+{
+ return d->data.toLongLong();
+}
+
+int QPpsAttribute::toInt() const
+{
+ return d->data.toInt();
+}
+
+bool QPpsAttribute::toBool() const
+{
+ return d->data.toBool();
+}
+
+QString QPpsAttribute::toString() const
+{
+ return d->data.toString();
+}
+
+QPpsAttributeList QPpsAttribute::toList() const
+{
+ return d->data.value< QPpsAttributeList >();
+}
+
+QPpsAttributeMap QPpsAttribute::toMap() const
+{
+ return d->data.value< QPpsAttributeMap >();
+}
+
+QPpsAttribute::Flags QPpsAttribute::flags() const
+{
+ return d->flags;
+}
+
+QVariant QPpsAttribute::toVariant() const
+{
+ return d->data;
+}
+
+QDebug operator<<(QDebug dbg, const QPpsAttribute &attribute)
+{
+ dbg << "QPpsAttribute(";
+
+ switch (attribute.type()) {
+ case QPpsAttribute::Number:
+ switch (attribute.toVariant().type()) {
+ case QVariant::Int:
+ dbg << "Number, " << attribute.flags() << ", " << attribute.toInt();
+ break;
+ case QVariant::LongLong:
+ dbg << "Number, " << attribute.flags() << ", " << attribute.toLongLong();
+ break;
+ default:
+ dbg << "Number, " << attribute.flags() << ", " << attribute.toDouble();
+ break;
+ }
+ break;
+ case QPpsAttribute::Bool:
+ dbg << "Bool, " << attribute.flags() << ", " << attribute.toBool();
+ break;
+ case QPpsAttribute::String:
+ dbg << "String, " << attribute.flags() << ", " << attribute.toString();
+ break;
+ case QPpsAttribute::Array:
+ dbg << "Array, " << attribute.flags() << ", " << attribute.toList();
+ break;
+ case QPpsAttribute::Object:
+ dbg << "Object, " << attribute.flags() << ", " << attribute.toMap();
+ break;
+ case QPpsAttribute::None:
+ dbg << "None";
+ break;
+ }
+
+ dbg << ')';
+
+ return dbg;
+}
diff --git a/src/corelib/kernel/qppsattribute_p.h b/src/corelib/kernel/qppsattribute_p.h
new file mode 100644
index 0000000000..03a0f98a17
--- /dev/null
+++ b/src/corelib/kernel/qppsattribute_p.h
@@ -0,0 +1,139 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
+ ** 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 QPPSATTRIBUTE_P_H
+#define QPPSATTRIBUTE_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 <QList>
+#include <QMap>
+#include <QSharedDataPointer>
+#include <QVariant>
+
+QT_BEGIN_NAMESPACE
+
+class QPpsAttributePrivate;
+class QPpsAttribute;
+
+typedef QList<QPpsAttribute> QPpsAttributeList;
+typedef QMap<QString, QPpsAttribute> QPpsAttributeMap;
+Q_DECLARE_METATYPE(QPpsAttributeList)
+Q_DECLARE_METATYPE(QPpsAttributeMap)
+
+class Q_CORE_EXPORT QPpsAttribute
+{
+public:
+
+ enum Type {
+ None = 0,
+ Number = 1,
+ Bool = 2,
+ String = 3,
+ Array = 4,
+ Object = 5
+ };
+
+ enum Flag {
+ Incomplete = 0x01,
+ Deleted = 0x02,
+ Created = 0x04,
+ Truncated = 0x08,
+ Purged = 0x10
+ };
+ Q_DECLARE_FLAGS(Flags, Flag)
+
+ QPpsAttribute();
+ QPpsAttribute(const QPpsAttribute &other);
+ ~QPpsAttribute();
+
+ QPpsAttribute &operator=(const QPpsAttribute &other);
+ bool operator==(const QPpsAttribute &other) const;
+ bool operator!=(const QPpsAttribute &other) const;
+
+#ifdef Q_COMPILER_RVALUE_REFS
+ QPpsAttribute(QPpsAttribute &&other);
+ QPpsAttribute &operator=(QPpsAttribute &&other);
+#endif
+
+ bool isValid() const;
+ Type type() const;
+ QPpsAttribute::Flags flags() const;
+
+ bool isNumber() const;
+ bool isBool() const;
+ bool isString() const;
+ bool isArray() const;
+ bool isObject() const;
+
+ double toDouble() const;
+ qlonglong toLongLong() const;
+ int toInt() const;
+ bool toBool() const;
+ QString toString() const;
+ QPpsAttributeList toList() const;
+ QPpsAttributeMap toMap() const;
+ QVariant toVariant() const;
+
+private:
+ QSharedDataPointer<QPpsAttributePrivate> d;
+ friend class QPpsAttributePrivate;
+};
+
+inline bool QPpsAttribute::operator!=(const QPpsAttribute &other) const
+{
+ return !(*this == other);
+}
+
+Q_CORE_EXPORT QDebug operator<<(QDebug dbg, const QPpsAttribute &attribute);
+
+QT_END_NAMESPACE
+
+#endif // QPPSATTRIBUTE_P_H
diff --git a/src/corelib/kernel/qppsattributeprivate_p.h b/src/corelib/kernel/qppsattributeprivate_p.h
new file mode 100644
index 0000000000..0aa29d0895
--- /dev/null
+++ b/src/corelib/kernel/qppsattributeprivate_p.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
+ ** 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 QPPSATTRIBUTEPRIVATE_P_H
+#define QPPSATTRIBUTEPRIVATE_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 "qppsattribute_p.h"
+
+#include <QList>
+#include <QMap>
+#include <QSharedData>
+#include <QString>
+#include <QVariant>
+
+QT_BEGIN_NAMESPACE
+
+class QPpsAttributePrivate : public QSharedData
+{
+public:
+ QPpsAttributePrivate();
+
+ static QPpsAttribute createPpsAttribute(double value, QPpsAttribute::Flags flags);
+ static QPpsAttribute createPpsAttribute(long long value, QPpsAttribute::Flags flags);
+ static QPpsAttribute createPpsAttribute(int value, QPpsAttribute::Flags flags);
+ static QPpsAttribute createPpsAttribute(bool value, QPpsAttribute::Flags flags);
+ static QPpsAttribute createPpsAttribute(const QString &value, QPpsAttribute::Flags flags);
+ static QPpsAttribute createPpsAttribute(const QPpsAttributeList &value,
+ QPpsAttribute::Flags flags);
+ static QPpsAttribute createPpsAttribute(const QPpsAttributeMap &value,
+ QPpsAttribute::Flags flags);
+
+private:
+ friend class QPpsAttribute;
+
+ QVariant data;
+ QPpsAttribute::Type type;
+ QPpsAttribute::Flags flags;
+};
+
+QT_END_NAMESPACE
+
+#endif // QPPSATTRIBUTEPRIVATE_P_H
diff --git a/src/corelib/kernel/qppsobject.cpp b/src/corelib/kernel/qppsobject.cpp
new file mode 100644
index 0000000000..eb8e69baff
--- /dev/null
+++ b/src/corelib/kernel/qppsobject.cpp
@@ -0,0 +1,964 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
+ ** 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 "qppsobject_p.h"
+
+#include "qppsobjectprivate_p.h"
+#include "qppsattribute_p.h"
+#include "qppsattributeprivate_p.h"
+#include "qcore_unix_p.h"
+
+#include <QObject>
+#include <QSocketNotifier>
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <confname.h>
+
+#include <sys/pps.h>
+
+///////////////////////////////////////////////////////////////////////////////
+static inline void safeAssign(bool *pointer, bool value)
+{
+ if (pointer)
+ *pointer = value;
+}
+
+class QPpsMaxSize
+{
+public:
+ QPpsMaxSize()
+ {
+ int fd = qt_safe_open("/pps/.all", O_RDONLY);
+ if (fd == -1) {
+ qWarning() << "qppsobject.cpp: qt_safe_open failed";
+ value = -1;
+ }
+
+ // This tells us the maximum transfer size across PPS
+ value = ::fpathconf(fd, _PC_REC_MAX_XFER_SIZE);
+
+ qt_safe_close(fd);
+ }
+
+ int value;
+};
+
+Q_GLOBAL_STATIC(QPpsMaxSize, ppsMaxSize)
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// QPpsObjectPrivate
+//
+///////////////////////////////////////////////////////////////////////////////
+
+QPpsObjectPrivate::QPpsObjectPrivate(const QString &path) :
+ notifier(0),
+ path(path),
+ error(EOK),
+ fd(-1),
+ readyReadEnabled(true)
+{
+}
+
+QPpsAttributeMap QPpsObjectPrivate::decode(const QByteArray &rawData, bool *ok)
+{
+ QPpsAttributeMap attributeMap;
+ pps_decoder_t decoder;
+
+ QByteArray mutableData(rawData);
+ pps_decoder_error_t error = pps_decoder_initialize(&decoder, mutableData.data());
+ if (error == PPS_DECODER_OK) {
+ // no need to check ok in this case
+ attributeMap = decodeObject(&decoder, ok);
+ } else {
+ qWarning() << "QPpsObjectPrivate::decode: pps_decoder_initialize failed";
+ *ok = false;
+ }
+
+ pps_decoder_cleanup(&decoder);
+ return attributeMap;
+}
+
+QVariantMap QPpsObjectPrivate::variantMapFromPpsAttributeMap(const QPpsAttributeMap &data)
+{
+ QVariantMap variantMap;
+
+ for (QPpsAttributeMap::const_iterator it = data.constBegin(); it != data.constEnd(); ++it) {
+ QVariant variant = variantFromPpsAttribute(it.value());
+ if (!variant.isValid())
+ return QVariantMap();
+ variantMap[it.key()] = variant;
+ }
+
+ return variantMap;
+}
+
+QPpsAttribute::Flags QPpsObjectPrivate::readFlags(pps_decoder_t *decoder)
+{
+ int rawFlags = pps_decoder_flags(decoder, 0);
+
+ QPpsAttribute::Flags attributeFlags;
+
+ if (rawFlags & PPS_INCOMPLETE)
+ attributeFlags |= QPpsAttribute::Incomplete;
+ if (rawFlags & PPS_DELETED)
+ attributeFlags |= QPpsAttribute::Deleted;
+ if (rawFlags & PPS_CREATED)
+ attributeFlags |= QPpsAttribute::Created;
+ if (rawFlags & PPS_TRUNCATED)
+ attributeFlags |= QPpsAttribute::Truncated;
+ if (rawFlags & PPS_PURGED)
+ attributeFlags |= QPpsAttribute::Purged;
+
+ return attributeFlags;
+}
+
+QPpsAttribute QPpsObjectPrivate::decodeString(pps_decoder_t *decoder)
+{
+ const char *value = 0;
+ pps_decoder_error_t error = pps_decoder_get_string(decoder, 0, &value);
+
+ if (error != PPS_DECODER_OK) {
+ qWarning() << "QPpsObjectPrivate::decodeString: PPS_DECODER_GET_STRING failed";
+ return QPpsAttribute();
+ }
+
+ QPpsAttribute::Flags flags = readFlags(decoder);
+ return QPpsAttributePrivate::createPpsAttribute(QString::fromUtf8(value), flags);
+}
+
+QPpsAttribute QPpsObjectPrivate::decodeNumber(pps_decoder_t *decoder)
+{
+ // In order to support more number types, we have to do something stupid because the PPS
+ // library won't let us work any other way. Basically, we have to probe the encoded type in
+ // order to try to get exactly what we want.
+ long long llValue;
+ double dValue;
+ int iValue;
+ QPpsAttribute::Flags flags;
+
+ if (pps_decoder_is_integer(decoder, 0)) {
+ pps_decoder_error_t error = pps_decoder_get_int(decoder, 0, &iValue);
+ switch (error) {
+ case PPS_DECODER_OK:
+ flags = readFlags(decoder);
+ return QPpsAttributePrivate::createPpsAttribute(iValue, flags);
+ case PPS_DECODER_CONVERSION_FAILED:
+ error = pps_decoder_get_int64(decoder, 0, &llValue);
+ if (error != PPS_DECODER_OK) {
+ qWarning() << "QPpsObjectPrivate::decodeNumber: failed to decode integer";
+ return QPpsAttribute();
+ }
+ flags = readFlags(decoder);
+ return QPpsAttributePrivate::createPpsAttribute(llValue, flags);
+ default:
+ qWarning() << "QPpsObjectPrivate::decodeNumber: pps_decoder_get_int failed";
+ return QPpsAttribute();
+ }
+ } else {
+ pps_decoder_error_t error = pps_decoder_get_double(decoder, 0, &dValue);
+ if (error != PPS_DECODER_OK) {
+ qWarning() << "QPpsObjectPrivate::decodeNumber: pps_decoder_get_double failed";
+ return QPpsAttribute();
+ }
+ flags = readFlags(decoder);
+ return QPpsAttributePrivate::createPpsAttribute(dValue, flags);
+ }
+}
+
+QPpsAttribute QPpsObjectPrivate::decodeBool(pps_decoder_t *decoder)
+{
+ bool value;
+ pps_decoder_error_t error = pps_decoder_get_bool(decoder, 0, &value);
+
+ if (error != PPS_DECODER_OK) {
+ qWarning() << "QPpsObjectPrivate::decodeBool: pps_decoder_get_bool failed";
+ return QPpsAttribute();
+ }
+
+ QPpsAttribute::Flags flags = readFlags(decoder);
+ return QPpsAttributePrivate::createPpsAttribute(value, flags);
+}
+
+template<typename T>
+QPpsAttribute QPpsObjectPrivate::decodeNestedData(T (*decodeFunction)(pps_decoder_t *, bool *),
+ pps_decoder_t *decoder)
+{
+ // We must read the flags before we push into the object,
+ // otherwise we'll get the flags for the first element in the object.
+ QPpsAttribute::Flags flags = readFlags(decoder);
+
+ if (!decoderPush(decoder))
+ return QPpsAttribute();
+
+ bool ok = false;
+
+ T attributeContainer = decodeFunction(decoder, &ok);
+
+ if (!ok)
+ return QPpsAttribute();
+
+ QPpsAttribute returnVal = QPpsAttributePrivate::createPpsAttribute(attributeContainer, flags);
+
+ if (!decoderPop(decoder))
+ return QPpsAttribute();
+
+ return returnVal;
+}
+
+QPpsAttribute QPpsObjectPrivate::decodeData(pps_decoder_t *decoder)
+{
+ pps_node_type_t nodeType = pps_decoder_type(decoder, 0);
+ switch (nodeType) {
+ case PPS_TYPE_BOOL:
+ return decodeBool(decoder);
+ case PPS_TYPE_NUMBER:
+ return decodeNumber(decoder);
+ case PPS_TYPE_STRING:
+ return decodeString(decoder);
+ case PPS_TYPE_ARRAY:
+ return decodeNestedData(&QPpsObjectPrivate::decodeArray, decoder);
+ case PPS_TYPE_OBJECT:
+ return decodeNestedData(&QPpsObjectPrivate::decodeObject, decoder);
+ case PPS_TYPE_DELETED: {
+ // This should create an attribute with the flags set to PpsAttribute::Deleted.
+ // However, we need to create a valid QPpsAttribute while doing so. To do this,
+ // I'll create an empty map as a sentinel. Note that the readFlags() call with produce
+ // the correct set of flags. While I suspect that there will never be any other flags
+ // set in conjunction with this one, I'd rather not be surprised later.
+ QPpsAttributeMap emptyMap;
+ QPpsAttribute::Flags flags = readFlags(decoder);
+ QPpsAttribute returnVal = QPpsAttributePrivate::createPpsAttribute(emptyMap, flags);
+ return returnVal;
+ }
+ case PPS_TYPE_NULL:
+ case PPS_TYPE_NONE:
+ case PPS_TYPE_UNKNOWN:
+ default:
+ qWarning() << "QPpsObjectPrivate::decodeData: invalid pps_node_type";
+ return QPpsAttribute();
+ }
+}
+
+QPpsAttributeList QPpsObjectPrivate::decodeArray(pps_decoder_t *decoder, bool *ok)
+{
+ QPpsAttributeList list;
+
+ int length = pps_decoder_length(decoder);
+ for (int i = 0; i < length; ++i) {
+ // Force movement to a specific index.
+ pps_decoder_error_t error = pps_decoder_goto_index(decoder, i);
+ if (error != PPS_DECODER_OK) {
+ qWarning() << "QPpsObjectPrivate::decodeArray: pps_decoder_goto_index failed";
+ *ok = false;
+ return QPpsAttributeList();
+ }
+
+ QPpsAttribute ppsAttribute = decodeData(decoder);
+ if (!ppsAttribute.isValid()) {
+ *ok = false;
+ return QPpsAttributeList();
+ }
+
+ list << ppsAttribute;
+ }
+
+ *ok = true;
+ return list;
+}
+
+QPpsAttributeMap QPpsObjectPrivate::decodeObject(pps_decoder_t *decoder, bool *ok)
+{
+ QPpsAttributeMap map;
+
+ int length = pps_decoder_length(decoder);
+ for (int i = 0; i < length; ++i) {
+ // Force movement to a specific index.
+ pps_decoder_error_t error = pps_decoder_goto_index(decoder, i);
+ if (error != PPS_DECODER_OK) {
+ qWarning() << "QPpsObjectPrivate::decodeObject: pps_decoder_goto_index failed";
+ *ok = false;
+ return QPpsAttributeMap();
+ }
+ QString name = QString::fromUtf8(pps_decoder_name(decoder));
+ QPpsAttribute ppsAttribute = decodeData(decoder);
+ if (!ppsAttribute.isValid()) {
+ *ok = false;
+ return QPpsAttributeMap();
+ }
+ map[name] = ppsAttribute;
+ }
+
+ *ok = true;
+ return map;
+}
+
+QVariant QPpsObjectPrivate::variantFromPpsAttribute(const QPpsAttribute &attribute)
+{
+ switch (attribute.type()) {
+ case QPpsAttribute::Number:
+ switch (attribute.toVariant().type()) {
+ case QVariant::Int:
+ return attribute.toInt();
+ case QVariant::LongLong:
+ return attribute.toLongLong();
+ default:
+ return attribute.toDouble();
+ }
+ break;
+ case QPpsAttribute::Bool:
+ return attribute.toBool();
+ case QPpsAttribute::String:
+ return attribute.toString();
+ case QPpsAttribute::Array: {
+ QVariantList variantList;
+ Q_FOREACH (const QPpsAttribute &attr, attribute.toList()) {
+ QVariant variant = variantFromPpsAttribute(attr);
+ if (!variant.isValid())
+ return QVariantList();
+ variantList << variant;
+ }
+ return variantList;
+ }
+ case QPpsAttribute::Object:
+ return variantMapFromPpsAttributeMap(attribute.toMap());
+ case QPpsAttribute::None:
+ default:
+ qWarning() << "QPpsObjectPrivate::variantFromPpsAttribute: invalid attribute parameter";
+ return QVariant();
+ }
+}
+
+QByteArray QPpsObjectPrivate::encode(const QVariantMap &ppsData, bool *ok)
+{
+ pps_encoder_t encoder;
+ pps_encoder_initialize(&encoder, false);
+
+ encodeObject(&encoder, ppsData, ok);
+ const char *rawData = 0;
+ if (*ok) {
+ // rawData points to a memory owned by encoder.
+ // The memory will be freed when pps_encoder_cleanup is called.
+ rawData = pps_encoder_buffer(&encoder);
+ if (!rawData) {
+ qWarning() << "QPpsObjectPrivate::encode: pps_encoder_buffer failed";
+ *ok = false;
+ }
+ }
+
+ pps_encoder_cleanup(&encoder);
+ return QByteArray(rawData);
+}
+
+void QPpsObjectPrivate::encodeData(pps_encoder_t *encoder, const char *name, const QVariant &data,
+ bool *ok)
+{
+ QString errorFunction;
+ pps_encoder_error_t error = PPS_ENCODER_OK;
+ switch (data.type()) {
+ case QVariant::Bool:
+ error = pps_encoder_add_bool(encoder, name, data.toBool());
+ errorFunction = QStringLiteral("pps_encoder_add_bool");
+ break;
+ // We want to support encoding uint even though libpps doesn't support it directly.
+ // We can't encode uint as an int since that will lose precision (e.g. 2^31+1 can't be
+ // encoded that way). However, we can convert uint to double without losing precision.
+ // QVariant.toDouble() conveniently takes care of the conversion for us.
+ case QVariant::UInt:
+ case QVariant::Double:
+ error = pps_encoder_add_double(encoder, name, data.toDouble());
+ errorFunction = QStringLiteral("pps_encoder_add_double");
+ break;
+ case QVariant::Int:
+ error = pps_encoder_add_int(encoder, name, data.toInt());
+ errorFunction = QStringLiteral("pps_encoder_add_int");
+ break;
+ case QVariant::LongLong:
+ error = pps_encoder_add_int64(encoder, name, data.toLongLong());
+ errorFunction = QStringLiteral("pps_encoder_add_int64");
+ break;
+ case QVariant::String:
+ error = pps_encoder_add_string(encoder, name, data.toString().toUtf8().constData());
+ errorFunction = QStringLiteral("pps_encoder_add_string");
+ break;
+ case QVariant::List:
+ error = pps_encoder_start_array(encoder, name);
+ errorFunction = QStringLiteral("pps_encoder_start_array");
+ if (error == PPS_ENCODER_OK) {
+ encodeArray(encoder, data.toList(), ok);
+ error = pps_encoder_end_array(encoder);
+ errorFunction = QStringLiteral("pps_encoder_end_array");
+ }
+ break;
+ case QVariant::Map:
+ error = pps_encoder_start_object(encoder, name);
+ errorFunction = QStringLiteral("pps_encoder_start_object");
+ if (error == PPS_ENCODER_OK) {
+ encodeObject(encoder, data.toMap(), ok);
+ error = pps_encoder_end_object(encoder);
+ errorFunction = QStringLiteral("pps_encoder_end_object");
+ }
+ break;
+ case QVariant::Invalid:
+ error = pps_encoder_add_null(encoder, name);
+ errorFunction = QStringLiteral("pps_encoder_add_null");
+ break;
+ default:
+ qWarning() << "QPpsObjectPrivate::encodeData: the type of the parameter data is invalid";
+ *ok = false;
+ return;
+ }
+
+ if (error != PPS_ENCODER_OK) {
+ qWarning() << "QPpsObjectPrivate::encodeData: " << errorFunction << " failed";
+ *ok = false;
+ } else {
+ *ok = true;
+ }
+}
+
+void QPpsObjectPrivate::encodeArray(pps_encoder_t *encoder, const QVariantList &data, bool *ok)
+{
+ for (QVariantList::const_iterator it = data.constBegin(); it != data.constEnd(); ++it) {
+ encodeData(encoder, 0, *it, ok);
+ if (!(*ok))
+ return;
+ }
+ // if the passed data is empty, nothing went wrong and ok is set to true
+ *ok = true;
+}
+
+void QPpsObjectPrivate::encodeObject(pps_encoder_t *encoder, const QVariantMap &data, bool *ok)
+{
+ for (QVariantMap::const_iterator it = data.constBegin(); it != data.constEnd(); ++it) {
+ encodeData(encoder, it.key().toUtf8().constData(), it.value(), ok);
+ if (!(*ok))
+ return;
+ }
+ // if the passed data is empty, nothing went wrong and ok is set to true
+ *ok = true;
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// QPpsObjectPrivate
+//
+///////////////////////////////////////////////////////////////////////////////
+
+QPpsObject::QPpsObject(const QString &path, QObject *parent) :
+ QObject(parent),
+ d_ptr(new QPpsObjectPrivate(path))
+{
+}
+
+QPpsObject::~QPpsObject()
+{
+ // RAII - ensure file gets closed
+ if (isOpen())
+ close();
+}
+
+int QPpsObject::error() const
+{
+ Q_D(const QPpsObject);
+ return d->error;
+}
+
+QString QPpsObject::errorString() const
+{
+ Q_D(const QPpsObject);
+ return qt_error_string(d->error);
+}
+
+bool QPpsObject::isReadyReadEnabled() const
+{
+ Q_D(const QPpsObject);
+
+ // query state of read ready signal
+ return d->readyReadEnabled;
+}
+
+void QPpsObject::setReadyReadEnabled(bool enable)
+{
+ Q_D(QPpsObject);
+
+ // toggle whether socket notifier will emit a signal on read ready
+ d->readyReadEnabled = enable;
+ if (isOpen())
+ d->notifier->setEnabled(enable);
+}
+
+bool QPpsObject::isBlocking() const
+{
+ Q_D(const QPpsObject);
+
+ // reset last error
+ d->error = EOK;
+
+ // abort if file not open
+ if (!isOpen()) {
+ d->error = EBADF;
+ return false;
+ }
+
+ // query file status flags
+ int flags = fcntl(d->fd, F_GETFL);
+ if (flags == -1) {
+ d->error = errno;
+ return false;
+ }
+ // check if non-blocking flag is unset
+ return ((flags & O_NONBLOCK) != O_NONBLOCK);
+}
+
+bool QPpsObject::setBlocking(bool enable)
+{
+ Q_D(QPpsObject);
+
+ // reset last error
+ d->error = EOK;
+
+ // abort if file not open
+ if (!isOpen()) {
+ d->error = EBADF;
+ return false;
+ }
+
+ // query file status flags
+ int flags = fcntl(d->fd, F_GETFL);
+ if (flags == -1) {
+ d->error = errno;
+ return false;
+ }
+
+ // configure non-blocking flag
+ if (enable)
+ flags &= ~O_NONBLOCK;
+ else
+ flags |= O_NONBLOCK;
+
+ // update file status flags
+ flags = fcntl(d->fd, F_SETFL, flags);
+ if (flags == -1) {
+ d->error = errno;
+ return false;
+ }
+
+ return true;
+}
+
+bool QPpsObject::isOpen() const
+{
+ Q_D(const QPpsObject);
+ return (d->fd != -1);
+}
+
+bool QPpsObject::open(QPpsObject::OpenModes mode)
+{
+ Q_D(QPpsObject);
+
+ // reset last error
+ d->error = EOK;
+
+ // abort if file already open
+ if (isOpen()) {
+ d->error = EBUSY;
+ return false;
+ }
+
+ // convert pps flags to open flags
+ int oflags = 0;
+ if ((mode & QPpsObject::Publish) && (mode & QPpsObject::Subscribe))
+ oflags |= O_RDWR;
+ else if (mode & QPpsObject::Publish)
+ oflags |= O_WRONLY;
+ else if (mode & QPpsObject::Subscribe)
+ oflags |= O_RDONLY;
+
+ if (mode & QPpsObject::Create)
+ oflags |= O_CREAT | O_EXCL;
+
+ if (mode & QPpsObject::DeleteContents)
+ oflags |= O_TRUNC;
+
+ // open pps file
+ d->fd = qt_safe_open(d->path.toUtf8().data(), oflags, 0666);
+ if (d->fd == -1) {
+ d->error = errno;
+ return false;
+ }
+ // wire up socket notifier to know when reads are ready
+ d->notifier = new QSocketNotifier(d->fd, QSocketNotifier::Read, this);
+ d->notifier->setEnabled(d->readyReadEnabled);
+ QObject::connect(d->notifier, &QSocketNotifier::activated, this, &QPpsObject::readyRead);
+ return true;
+}
+
+bool QPpsObject::close()
+{
+ Q_D(QPpsObject);
+
+ // reset last error
+ d->error = EOK;
+
+ // abort if file not open
+ if (!isOpen()) {
+ d->error = EBADF;
+ return false;
+ }
+
+ // shutdown socket notifier
+ delete d->notifier;
+ d->notifier = 0;
+
+ // close pps file
+ const int result = qt_safe_close(d->fd);
+ d->fd = -1;
+
+ // check success of operation
+ if (result != 0) {
+ d->error = errno;
+ return false;
+ }
+ return true;
+}
+
+QByteArray QPpsObject::read(bool *ok)
+{
+ Q_D(QPpsObject);
+
+ // reset last error
+ d->error = EOK;
+
+ // abort if file not open
+ if (!isOpen()) {
+ d->error = EBADF;
+ safeAssign(ok, false);
+ return QByteArray();
+ }
+
+ const int maxSize = ppsMaxSize->value;
+ if (maxSize == -1) {
+ qWarning() << "QPpsObject::read: maxSize is equal to -1";
+ safeAssign(ok, false);
+ return QByteArray();
+ }
+
+ QByteArray byteArray;
+ byteArray.resize(maxSize); // resize doesn't initialize the data
+ const int result = qt_safe_read(d->fd, byteArray.data(), byteArray.size());
+
+ if (result == -1) {
+ d->error = errno;
+ qWarning() << "QPpsObject::read failed to read pps data, error " << errorString();
+ safeAssign(ok, false);
+ return QByteArray(); // Specifically return a default-constructed QByteArray.
+ }
+ if (result == 0) {
+ // normalize the behavior of read() when no data is ready so a pps object
+ // put in non-blocking mode via opening w/o wait (read returns 0) looks
+ // the same as a pps object put in non-blocking mode by setting O_NONBLOCK
+ // (read returns EAGAIN)
+ d->error = EAGAIN;
+ safeAssign(ok, false);
+ return QByteArray(); // Specifically return a default-constructed QByteArray.
+ }
+ // resize byte array to amount actually read
+ byteArray.resize(result);
+ safeAssign(ok, true);
+ return byteArray;
+}
+
+bool QPpsObject::write(const QByteArray &byteArray)
+{
+ Q_D(QPpsObject);
+
+ // reset last error
+ d->error = EOK;
+
+ // abort if file not open
+ if (!isOpen()) {
+ d->error = EBADF;
+ return false;
+ }
+
+ // write entire byte array to pps file
+ const int result = qt_safe_write(d->fd, byteArray.data(), byteArray.size());
+ if (result == -1)
+ d->error = errno;
+
+ return (result == byteArray.size());
+}
+
+int QPpsObject::writeMessage(const QString &msg, const QVariantMap &dat)
+{
+ // Treat empty msg as an encoding error
+ if (msg.isEmpty())
+ return -1;
+
+ bool ok;
+ QByteArray byteArray = encodeMessage(msg, dat, &ok);
+
+ if (!ok)
+ return -1;
+
+ ok = write(byteArray);
+ if (!ok)
+ return error();
+
+ return EOK;
+}
+
+int QPpsObject::writeMessage(const QString &msg, const QString &id, const QVariantMap &dat)
+{
+ // Treat empty msg or id as an encoding error
+ if (msg.isEmpty() || id.isEmpty())
+ return -1;
+
+ bool ok;
+ QByteArray byteArray = encodeMessage(msg, id, dat, &ok);
+
+ if (!ok)
+ return -1;
+
+ ok = write(byteArray);
+ if (!ok)
+ return error();
+
+ return EOK;
+}
+
+bool QPpsObject::remove()
+{
+ Q_D(QPpsObject);
+
+ // reset last error
+ d->error = EOK;
+
+ // delete pps file
+ const int result = unlink(d->path.toUtf8().data());
+
+ // check success of operation
+ if (result != 0) {
+ d->error = errno;
+ return false;
+ }
+ return true;
+}
+
+// static
+QVariantMap QPpsObject::decode(const QByteArray &rawData, bool *ok)
+{
+ QPpsAttributeMap mapData = decodeWithFlags(rawData, 0, ok);
+
+ // If *ok is false, then mapData is empty, so the resulting QVariantMap
+ // will also be empty, as desired.
+ return QPpsObjectPrivate::variantMapFromPpsAttributeMap(mapData);
+}
+
+// static
+QPpsAttributeMap QPpsObject::decodeWithFlags(const QByteArray &rawData, bool *ok)
+{
+ return QPpsObject::decodeWithFlags(rawData, 0, ok);
+}
+
+// static
+QPpsAttributeMap QPpsObject::decodeWithFlags(const QByteArray &rawData,
+ QPpsAttribute *objectAttribute, bool *ok)
+{
+ safeAssign(ok, true);
+
+ bool success = false;
+ QPpsAttributeMap mapData = QPpsObjectPrivate::decode(rawData, &success);
+ if (!success) {
+ safeAssign(ok, false);
+ return QPpsAttributeMap();
+ }
+
+ // The object name is the key of the first element, and the flags of that attribute
+ // give the status for the object as a whole.
+ if (!mapData.isEmpty() && objectAttribute) {
+ QString extractedName = mapData.begin().key();
+ QPpsAttribute topmostAttribute = mapData.begin().value();
+ QPpsAttribute::Flags topmostFlags = topmostAttribute.flags();
+ QPpsAttribute toplevelAttribute =
+ QPpsAttributePrivate::createPpsAttribute(extractedName, topmostFlags);
+ *objectAttribute = toplevelAttribute;
+ }
+
+ return mapData;
+}
+
+
+// static
+QByteArray QPpsObject::encode(const QVariantMap &ppsData, bool *ok)
+{
+ safeAssign(ok, true);
+
+ bool success = false;
+ QByteArray byteArray = QPpsObjectPrivate::encode(ppsData, &success);
+ if (!success) {
+ safeAssign(ok, false);
+ return QByteArray();
+ }
+ return byteArray;
+}
+
+// static
+QByteArray QPpsObject::encodeMessage(const QString &msg, const QVariantMap &dat, bool *ok)
+{
+ safeAssign(ok, true);
+
+ // Treat empty msg as an encoding error
+ if (msg.isEmpty()) {
+ safeAssign(ok, false);
+ return QByteArray();
+ }
+
+ QVariantMap ppsData;
+ ppsData[QStringLiteral("msg")] = msg;
+ ppsData[QStringLiteral("dat")] = dat;
+
+ return QPpsObject::encode(ppsData, ok);
+}
+
+// static
+QByteArray QPpsObject::encodeMessage(const QString &msg, const QString &id, const QVariantMap &dat,
+ bool *ok)
+{
+ safeAssign(ok, true);
+
+ // Treat empty msg or id as an encoding error
+ if (msg.isEmpty() || id.isEmpty()) {
+ safeAssign(ok, false);
+ return QByteArray();
+ }
+
+ QVariantMap ppsData;
+ ppsData[QStringLiteral("msg")] = msg;
+ ppsData[QStringLiteral("id")] = id;
+ ppsData[QStringLiteral("dat")] = dat;
+
+ return QPpsObject::encode(ppsData, ok);
+}
+
+// static
+int QPpsObject::sendMessage(const QString &path, const QString &message)
+{
+ QPpsObject pps(path);
+
+ bool ok = pps.open(QPpsObject::Publish);
+ if (!ok)
+ return pps.error();
+
+ ok = pps.write(message.toLocal8Bit());
+ if (!ok)
+ return pps.error();
+
+ return EOK;
+}
+
+// static
+int QPpsObject::sendMessage(const QString &path, const QVariantMap &message)
+{
+ QPpsObject pps(path);
+
+ bool ok = pps.open(QPpsObject::Publish);
+ if (!ok)
+ return pps.error();
+
+ QByteArray payload = QPpsObject::encode(message, &ok);
+ if (!ok)
+ return -1;
+
+ ok = pps.write(payload);
+ if (!ok)
+ return pps.error();
+
+ return EOK;
+}
+
+// static
+int QPpsObject::sendMessage(const QString &path, const QString &msg, const QVariantMap &dat)
+{
+ // Treat empty msg as an encoding error
+ if (msg.isEmpty())
+ return -1;
+
+ QPpsObject pps(path);
+
+ bool ok = pps.open(QPpsObject::Publish);
+ if (!ok)
+ return pps.error();
+
+ QByteArray payload = QPpsObject::encodeMessage(msg, dat, &ok);
+ if (!ok)
+ return -1;
+
+ ok = pps.write(payload);
+ if (!ok)
+ return pps.error();
+
+ return EOK;
+}
+
+// static
+int QPpsObject::sendMessage(const QString &path, const QByteArray &ppsData)
+{
+ QPpsObject pps(path);
+
+ bool ok = pps.open(QPpsObject::Publish);
+ if (!ok)
+ return pps.error();
+
+ ok = pps.write(ppsData);
+ if (!ok)
+ return pps.error();
+
+ return EOK;
+}
diff --git a/src/corelib/kernel/qppsobject_p.h b/src/corelib/kernel/qppsobject_p.h
new file mode 100644
index 0000000000..1095796a13
--- /dev/null
+++ b/src/corelib/kernel/qppsobject_p.h
@@ -0,0 +1,130 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
+ ** 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 QPPSOBJECT_P_H
+#define QPPSOBJECT_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 "qppsattribute_p.h"
+
+#include <QMap>
+#include <QObject>
+#include <QVariantMap>
+
+QT_BEGIN_NAMESPACE
+
+class QPpsObjectPrivate;
+
+class Q_CORE_EXPORT QPpsObject : public QObject
+{
+ Q_OBJECT
+
+public:
+ enum OpenMode {
+ Publish = 1,
+ Subscribe = 2,
+ PublishSubscribe = Publish | Subscribe,
+ Create = 4,
+ DeleteContents = 8
+ };
+ Q_DECLARE_FLAGS(OpenModes, OpenMode)
+
+ explicit QPpsObject(const QString &path, QObject *parent = 0);
+ virtual ~QPpsObject();
+
+ int error() const;
+ QString errorString() const;
+
+ bool isReadyReadEnabled() const;
+ bool isBlocking() const;
+ bool setBlocking(bool enable);
+ bool isOpen() const;
+
+ bool open(QPpsObject::OpenModes mode = QPpsObject::PublishSubscribe);
+ bool close();
+ bool remove();
+
+ QByteArray read(bool *ok = 0);
+ bool write(const QByteArray &byteArray);
+
+ int writeMessage(const QString &msg, const QVariantMap &dat);
+ int writeMessage(const QString &msg, const QString &id, const QVariantMap &dat);
+
+ static QVariantMap decode(const QByteArray &rawData, bool *ok = 0);
+ static QPpsAttributeMap decodeWithFlags(const QByteArray &rawData, bool *ok = 0);
+ static QPpsAttributeMap decodeWithFlags(const QByteArray &rawData,
+ QPpsAttribute *objectAttribute, bool *ok = 0);
+
+ static QByteArray encode(const QVariantMap &ppsData, bool *ok = 0);
+ static QByteArray encodeMessage(const QString &msg, const QVariantMap &dat, bool *ok = 0);
+ static QByteArray encodeMessage(const QString &msg, const QString &id, const QVariantMap &dat,
+ bool *ok = 0);
+
+ static int sendMessage(const QString &path, const QString &message);
+ static int sendMessage(const QString &path, const QVariantMap &message);
+ static int sendMessage(const QString &path, const QString &msg, const QVariantMap &dat);
+ static int sendMessage(const QString &path, const QByteArray &ppsData);
+
+public Q_SLOTS:
+ void setReadyReadEnabled(bool enable);
+
+Q_SIGNALS:
+ void readyRead();
+
+private:
+ QScopedPointer<QPpsObjectPrivate> d_ptr;
+ Q_DECLARE_PRIVATE(QPpsObject)
+ Q_DISABLE_COPY(QPpsObject)
+};
+
+QT_END_NAMESPACE
+
+#endif // QPPSOBJECT_P_H
diff --git a/src/corelib/kernel/qppsobjectprivate_p.h b/src/corelib/kernel/qppsobjectprivate_p.h
new file mode 100644
index 0000000000..d291d6b559
--- /dev/null
+++ b/src/corelib/kernel/qppsobjectprivate_p.h
@@ -0,0 +1,128 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
+ ** 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 QPPSOBJECTPRIVATE_P_H_
+#define QPPSOBJECTPRIVATE_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 "qppsattribute_p.h"
+
+#include <QMap>
+#include <QDebug>
+
+#include <sys/pps.h>
+
+QT_BEGIN_NAMESPACE
+
+class QSocketNotifier;
+
+class QPpsObjectPrivate
+{
+public:
+ explicit QPpsObjectPrivate(const QString &path);
+
+ static QPpsAttributeMap decode(const QByteArray &rawData, bool *ok);
+ static QByteArray encode(const QVariantMap &ppsData, bool *ok);
+
+ static QVariantMap variantMapFromPpsAttributeMap(const QPpsAttributeMap &data);
+
+ QSocketNotifier *notifier;
+ QString path;
+ mutable int error;
+ int fd;
+ bool readyReadEnabled;
+
+private:
+ static QPpsAttribute::Flags readFlags(pps_decoder_t *decoder);
+ static QPpsAttribute decodeString(pps_decoder_t *decoder);
+ static QPpsAttribute decodeNumber(pps_decoder_t *decoder);
+ static QPpsAttribute decodeBool(pps_decoder_t *decoder);
+ static QPpsAttribute decodeData(pps_decoder_t *decoder);
+ static QPpsAttributeList decodeArray(pps_decoder_t *decoder, bool *ok);
+ static QPpsAttributeMap decodeObject(pps_decoder_t *decoder, bool *ok);
+ static bool decoderPush(pps_decoder_t *decoder, const char *name = 0);
+ static bool decoderPop(pps_decoder_t *decoder);
+
+ template<typename T>
+ static QPpsAttribute decodeNestedData(T (*decodeFunction)(pps_decoder_t *, bool *),
+ pps_decoder_t *decoder);
+
+ static void encodeData(pps_encoder_t *encoder, const char *name,
+ const QVariant &data, bool *ok);
+ static void encodeArray(pps_encoder_t *encoder, const QVariantList &data, bool *ok);
+ static void encodeObject(pps_encoder_t *encoder, const QVariantMap &data, bool *ok);
+
+ static QVariant variantFromPpsAttribute(const QPpsAttribute &attribute);
+};
+
+inline bool QPpsObjectPrivate::decoderPush(pps_decoder_t *decoder, const char *name)
+{
+ pps_decoder_error_t error = pps_decoder_push(decoder, name);
+ if (error != PPS_DECODER_OK) {
+ qWarning() << "QPpsObjectPrivate::decodeData: pps_decoder_push failed";
+ return false;
+ }
+ return true;
+}
+
+inline bool QPpsObjectPrivate::decoderPop(pps_decoder_t *decoder)
+{
+ pps_decoder_error_t error = pps_decoder_pop(decoder);
+ if (error != PPS_DECODER_OK) {
+ qWarning() << "QPpsObjectPrivate::decodeData: pps_decoder_pop failed";
+ return false;
+ }
+ return true;
+}
+
+QT_END_NAMESPACE
+
+#endif /* QPPSOBJECTPRIVATE_P_H_ */