From e5e1fac136065d7c8afc49ac72cb517f64c87910 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Thu, 15 Jun 2017 13:04:36 +0200 Subject: 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 --- src/corelib/global/global.pri | 1 + src/corelib/global/qendian_p.h | 141 +++++++++++++++++++++++++++ src/corelib/json/qjson.cpp | 13 +-- src/corelib/json/qjson_p.h | 38 +------- src/gui/image/qimage_conversions.cpp | 9 +- src/plugins/imageformats/ico/ico.pro | 1 + src/plugins/imageformats/ico/qicohandler.cpp | 128 ++++++------------------ 7 files changed, 185 insertions(+), 146 deletions(-) create mode 100644 src/corelib/global/qendian_p.h 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 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 i) const { return val == i.val; } + bool operator !=(QSpecialInteger 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 +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 +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 +using QLEInteger = QSpecialInteger>; + +template +using QBEInteger = QSpecialInteger>; + +template +class QTypeInfo > + : public QTypeInfoMerger, T> {}; + +template +class QTypeInfo > + : public QTypeInfoMerger, T> {}; + +typedef QLEInteger qint16_le; +typedef QLEInteger qint32_le; +typedef QLEInteger qint64_le; +typedef QLEInteger quint16_le; +typedef QLEInteger quint32_le; +typedef QLEInteger quint64_le; + +typedef QBEInteger qint16_be; +typedef QBEInteger qint32_be; +typedef QBEInteger qint64_be; +typedef QBEInteger quint16_be; +typedef QBEInteger quint32_be; +typedef QBEInteger 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(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 #include +#include "private/qendian_p.h" #include "private/qsimd_p.h" #include @@ -131,42 +132,7 @@ class Value; class Entry; template -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 i) { return val == i.val; } - bool operator !=(q_littleendian 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 -class QTypeInfo > - : public QTypeInfoMerger, T> {}; - -namespace QJsonPrivate { +using q_littleendian = QLEInteger; typedef q_littleendian qle_short; typedef q_littleendian 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 #include #include +#include #include #include #include @@ -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(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 +#include #include #include #include @@ -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(&tmp[4]); - iconDirEntry->wBitCount = qFromLittleEndian(&tmp[6]); - iconDirEntry->dwBytesInRes = qFromLittleEndian(&tmp[8]); - iconDirEntry->dwImageOffset = qFromLittleEndian(&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(iconEntry.wPlanes, &tmp[4]); - qToLittleEndian(iconEntry.wBitCount, &tmp[6]); - qToLittleEndian(iconEntry.dwBytesInRes, &tmp[8]); - qToLittleEndian(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(&tmp[0]); - iconDir->idType = qFromLittleEndian(&tmp[2]); - iconDir->idCount = qFromLittleEndian(&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(&header[0]); - pHeader->biWidth = qFromLittleEndian(&header[4]); - pHeader->biHeight = qFromLittleEndian(&header[8]); - pHeader->biPlanes = qFromLittleEndian(&header[12]); - pHeader->biBitCount = qFromLittleEndian(&header[14]); - pHeader->biCompression = qFromLittleEndian(&header[16]); - pHeader->biSizeImage = qFromLittleEndian(&header[20]); - pHeader->biXPelsPerMeter = qFromLittleEndian(&header[24]); - pHeader->biYPelsPerMeter = qFromLittleEndian(&header[28]); - pHeader->biClrUsed = qFromLittleEndian(&header[32]); - pHeader->biClrImportant = qFromLittleEndian(&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(header.biSize, &tmp[0]); - qToLittleEndian(header.biWidth, &tmp[4]); - qToLittleEndian(header.biHeight, &tmp[8]); - qToLittleEndian(header.biPlanes, &tmp[12]); - qToLittleEndian(header.biBitCount, &tmp[14]); - qToLittleEndian(header.biCompression, &tmp[16]); - qToLittleEndian(header.biSizeImage, &tmp[20]); - qToLittleEndian(header.biXPelsPerMeter, &tmp[24]); - qToLittleEndian(header.biYPelsPerMeter, &tmp[28]); - qToLittleEndian(header.biClrUsed, &tmp[32]); - qToLittleEndian(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; -- cgit v1.2.3