diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2023-09-22 19:08:42 -0700 |
---|---|---|
committer | Thiago Macieira <thiago.macieira@intel.com> | 2023-10-21 15:21:30 -0700 |
commit | 39843b65f4b04a5d92d5a867131ba83cd3b92a02 (patch) | |
tree | 7fc68fa07dcc733ea7855ddc7a4f49d8dffa3101 /src/corelib/io | |
parent | 4107e4d8ca835b8d7d632589f12effea76b19d96 (diff) |
QStorageInfo/Linux: decode the names encoded by udev in-place
This function is only called with the name of a file coming from
QFileInfo::fileName() so it's usually already detached anyway. And if
there's nothing to decode, pass the string through without even
attempting to modify it.
Pick-to: 6.6
Change-Id: I9d43e5b91eb142d6945cfffd1787651437074d35
Reviewed-by: Ahmad Samir <a.samirh78@gmail.com>
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
Diffstat (limited to 'src/corelib/io')
-rw-r--r-- | src/corelib/io/qstorageinfo_linux.cpp | 49 |
1 files changed, 31 insertions, 18 deletions
diff --git a/src/corelib/io/qstorageinfo_linux.cpp b/src/corelib/io/qstorageinfo_linux.cpp index 15bcd978fe..2910a4bfa3 100644 --- a/src/corelib/io/qstorageinfo_linux.cpp +++ b/src/corelib/io/qstorageinfo_linux.cpp @@ -8,6 +8,7 @@ #include "qdiriterator.h" #include <private/qcore_unix_p.h> +#include <private/qtools_p.h> #if defined(Q_OS_ANDROID) # include <sys/mount.h> @@ -35,27 +36,39 @@ using namespace Qt::StringLiterals; // udev encodes the labels with ID_LABEL_FS_ENC which is done with // blkid_encode_string(). Within this function some 1-byte utf-8 // characters not considered safe (e.g. '\' or ' ') are encoded as hex -static QString decodeFsEncString(const QString &str) +static QString decodeFsEncString(QString &&str) { - QString decoded; - decoded.reserve(str.size()); - - int i = 0; - while (i < str.size()) { - if (i <= str.size() - 4) { // we need at least four characters \xAB - if (QStringView{str}.sliced(i).startsWith("\\x"_L1)) { - bool bOk; - const int code = QStringView{str}.mid(i+2, 2).toInt(&bOk, 16); - if (bOk && code >= 0x20 && code < 0x80) { - decoded += QChar(code); - i += 4; - continue; - } - } + using namespace QtMiscUtils; + qsizetype start = str.indexOf(u'\\'); + if (start < 0) + return std::move(str); + + // decode in-place + QString decoded = std::move(str); + auto ptr = reinterpret_cast<char16_t *>(decoded.begin()); + qsizetype in = start; + qsizetype out = start; + qsizetype size = decoded.size(); + + while (in < size) { + Q_ASSERT(ptr[in] == u'\\'); + if (size - in >= 4 && ptr[in + 1] == u'x') { // we need four characters: \xAB + int c = fromHex(ptr[in + 2]) << 4; + c |= fromHex(ptr[in + 3]); + if (Q_UNLIKELY(c < 0)) + c = QChar::ReplacementCharacter; // bad hex sequence + ptr[out++] = c; + in += 4; + } + + for ( ; in < size; ++in) { + char16_t c = ptr[in]; + if (c == u'\\') + break; + ptr[out++] = c; } - decoded += str.at(i); - ++i; } + decoded.resize(out); return decoded; } |