QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
fromencodedcomponenthelper.cpp
Go to the documentation of this file.
1/***************************************************************************
2 fromencodedcomponenthelper.h
3 -------------------
4 begin : 22.06.2021
5 copyright : (C) 2021 by Denis Rouzaud
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
19
20#include <QString>
21
22static bool qt_is_ascii( const char *&ptr, const char *end ) noexcept
23{
24 while ( ptr + 4 <= end )
25 {
26 quint32 data = qFromUnaligned<quint32>( ptr );
27 if ( data &= 0x80808080U )
28 {
29#if Q_BYTE_ORDER == Q_BIG_ENDIAN
30 uint idx = qCountLeadingZeroBits( data );
31#else
32 const uint idx = qCountTrailingZeroBits( data );
33#endif
34 ptr += idx / 8;
35 return false;
36 }
37 ptr += 4;
38 }
39 while ( ptr != end )
40 {
41 if ( quint8( *ptr ) & 0x80 )
42 return false;
43 ++ptr;
44 }
45 return true;
46}
47
57QString fromEncodedComponent_helper( const QByteArray &ba )
58{
59 if ( ba.isNull() )
60 return QString();
61 // scan ba for anything above or equal to 0x80
62 // control points below 0x20 are fine in QString
63 const char *in = ba.constData();
64 const char *const end = ba.constEnd();
65 if ( qt_is_ascii( in, end ) )
66 {
67 // no non-ASCII found, we're safe to convert to QString
68 return QString::fromLatin1( ba, ba.size() );
69 }
70 // we found something that we need to encode
71 QByteArray intermediate = ba;
72 intermediate.resize( ba.size() * 3 - ( in - ba.constData() ) );
73 uchar *out = reinterpret_cast<uchar *>( intermediate.data() + ( in - ba.constData() ) );
74 for ( ; in < end; ++in )
75 {
76 if ( *in & 0x80 )
77 {
78 // encode
79 *out++ = '%';
80 *out++ = encodeNibble( uchar( *in ) >> 4 );
81 *out++ = encodeNibble( uchar( *in ) & 0xf );
82 }
83 else
84 {
85 // keep
86 *out++ = uchar( *in );
87 }
88 }
89 // now it's safe to call fromLatin1
90 return QString::fromLatin1( intermediate, out - reinterpret_cast<uchar *>( intermediate.data() ) );
91}
92
93
94
95
QString fromEncodedComponent_helper(const QByteArray &ba)
ushort encodeNibble(ushort c)