summaryrefslogtreecommitdiffstats
path: root/src/corelib/io
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2023-09-22 19:08:42 -0700
committerThiago Macieira <thiago.macieira@intel.com>2023-10-21 15:21:30 -0700
commit39843b65f4b04a5d92d5a867131ba83cd3b92a02 (patch)
tree7fc68fa07dcc733ea7855ddc7a4f49d8dffa3101 /src/corelib/io
parent4107e4d8ca835b8d7d632589f12effea76b19d96 (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.cpp49
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;
}