QGIS API Documentation  3.25.0-Master (dec16ba68b)
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
6  email : [email protected]
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 
22 static 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 
57 QString 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)