summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2017-06-15 13:04:36 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2017-06-21 06:37:24 +0000
commite5e1fac136065d7c8afc49ac72cb517f64c87910 (patch)
tree23bfea53fd8ffe183b5bbad7e0c76387b165ff16
parent4d70e03002de5cfc558398a235755470ad2c8408 (diff)
Move endian integers to qendian_p.h
The endian integers have more use than just in QJson, and is already used separately by QtDeclarative. This patch moves q_littleendian out of qjson_p.h and matches it with a corresponding q_bigendian, and puts it to use in simplifying endian handling in the ico image handler. Change-Id: I975bb701a089256db8ced3cb53b4bd62cdfb02dd Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r--src/corelib/global/global.pri1
-rw-r--r--src/corelib/global/qendian_p.h141
-rw-r--r--src/corelib/json/qjson.cpp13
-rw-r--r--src/corelib/json/qjson_p.h38
-rw-r--r--src/gui/image/qimage_conversions.cpp9
-rw-r--r--src/plugins/imageformats/ico/ico.pro1
-rw-r--r--src/plugins/imageformats/ico/qicohandler.cpp128
7 files changed, 185 insertions, 146 deletions
diff --git a/src/corelib/global/global.pri b/src/corelib/global/global.pri
index a087452d06..efc7f3cd22 100644
--- a/src/corelib/global/global.pri
+++ b/src/corelib/global/global.pri
@@ -9,6 +9,7 @@ HEADERS += \
global/qprocessordetection.h \
global/qnamespace.h \
global/qendian.h \
+ global/qendian_p.h \
global/qnumeric_p.h \
global/qnumeric.h \
global/qfloat16_p.h \
diff --git a/src/corelib/global/qendian_p.h b/src/corelib/global/qendian_p.h
new file mode 100644
index 0000000000..b279701a31
--- /dev/null
+++ b/src/corelib/global/qendian_p.h
@@ -0,0 +1,141 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QENDIAN_P_H
+#define QENDIAN_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qendian.h"
+
+QT_BEGIN_NAMESPACE
+
+template<class S>
+class QSpecialInteger
+{
+ typedef typename S::StorageType T;
+ T val;
+public:
+ QSpecialInteger() = default;
+ explicit Q_DECL_CONSTEXPR QSpecialInteger(T i) : val(S::toSpecial(i)) {}
+
+ QSpecialInteger &operator =(T i) { val = S::toSpecial(i); return *this; }
+ operator T() const { return S::fromSpecial(val); }
+
+ bool operator ==(QSpecialInteger<S> i) const { return val == i.val; }
+ bool operator !=(QSpecialInteger<S> i) const { return val != i.val; }
+
+ QSpecialInteger &operator +=(T i)
+ { return (*this = S::fromSpecial(val) + i); }
+ QSpecialInteger &operator -=(T i)
+ { return (*this = S::fromSpecial(val) - i); }
+ QSpecialInteger &operator *=(T i)
+ { return (*this = S::fromSpecial(val) * i); }
+ QSpecialInteger &operator >>=(T i)
+ { return (*this = S::fromSpecial(val) >> i); }
+ QSpecialInteger &operator <<=(T i)
+ { return (*this = S::fromSpecial(val) << i); }
+ QSpecialInteger &operator /=(T i)
+ { return (*this = S::fromSpecial(val) / i); }
+ QSpecialInteger &operator %=(T i)
+ { return (*this = S::fromSpecial(val) % i); }
+ QSpecialInteger &operator |=(T i)
+ { return (*this = S::fromSpecial(val) | i); }
+ QSpecialInteger &operator &=(T i)
+ { return (*this = S::fromSpecial(val) & i); }
+ QSpecialInteger &operator ^=(T i)
+ { return (*this = S::fromSpecial(val) ^ i); }
+};
+
+template<typename T>
+class QLittleEndianStorageType {
+public:
+ typedef T StorageType;
+ static Q_DECL_CONSTEXPR T toSpecial(T source) { return qToLittleEndian(source); }
+ static Q_DECL_CONSTEXPR T fromSpecial(T source) { return qFromLittleEndian(source); }
+};
+
+template<typename T>
+class QBigEndianStorageType {
+public:
+ typedef T StorageType;
+ static Q_DECL_CONSTEXPR T toSpecial(T source) { return qToBigEndian(source); }
+ static Q_DECL_CONSTEXPR T fromSpecial(T source) { return qFromBigEndian(source); }
+};
+
+template<typename T>
+using QLEInteger = QSpecialInteger<QLittleEndianStorageType<T>>;
+
+template<typename T>
+using QBEInteger = QSpecialInteger<QBigEndianStorageType<T>>;
+
+template <typename T>
+class QTypeInfo<QLEInteger<T> >
+ : public QTypeInfoMerger<QLEInteger<T>, T> {};
+
+template <typename T>
+class QTypeInfo<QBEInteger<T> >
+ : public QTypeInfoMerger<QBEInteger<T>, T> {};
+
+typedef QLEInteger<qint16> qint16_le;
+typedef QLEInteger<qint32> qint32_le;
+typedef QLEInteger<qint64> qint64_le;
+typedef QLEInteger<quint16> quint16_le;
+typedef QLEInteger<quint32> quint32_le;
+typedef QLEInteger<quint64> quint64_le;
+
+typedef QBEInteger<qint16> qint16_be;
+typedef QBEInteger<qint32> qint32_be;
+typedef QBEInteger<qint64> qint64_be;
+typedef QBEInteger<quint16> quint16_be;
+typedef QBEInteger<quint32> quint32_be;
+typedef QBEInteger<quint64> quint64_be;
+
+QT_END_NAMESPACE
+
+#endif // QENDIAN_P_H
diff --git a/src/corelib/json/qjson.cpp b/src/corelib/json/qjson.cpp
index d509349a51..e4bca3bcd0 100644
--- a/src/corelib/json/qjson.cpp
+++ b/src/corelib/json/qjson.cpp
@@ -45,15 +45,8 @@ QT_BEGIN_NAMESPACE
namespace QJsonPrivate
{
-#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
-#define Q_TO_LITTLE_ENDIAN(x) (x)
-#else
-#define Q_TO_LITTLE_ENDIAN(x) ( ((x & 0xff) << 24) | ((x & 0xff00) << 8) | ((x & 0xff0000) >> 8) | ((x & 0xff000000) >> 24) )
-#endif
-
-static const Base emptyArray = { { Q_TO_LITTLE_ENDIAN(sizeof(Base)) }, { 0 }, { 0 } };
-static const Base emptyObject = { { Q_TO_LITTLE_ENDIAN(sizeof(Base)) }, { 0 }, { 0 } };
-
+static Q_CONSTEXPR Base emptyArray = { { qle_uint(sizeof(Base)) }, { 0 }, { qle_uint(0) } };
+static Q_CONSTEXPR Base emptyObject = { { qle_uint(sizeof(Base)) }, { 0 }, { qle_uint(0) } };
void Data::compact()
{
@@ -394,7 +387,7 @@ int Value::requiredStorage(QJsonValue &v, bool *compressed)
v.d->compact();
v.base = static_cast<QJsonPrivate::Base *>(v.d->header->root());
}
- return v.base ? v.base->size : sizeof(QJsonPrivate::Base);
+ return v.base ? uint(v.base->size) : sizeof(QJsonPrivate::Base);
case QJsonValue::Undefined:
case QJsonValue::Null:
case QJsonValue::Bool:
diff --git a/src/corelib/json/qjson_p.h b/src/corelib/json/qjson_p.h
index c012ec2662..5d600843aa 100644
--- a/src/corelib/json/qjson_p.h
+++ b/src/corelib/json/qjson_p.h
@@ -61,6 +61,7 @@
#include <qendian.h>
#include <qnumeric.h>
+#include "private/qendian_p.h"
#include "private/qsimd_p.h"
#include <limits.h>
@@ -131,42 +132,7 @@ class Value;
class Entry;
template<typename T>
-class q_littleendian
-{
-public:
- T val;
-
- q_littleendian &operator =(T i) { val = qToLittleEndian(i); return *this; }
- operator T() const { return qFromLittleEndian(val); }
-
- bool operator ==(T i) { return qFromLittleEndian(val) == i; }
- bool operator !=(T i) { return qFromLittleEndian(val) != i; }
- bool operator ==(q_littleendian<T> i) { return val == i.val; }
- bool operator !=(q_littleendian<T> i) { return val != i.val; }
- bool operator <(T i) { return qFromLittleEndian(val) < i; }
- bool operator >(T i) { return qFromLittleEndian(val) > i; }
- bool operator <=(T i) { return qFromLittleEndian(val) <= i; }
- bool operator >=(T i) { return qFromLittleEndian(val) >= i; }
- q_littleendian &operator +=(T i) {
- val = qToLittleEndian(qFromLittleEndian(val) + i);
- return *this;
- }
- q_littleendian &operator |=(T i) {
- val = qToLittleEndian(qFromLittleEndian(val) | i);
- return *this;
- }
- q_littleendian &operator &=(T i) {
- val = qToLittleEndian(qFromLittleEndian(val) & i);
- return *this;
- }
-};
-} // namespace QJsonPrivate
-
-template <typename T>
-class QTypeInfo<QJsonPrivate::q_littleendian<T> >
- : public QTypeInfoMerger<QJsonPrivate::q_littleendian<T>, T> {};
-
-namespace QJsonPrivate {
+using q_littleendian = QLEInteger<T>;
typedef q_littleendian<short> qle_short;
typedef q_littleendian<unsigned short> qle_ushort;
diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp
index 659e7d9901..aa7cfe9547 100644
--- a/src/gui/image/qimage_conversions.cpp
+++ b/src/gui/image/qimage_conversions.cpp
@@ -40,6 +40,7 @@
#include <private/qdrawhelper_p.h>
#include <private/qguiapplication_p.h>
#include <private/qcolorprofile_p.h>
+#include <private/qendian_p.h>
#include <private/qsimd_p.h>
#include <private/qimage_p.h>
#include <qendian.h>
@@ -341,10 +342,10 @@ Q_GUI_EXPORT void QT_FASTCALL qt_convert_rgb888_to_rgb32(quint32 *dest_data, con
// Handle 4 pixels at a time 12 bytes input to 16 bytes output.
for (; pixel + 3 < len; pixel += 4) {
- const quint32 *src_packed = (const quint32 *) src_data;
- const quint32 src1 = qFromBigEndian(src_packed[0]);
- const quint32 src2 = qFromBigEndian(src_packed[1]);
- const quint32 src3 = qFromBigEndian(src_packed[2]);
+ const quint32_be *src_packed = reinterpret_cast<const quint32_be *>(src_data);
+ const quint32 src1 = src_packed[0];
+ const quint32 src2 = src_packed[1];
+ const quint32 src3 = src_packed[2];
dest_data[0] = 0xff000000 | (src1 >> 8);
dest_data[1] = 0xff000000 | (src1 << 16) | (src2 >> 16);
diff --git a/src/plugins/imageformats/ico/ico.pro b/src/plugins/imageformats/ico/ico.pro
index 7ca1f18cb1..c8bb37eff2 100644
--- a/src/plugins/imageformats/ico/ico.pro
+++ b/src/plugins/imageformats/ico/ico.pro
@@ -3,6 +3,7 @@ TARGET = qico
HEADERS += main.h qicohandler.h
SOURCES += main.cpp qicohandler.cpp
OTHER_FILES += ico.json
+QT += core-private
PLUGIN_TYPE = imageformats
PLUGIN_CLASS_NAME = QICOPlugin
diff --git a/src/plugins/imageformats/ico/qicohandler.cpp b/src/plugins/imageformats/ico/qicohandler.cpp
index 17d1aeeb5d..e61173db30 100644
--- a/src/plugins/imageformats/ico/qicohandler.cpp
+++ b/src/plugins/imageformats/ico/qicohandler.cpp
@@ -48,6 +48,7 @@
#include "qicohandler.h"
#include <QtCore/qendian.h>
+#include <private/qendian_p.h>
#include <QtGui/QImage>
#include <QtCore/QFile>
#include <QtCore/QBuffer>
@@ -63,34 +64,34 @@ typedef struct
quint8 bHeight; // Height of the image (actual height, not times 2)
quint8 bColorCount; // Number of colors in image (0 if >=8bpp) [ not ture ]
quint8 bReserved; // Reserved
- quint16 wPlanes; // Color Planes
- quint16 wBitCount; // Bits per pixel
- quint32 dwBytesInRes; // how many bytes in this resource?
- quint32 dwImageOffset; // where in the file is this image
+ quint16_le wPlanes; // Color Planes
+ quint16_le wBitCount; // Bits per pixel
+ quint32_le dwBytesInRes; // how many bytes in this resource?
+ quint32_le dwImageOffset; // where in the file is this image
} ICONDIRENTRY, *LPICONDIRENTRY;
#define ICONDIRENTRY_SIZE 16
typedef struct
{
- quint16 idReserved; // Reserved
- quint16 idType; // resource type (1 for icons, 2 for cursors)
- quint16 idCount; // how many images?
+ quint16_le idReserved; // Reserved
+ quint16_le idType; // resource type (1 for icons, 2 for cursors)
+ quint16_le idCount; // how many images?
ICONDIRENTRY idEntries[1]; // the entries for each image
} ICONDIR, *LPICONDIR;
#define ICONDIR_SIZE 6 // Exclude the idEntries field
typedef struct { // BMP information header
- quint32 biSize; // size of this struct
- quint32 biWidth; // pixmap width
- quint32 biHeight; // pixmap height (specifies the combined height of the XOR and AND masks)
- quint16 biPlanes; // should be 1
- quint16 biBitCount; // number of bits per pixel
- quint32 biCompression; // compression method
- quint32 biSizeImage; // size of image
- quint32 biXPelsPerMeter; // horizontal resolution
- quint32 biYPelsPerMeter; // vertical resolution
- quint32 biClrUsed; // number of colors used
- quint32 biClrImportant; // number of important colors
+ quint32_le biSize; // size of this struct
+ quint32_le biWidth; // pixmap width
+ quint32_le biHeight; // pixmap height (specifies the combined height of the XOR and AND masks)
+ quint16_le biPlanes; // should be 1
+ quint16_le biBitCount; // number of bits per pixel
+ quint32_le biCompression; // compression method
+ quint32_le biSizeImage; // size of image
+ quint32_le biXPelsPerMeter; // horizontal resolution
+ quint32_le biYPelsPerMeter; // vertical resolution
+ quint32_le biClrUsed; // number of colors used
+ quint32_le biClrImportant; // number of important colors
} BMP_INFOHDR ,*LPBMP_INFOHDR;
#define BMP_INFOHDR_SIZE 40
@@ -140,108 +141,43 @@ private:
// Data readers and writers that takes care of alignment and endian stuff.
static bool readIconDirEntry(QIODevice *iodev, ICONDIRENTRY *iconDirEntry)
{
- if (iodev) {
- uchar tmp[ICONDIRENTRY_SIZE];
- if (iodev->read((char*)tmp, ICONDIRENTRY_SIZE) == ICONDIRENTRY_SIZE) {
- iconDirEntry->bWidth = tmp[0];
- iconDirEntry->bHeight = tmp[1];
- iconDirEntry->bColorCount = tmp[2];
- iconDirEntry->bReserved = tmp[3];
-
- iconDirEntry->wPlanes = qFromLittleEndian<quint16>(&tmp[4]);
- iconDirEntry->wBitCount = qFromLittleEndian<quint16>(&tmp[6]);
- iconDirEntry->dwBytesInRes = qFromLittleEndian<quint32>(&tmp[8]);
- iconDirEntry->dwImageOffset = qFromLittleEndian<quint32>(&tmp[12]);
- return true;
- }
- }
+ if (iodev)
+ return (iodev->read((char*)iconDirEntry, ICONDIRENTRY_SIZE) == ICONDIRENTRY_SIZE);
return false;
}
static bool writeIconDirEntry(QIODevice *iodev, const ICONDIRENTRY &iconEntry)
{
- if (iodev) {
- uchar tmp[ICONDIRENTRY_SIZE];
- tmp[0] = iconEntry.bWidth;
- tmp[1] = iconEntry.bHeight;
- tmp[2] = iconEntry.bColorCount;
- tmp[3] = iconEntry.bReserved;
- qToLittleEndian<quint16>(iconEntry.wPlanes, &tmp[4]);
- qToLittleEndian<quint16>(iconEntry.wBitCount, &tmp[6]);
- qToLittleEndian<quint32>(iconEntry.dwBytesInRes, &tmp[8]);
- qToLittleEndian<quint32>(iconEntry.dwImageOffset, &tmp[12]);
- return iodev->write((char*)tmp, ICONDIRENTRY_SIZE) == ICONDIRENTRY_SIZE;
- }
-
+ if (iodev)
+ return iodev->write((char*)&iconEntry, ICONDIRENTRY_SIZE) == ICONDIRENTRY_SIZE;
return false;
}
static bool readIconDir(QIODevice *iodev, ICONDIR *iconDir)
{
- if (iodev) {
- uchar tmp[ICONDIR_SIZE];
- if (iodev->read((char*)tmp, ICONDIR_SIZE) == ICONDIR_SIZE) {
- iconDir->idReserved = qFromLittleEndian<quint16>(&tmp[0]);
- iconDir->idType = qFromLittleEndian<quint16>(&tmp[2]);
- iconDir->idCount = qFromLittleEndian<quint16>(&tmp[4]);
- return true;
- }
- }
+ if (iodev)
+ return (iodev->read((char*)iconDir, ICONDIR_SIZE) == ICONDIR_SIZE);
return false;
}
static bool writeIconDir(QIODevice *iodev, const ICONDIR &iconDir)
{
- if (iodev) {
- uchar tmp[6];
- qToLittleEndian(iconDir.idReserved, tmp);
- qToLittleEndian(iconDir.idType, &tmp[2]);
- qToLittleEndian(iconDir.idCount, &tmp[4]);
- return iodev->write((char*)tmp, 6) == 6;
- }
+ if (iodev)
+ return iodev->write((char*)&iconDir, 6) == 6;
return false;
}
static bool readBMPInfoHeader(QIODevice *iodev, BMP_INFOHDR *pHeader)
{
- if (iodev) {
- uchar header[BMP_INFOHDR_SIZE];
- if (iodev->read((char*)header, BMP_INFOHDR_SIZE) == BMP_INFOHDR_SIZE) {
- pHeader->biSize = qFromLittleEndian<quint32>(&header[0]);
- pHeader->biWidth = qFromLittleEndian<quint32>(&header[4]);
- pHeader->biHeight = qFromLittleEndian<quint32>(&header[8]);
- pHeader->biPlanes = qFromLittleEndian<quint16>(&header[12]);
- pHeader->biBitCount = qFromLittleEndian<quint16>(&header[14]);
- pHeader->biCompression = qFromLittleEndian<quint32>(&header[16]);
- pHeader->biSizeImage = qFromLittleEndian<quint32>(&header[20]);
- pHeader->biXPelsPerMeter = qFromLittleEndian<quint32>(&header[24]);
- pHeader->biYPelsPerMeter = qFromLittleEndian<quint32>(&header[28]);
- pHeader->biClrUsed = qFromLittleEndian<quint32>(&header[32]);
- pHeader->biClrImportant = qFromLittleEndian<quint32>(&header[36]);
- return true;
- }
- }
+ if (iodev)
+ return (iodev->read((char*)pHeader, BMP_INFOHDR_SIZE) == BMP_INFOHDR_SIZE);
return false;
}
static bool writeBMPInfoHeader(QIODevice *iodev, const BMP_INFOHDR &header)
{
- if (iodev) {
- uchar tmp[BMP_INFOHDR_SIZE];
- qToLittleEndian<quint32>(header.biSize, &tmp[0]);
- qToLittleEndian<quint32>(header.biWidth, &tmp[4]);
- qToLittleEndian<quint32>(header.biHeight, &tmp[8]);
- qToLittleEndian<quint16>(header.biPlanes, &tmp[12]);
- qToLittleEndian<quint16>(header.biBitCount, &tmp[14]);
- qToLittleEndian<quint32>(header.biCompression, &tmp[16]);
- qToLittleEndian<quint32>(header.biSizeImage, &tmp[20]);
- qToLittleEndian<quint32>(header.biXPelsPerMeter, &tmp[24]);
- qToLittleEndian<quint32>(header.biYPelsPerMeter, &tmp[28]);
- qToLittleEndian<quint32>(header.biClrUsed, &tmp[32]);
- qToLittleEndian<quint32>(header.biClrImportant, &tmp[36]);
-
- return iodev->write((char*)tmp, BMP_INFOHDR_SIZE) == BMP_INFOHDR_SIZE;
- }
+ if (iodev)
+ return iodev->write((char*)&header, BMP_INFOHDR_SIZE) == BMP_INFOHDR_SIZE;
return false;
}
@@ -561,7 +497,7 @@ QImage ICOReader::iconAt(int index)
if (icoAttrib.depth == 32) // there's no colormap
icoAttrib.ncolors = 0;
else // # colors used
- icoAttrib.ncolors = header.biClrUsed ? header.biClrUsed : 1 << icoAttrib.nbits;
+ icoAttrib.ncolors = header.biClrUsed ? uint(header.biClrUsed) : 1 << icoAttrib.nbits;
if (icoAttrib.ncolors > 256) //color table can't be more than 256
return img;
icoAttrib.w = iconEntry.bWidth;