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>
This commit is contained in:
parent
4107e4d8ca
commit
39843b65f4
@ -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());
|
||||
using namespace QtMiscUtils;
|
||||
qsizetype start = str.indexOf(u'\\');
|
||||
if (start < 0)
|
||||
return std::move(str);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user