summaryrefslogtreecommitdiffstats
path: root/src/corelib/plugin/quuid.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/plugin/quuid.cpp')
-rw-r--r--src/corelib/plugin/quuid.cpp215
1 files changed, 125 insertions, 90 deletions
diff --git a/src/corelib/plugin/quuid.cpp b/src/corelib/plugin/quuid.cpp
index 0afce7fcf0..c9644c73d3 100644
--- a/src/corelib/plugin/quuid.cpp
+++ b/src/corelib/plugin/quuid.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -49,21 +50,25 @@
#endif
QT_BEGIN_NAMESPACE
-template <class Char, class Integral>
-void _q_toHex(Char *&dst, Integral value)
+// 16 bytes (a uint, two shorts and a uchar[8]), each represented by two hex
+// digits; plus four dashes and a pair of enclosing brace: 16*2 + 4 + 2 = 38.
+enum { MaxStringUuidLength = 38 };
+
+template <class Integral>
+void _q_toHex(char *&dst, Integral value)
{
value = qToBigEndian(value);
const char* p = reinterpret_cast<const char*>(&value);
for (uint i = 0; i < sizeof(Integral); ++i, dst += 2) {
- dst[0] = Char(QtMiscUtils::toHexLower((p[i] >> 4) & 0xf));
- dst[1] = Char(QtMiscUtils::toHexLower(p[i] & 0xf));
+ dst[0] = QtMiscUtils::toHexLower((p[i] >> 4) & 0xf);
+ dst[1] = QtMiscUtils::toHexLower(p[i] & 0xf);
}
}
-template <class Char, class Integral>
-bool _q_fromHex(const Char *&src, Integral &value)
+template <class Integral>
+bool _q_fromHex(const char *&src, Integral &value)
{
value = 0;
@@ -79,48 +84,64 @@ bool _q_fromHex(const Char *&src, Integral &value)
return true;
}
-template <class Char>
-void _q_uuidToHex(Char *&dst, const uint &d1, const ushort &d2, const ushort &d3, const uchar (&d4)[8])
+static char *_q_uuidToHex(const QUuid &uuid, char *dst)
{
- *dst++ = Char('{');
- _q_toHex(dst, d1);
- *dst++ = Char('-');
- _q_toHex(dst, d2);
- *dst++ = Char('-');
- _q_toHex(dst, d3);
- *dst++ = Char('-');
+ *dst++ = '{';
+ _q_toHex(dst, uuid.data1);
+ *dst++ = '-';
+ _q_toHex(dst, uuid.data2);
+ *dst++ = '-';
+ _q_toHex(dst, uuid.data3);
+ *dst++ = '-';
for (int i = 0; i < 2; i++)
- _q_toHex(dst, d4[i]);
- *dst++ = Char('-');
+ _q_toHex(dst, uuid.data4[i]);
+ *dst++ = '-';
for (int i = 2; i < 8; i++)
- _q_toHex(dst, d4[i]);
- *dst = Char('}');
+ _q_toHex(dst, uuid.data4[i]);
+ *dst++ = '}';
+ return dst;
}
-template <class Char>
-bool _q_uuidFromHex(const Char *&src, uint &d1, ushort &d2, ushort &d3, uchar (&d4)[8])
+/*!
+ \internal
+
+ Parses the string representation of a UUID (with optional surrounding "{}")
+ by reading at most MaxStringUuidLength (38) characters from \a src, which
+ may be \c nullptr. Stops at the first invalid character (which includes a
+ premature NUL).
+
+ Returns the successfully parsed QUuid, or a null QUuid in case of failure.
+*/
+Q_NEVER_INLINE
+static QUuid _q_uuidFromHex(const char *src)
{
- if (*src == Char('{'))
- src++;
- if (!_q_fromHex(src, d1)
- || *src++ != Char('-')
- || !_q_fromHex(src, d2)
- || *src++ != Char('-')
- || !_q_fromHex(src, d3)
- || *src++ != Char('-')
- || !_q_fromHex(src, d4[0])
- || !_q_fromHex(src, d4[1])
- || *src++ != Char('-')
- || !_q_fromHex(src, d4[2])
- || !_q_fromHex(src, d4[3])
- || !_q_fromHex(src, d4[4])
- || !_q_fromHex(src, d4[5])
- || !_q_fromHex(src, d4[6])
- || !_q_fromHex(src, d4[7])) {
- return false;
+ uint d1;
+ ushort d2, d3;
+ uchar d4[8];
+
+ if (src) {
+ if (*src == '{')
+ src++;
+ if (Q_LIKELY( _q_fromHex(src, d1)
+ && *src++ == '-'
+ && _q_fromHex(src, d2)
+ && *src++ == '-'
+ && _q_fromHex(src, d3)
+ && *src++ == '-'
+ && _q_fromHex(src, d4[0])
+ && _q_fromHex(src, d4[1])
+ && *src++ == '-'
+ && _q_fromHex(src, d4[2])
+ && _q_fromHex(src, d4[3])
+ && _q_fromHex(src, d4[4])
+ && _q_fromHex(src, d4[5])
+ && _q_fromHex(src, d4[6])
+ && _q_fromHex(src, d4[7]))) {
+ return QUuid(d1, d2, d3, d4[0], d4[1], d4[2], d4[3], d4[4], d4[5], d4[6], d4[7]);
+ }
}
- return true;
+ return QUuid();
}
#ifndef QT_BOOTSTRAPPED
@@ -331,7 +352,7 @@ static QUuid createFromName(const QUuid &ns, const QByteArray &baseData, QCrypto
/*!
Creates a QUuid object from the string \a text, which must be
formatted as five hex fields separated by '-', e.g.,
- "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}" where 'x' is a hex
+ "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}" where each 'x' is a hex
digit. The curly braces shown here are optional, but it is normal to
include them. If the conversion fails, a null UUID is created. See
toString() for an explanation of how the five hex fields map to the
@@ -340,45 +361,76 @@ static QUuid createFromName(const QUuid &ns, const QByteArray &baseData, QCrypto
\sa toString(), QUuid()
*/
QUuid::QUuid(const QString &text)
+ : QUuid(fromString(text))
{
- if (text.length() < 36) {
- *this = QUuid();
- return;
- }
+}
+
+/*!
+ \since 5.10
- const ushort *data = reinterpret_cast<const ushort *>(text.unicode());
+ Creates a QUuid object from the string \a text, which must be
+ formatted as five hex fields separated by '-', e.g.,
+ "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}" where each 'x' is a hex
+ digit. The curly braces shown here are optional, but it is normal to
+ include them. If the conversion fails, a null UUID is returned. See
+ toString() for an explanation of how the five hex fields map to the
+ public data members in QUuid.
- if (*data == '{' && text.length() < 37) {
- *this = QUuid();
- return;
- }
+ \sa toString(), QUuid()
+*/
+QUuid QUuid::fromString(QStringView text) Q_DECL_NOTHROW
+{
+ if (text.size() > MaxStringUuidLength)
+ text = text.left(MaxStringUuidLength); // text.truncate(MaxStringUuidLength);
+
+ char latin1[MaxStringUuidLength + 1];
+ char *dst = latin1;
+
+ for (QChar ch : text)
+ *dst++ = ch.toLatin1();
+
+ *dst++ = '\0'; // don't read garbage as potentially valid data
- if (!_q_uuidFromHex(data, data1, data2, data3, data4)) {
- *this = QUuid();
- return;
+ return _q_uuidFromHex(latin1);
+}
+
+/*!
+ \since 5.10
+ \overload
+
+ Creates a QUuid object from the string \a text, which must be
+ formatted as five hex fields separated by '-', e.g.,
+ "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}" where each 'x' is a hex
+ digit. The curly braces shown here are optional, but it is normal to
+ include them. If the conversion fails, a null UUID is returned. See
+ toString() for an explanation of how the five hex fields map to the
+ public data members in QUuid.
+
+ \sa toString(), QUuid()
+*/
+QUuid QUuid::fromString(QLatin1String text) Q_DECL_NOTHROW
+{
+ if (Q_UNLIKELY(text.size() < MaxStringUuidLength - 2
+ || (text.front() == QLatin1Char('{') && text.size() < MaxStringUuidLength - 1))) {
+ // Too short. Don't call _q_uuidFromHex(); QL1Ss need not be NUL-terminated,
+ // and we don't want to read trailing garbage as potentially valid data.
+ text = QLatin1String();
}
+ return _q_uuidFromHex(text.data());
}
/*!
\internal
*/
QUuid::QUuid(const char *text)
+ : QUuid(_q_uuidFromHex(text))
{
- if (!text) {
- *this = QUuid();
- return;
- }
-
- if (!_q_uuidFromHex(text, data1, data2, data3, data4)) {
- *this = QUuid();
- return;
- }
}
/*!
Creates a QUuid object from the QByteArray \a text, which must be
formatted as five hex fields separated by '-', e.g.,
- "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}" where 'x' is a hex
+ "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}" where each 'x' is a hex
digit. The curly braces shown here are optional, but it is normal to
include them. If the conversion fails, a null UUID is created. See
toByteArray() for an explanation of how the five hex fields map to the
@@ -389,23 +441,8 @@ QUuid::QUuid(const char *text)
\sa toByteArray(), QUuid()
*/
QUuid::QUuid(const QByteArray &text)
+ : QUuid(fromString(QLatin1String(text.data(), text.size())))
{
- if (text.length() < 36) {
- *this = QUuid();
- return;
- }
-
- const char *data = text.constData();
-
- if (*data == '{' && text.length() < 37) {
- *this = QUuid();
- return;
- }
-
- if (!_q_uuidFromHex(data, data1, data2, data3, data4)) {
- *this = QUuid();
- return;
- }
}
/*!
@@ -548,12 +585,11 @@ QUuid QUuid::fromRfc4122(const QByteArray &bytes)
*/
QString QUuid::toString() const
{
- QString result(38, Qt::Uninitialized);
- ushort *data = (ushort *)result.data();
-
- _q_uuidToHex(data, data1, data2, data3, data4);
-
- return result;
+ char latin1[MaxStringUuidLength];
+ const auto end = _q_uuidToHex(*this, latin1);
+ Q_ASSERT(end - latin1 == MaxStringUuidLength);
+ Q_UNUSED(end);
+ return QString::fromLatin1(latin1, MaxStringUuidLength);
}
/*!
@@ -594,11 +630,10 @@ QString QUuid::toString() const
*/
QByteArray QUuid::toByteArray() const
{
- QByteArray result(38, Qt::Uninitialized);
- char *data = result.data();
-
- _q_uuidToHex(data, data1, data2, data3, data4);
-
+ QByteArray result(MaxStringUuidLength, Qt::Uninitialized);
+ const auto end = _q_uuidToHex(*this, const_cast<char*>(result.constData()));
+ Q_ASSERT(end - result.constData() == MaxStringUuidLength);
+ Q_UNUSED(end);
return result;
}