Absolute File Name: | /home/qt/qt5_coco/qt5/qtbase/src/corelib/io/qurlrecode.cpp |
Source code | Switch to Preprocessed file |
Line | Source | Count | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | /**************************************************************************** | - | ||||||||||||||||||
2 | ** | - | ||||||||||||||||||
3 | ** Copyright (C) 2012 Intel Corporation | - | ||||||||||||||||||
4 | ** Contact: http://www.qt.io/licensing/ | - | ||||||||||||||||||
5 | ** | - | ||||||||||||||||||
6 | ** This file is part of the QtCore module of the Qt Toolkit. | - | ||||||||||||||||||
7 | ** | - | ||||||||||||||||||
8 | ** $QT_BEGIN_LICENSE:LGPL21$ | - | ||||||||||||||||||
9 | ** Commercial License Usage | - | ||||||||||||||||||
10 | ** Licensees holding valid commercial Qt licenses may use this file in | - | ||||||||||||||||||
11 | ** accordance with the commercial license agreement provided with the | - | ||||||||||||||||||
12 | ** Software or, alternatively, in accordance with the terms contained in | - | ||||||||||||||||||
13 | ** a written agreement between you and The Qt Company. For licensing terms | - | ||||||||||||||||||
14 | ** and conditions see http://www.qt.io/terms-conditions. For further | - | ||||||||||||||||||
15 | ** information use the contact form at http://www.qt.io/contact-us. | - | ||||||||||||||||||
16 | ** | - | ||||||||||||||||||
17 | ** GNU Lesser General Public License Usage | - | ||||||||||||||||||
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser | - | ||||||||||||||||||
19 | ** General Public License version 2.1 or version 3 as published by the Free | - | ||||||||||||||||||
20 | ** Software Foundation and appearing in the file LICENSE.LGPLv21 and | - | ||||||||||||||||||
21 | ** LICENSE.LGPLv3 included in the packaging of this file. Please review the | - | ||||||||||||||||||
22 | ** following information to ensure the GNU Lesser General Public License | - | ||||||||||||||||||
23 | ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and | - | ||||||||||||||||||
24 | ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. | - | ||||||||||||||||||
25 | ** | - | ||||||||||||||||||
26 | ** As a special exception, The Qt Company gives you certain additional | - | ||||||||||||||||||
27 | ** rights. These rights are described in The Qt Company LGPL Exception | - | ||||||||||||||||||
28 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. | - | ||||||||||||||||||
29 | ** | - | ||||||||||||||||||
30 | ** $QT_END_LICENSE$ | - | ||||||||||||||||||
31 | ** | - | ||||||||||||||||||
32 | ****************************************************************************/ | - | ||||||||||||||||||
33 | - | |||||||||||||||||||
34 | #include "qurl.h" | - | ||||||||||||||||||
35 | #include "private/qutfcodec_p.h" | - | ||||||||||||||||||
36 | #include "private/qtools_p.h" | - | ||||||||||||||||||
37 | - | |||||||||||||||||||
38 | QT_BEGIN_NAMESPACE | - | ||||||||||||||||||
39 | - | |||||||||||||||||||
40 | // ### move to qurl_p.h | - | ||||||||||||||||||
41 | enum EncodingAction { | - | ||||||||||||||||||
42 | DecodeCharacter = 0, | - | ||||||||||||||||||
43 | LeaveCharacter = 1, | - | ||||||||||||||||||
44 | EncodeCharacter = 2 | - | ||||||||||||||||||
45 | }; | - | ||||||||||||||||||
46 | - | |||||||||||||||||||
47 | // From RFC 3896, Appendix A Collected ABNF for URI | - | ||||||||||||||||||
48 | // unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" | - | ||||||||||||||||||
49 | // reserved = gen-delims / sub-delims | - | ||||||||||||||||||
50 | // gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" | - | ||||||||||||||||||
51 | // sub-delims = "!" / "$" / "&" / "'" / "(" / ")" | - | ||||||||||||||||||
52 | // / "*" / "+" / "," / ";" / "=" | - | ||||||||||||||||||
53 | static const uchar defaultActionTable[96] = { | - | ||||||||||||||||||
54 | 2, // space | - | ||||||||||||||||||
55 | 1, // '!' (sub-delim) | - | ||||||||||||||||||
56 | 2, // '"' | - | ||||||||||||||||||
57 | 1, // '#' (gen-delim) | - | ||||||||||||||||||
58 | 1, // '$' (gen-delim) | - | ||||||||||||||||||
59 | 2, // '%' (percent) | - | ||||||||||||||||||
60 | 1, // '&' (gen-delim) | - | ||||||||||||||||||
61 | 1, // "'" (sub-delim) | - | ||||||||||||||||||
62 | 1, // '(' (sub-delim) | - | ||||||||||||||||||
63 | 1, // ')' (sub-delim) | - | ||||||||||||||||||
64 | 1, // '*' (sub-delim) | - | ||||||||||||||||||
65 | 1, // '+' (sub-delim) | - | ||||||||||||||||||
66 | 1, // ',' (sub-delim) | - | ||||||||||||||||||
67 | 0, // '-' (unreserved) | - | ||||||||||||||||||
68 | 0, // '.' (unreserved) | - | ||||||||||||||||||
69 | 1, // '/' (gen-delim) | - | ||||||||||||||||||
70 | - | |||||||||||||||||||
71 | 0, 0, 0, 0, 0, // '0' to '4' (unreserved) | - | ||||||||||||||||||
72 | 0, 0, 0, 0, 0, // '5' to '9' (unreserved) | - | ||||||||||||||||||
73 | 1, // ':' (gen-delim) | - | ||||||||||||||||||
74 | 1, // ';' (sub-delim) | - | ||||||||||||||||||
75 | 2, // '<' | - | ||||||||||||||||||
76 | 1, // '=' (sub-delim) | - | ||||||||||||||||||
77 | 2, // '>' | - | ||||||||||||||||||
78 | 1, // '?' (gen-delim) | - | ||||||||||||||||||
79 | - | |||||||||||||||||||
80 | 1, // '@' (gen-delim) | - | ||||||||||||||||||
81 | 0, 0, 0, 0, 0, // 'A' to 'E' (unreserved) | - | ||||||||||||||||||
82 | 0, 0, 0, 0, 0, // 'F' to 'J' (unreserved) | - | ||||||||||||||||||
83 | 0, 0, 0, 0, 0, // 'K' to 'O' (unreserved) | - | ||||||||||||||||||
84 | 0, 0, 0, 0, 0, // 'P' to 'T' (unreserved) | - | ||||||||||||||||||
85 | 0, 0, 0, 0, 0, 0, // 'U' to 'Z' (unreserved) | - | ||||||||||||||||||
86 | 1, // '[' (gen-delim) | - | ||||||||||||||||||
87 | 2, // '\' | - | ||||||||||||||||||
88 | 1, // ']' (gen-delim) | - | ||||||||||||||||||
89 | 2, // '^' | - | ||||||||||||||||||
90 | 0, // '_' (unreserved) | - | ||||||||||||||||||
91 | - | |||||||||||||||||||
92 | 2, // '`' | - | ||||||||||||||||||
93 | 0, 0, 0, 0, 0, // 'a' to 'e' (unreserved) | - | ||||||||||||||||||
94 | 0, 0, 0, 0, 0, // 'f' to 'j' (unreserved) | - | ||||||||||||||||||
95 | 0, 0, 0, 0, 0, // 'k' to 'o' (unreserved) | - | ||||||||||||||||||
96 | 0, 0, 0, 0, 0, // 'p' to 't' (unreserved) | - | ||||||||||||||||||
97 | 0, 0, 0, 0, 0, 0, // 'u' to 'z' (unreserved) | - | ||||||||||||||||||
98 | 2, // '{' | - | ||||||||||||||||||
99 | 2, // '|' | - | ||||||||||||||||||
100 | 2, // '}' | - | ||||||||||||||||||
101 | 0, // '~' (unreserved) | - | ||||||||||||||||||
102 | - | |||||||||||||||||||
103 | 2 // BSKP | - | ||||||||||||||||||
104 | }; | - | ||||||||||||||||||
105 | - | |||||||||||||||||||
106 | // mask tables, in negative polarity | - | ||||||||||||||||||
107 | // 0x00 if it belongs to this category | - | ||||||||||||||||||
108 | // 0xff if it doesn't | - | ||||||||||||||||||
109 | - | |||||||||||||||||||
110 | static const uchar reservedMask[96] = { | - | ||||||||||||||||||
111 | 0xff, // space | - | ||||||||||||||||||
112 | 0xff, // '!' (sub-delim) | - | ||||||||||||||||||
113 | 0x00, // '"' | - | ||||||||||||||||||
114 | 0xff, // '#' (gen-delim) | - | ||||||||||||||||||
115 | 0xff, // '$' (gen-delim) | - | ||||||||||||||||||
116 | 0xff, // '%' (percent) | - | ||||||||||||||||||
117 | 0xff, // '&' (gen-delim) | - | ||||||||||||||||||
118 | 0xff, // "'" (sub-delim) | - | ||||||||||||||||||
119 | 0xff, // '(' (sub-delim) | - | ||||||||||||||||||
120 | 0xff, // ')' (sub-delim) | - | ||||||||||||||||||
121 | 0xff, // '*' (sub-delim) | - | ||||||||||||||||||
122 | 0xff, // '+' (sub-delim) | - | ||||||||||||||||||
123 | 0xff, // ',' (sub-delim) | - | ||||||||||||||||||
124 | 0xff, // '-' (unreserved) | - | ||||||||||||||||||
125 | 0xff, // '.' (unreserved) | - | ||||||||||||||||||
126 | 0xff, // '/' (gen-delim) | - | ||||||||||||||||||
127 | - | |||||||||||||||||||
128 | 0xff, 0xff, 0xff, 0xff, 0xff, // '0' to '4' (unreserved) | - | ||||||||||||||||||
129 | 0xff, 0xff, 0xff, 0xff, 0xff, // '5' to '9' (unreserved) | - | ||||||||||||||||||
130 | 0xff, // ':' (gen-delim) | - | ||||||||||||||||||
131 | 0xff, // ';' (sub-delim) | - | ||||||||||||||||||
132 | 0x00, // '<' | - | ||||||||||||||||||
133 | 0xff, // '=' (sub-delim) | - | ||||||||||||||||||
134 | 0x00, // '>' | - | ||||||||||||||||||
135 | 0xff, // '?' (gen-delim) | - | ||||||||||||||||||
136 | - | |||||||||||||||||||
137 | 0xff, // '@' (gen-delim) | - | ||||||||||||||||||
138 | 0xff, 0xff, 0xff, 0xff, 0xff, // 'A' to 'E' (unreserved) | - | ||||||||||||||||||
139 | 0xff, 0xff, 0xff, 0xff, 0xff, // 'F' to 'J' (unreserved) | - | ||||||||||||||||||
140 | 0xff, 0xff, 0xff, 0xff, 0xff, // 'K' to 'O' (unreserved) | - | ||||||||||||||||||
141 | 0xff, 0xff, 0xff, 0xff, 0xff, // 'P' to 'T' (unreserved) | - | ||||||||||||||||||
142 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 'U' to 'Z' (unreserved) | - | ||||||||||||||||||
143 | 0xff, // '[' (gen-delim) | - | ||||||||||||||||||
144 | 0x00, // '\' | - | ||||||||||||||||||
145 | 0xff, // ']' (gen-delim) | - | ||||||||||||||||||
146 | 0x00, // '^' | - | ||||||||||||||||||
147 | 0xff, // '_' (unreserved) | - | ||||||||||||||||||
148 | - | |||||||||||||||||||
149 | 0x00, // '`' | - | ||||||||||||||||||
150 | 0xff, 0xff, 0xff, 0xff, 0xff, // 'a' to 'e' (unreserved) | - | ||||||||||||||||||
151 | 0xff, 0xff, 0xff, 0xff, 0xff, // 'f' to 'j' (unreserved) | - | ||||||||||||||||||
152 | 0xff, 0xff, 0xff, 0xff, 0xff, // 'k' to 'o' (unreserved) | - | ||||||||||||||||||
153 | 0xff, 0xff, 0xff, 0xff, 0xff, // 'p' to 't' (unreserved) | - | ||||||||||||||||||
154 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 'u' to 'z' (unreserved) | - | ||||||||||||||||||
155 | 0x00, // '{' | - | ||||||||||||||||||
156 | 0x00, // '|' | - | ||||||||||||||||||
157 | 0x00, // '}' | - | ||||||||||||||||||
158 | 0xff, // '~' (unreserved) | - | ||||||||||||||||||
159 | - | |||||||||||||||||||
160 | 0xff // BSKP | - | ||||||||||||||||||
161 | }; | - | ||||||||||||||||||
162 | - | |||||||||||||||||||
163 | static inline bool isHex(ushort c) | - | ||||||||||||||||||
164 | { | - | ||||||||||||||||||
165 | return (c >= 'a' && c <= 'f') || executed 5213 times by 10 tests: return (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') || (c >= '0' && c <= '9'); Executed by:
| 29-5213 | ||||||||||||||||||
166 | (c >= 'A' && c <= 'F') || executed 5213 times by 10 tests: return (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') || (c >= '0' && c <= '9'); Executed by:
| 29-5213 | ||||||||||||||||||
167 | (c >= '0' && c <= '9'); executed 5213 times by 10 tests: return (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') || (c >= '0' && c <= '9'); Executed by:
| 11-5213 | ||||||||||||||||||
168 | } | - | ||||||||||||||||||
169 | - | |||||||||||||||||||
170 | static inline bool isUpperHex(ushort c) | - | ||||||||||||||||||
171 | { | - | ||||||||||||||||||
172 | // undefined behaviour if c isn't an hex char! | - | ||||||||||||||||||
173 | return c < 0x60; executed 3707 times by 6 tests: return c < 0x60; Executed by:
| 3707 | ||||||||||||||||||
174 | } | - | ||||||||||||||||||
175 | - | |||||||||||||||||||
176 | static inline ushort toUpperHex(ushort c) | - | ||||||||||||||||||
177 | { | - | ||||||||||||||||||
178 | return isUpperHex(c) ? c : c - 0x20; executed 248 times by 4 tests: return isUpperHex(c) ? c : c - 0x20; Executed by:
| 51-248 | ||||||||||||||||||
179 | } | - | ||||||||||||||||||
180 | - | |||||||||||||||||||
181 | static inline ushort decodeNibble(ushort c) | - | ||||||||||||||||||
182 | { | - | ||||||||||||||||||
183 | return c >= 'a' ? c - 'a' + 0xA : executed 5146 times by 10 tests: return c >= 'a' ? c - 'a' + 0xA : c >= 'A' ? c - 'A' + 0xA : c - '0'; Executed by:
| 109-5146 | ||||||||||||||||||
184 | c >= 'A' ? c - 'A' + 0xA : c - '0'; executed 5146 times by 10 tests: return c >= 'a' ? c - 'a' + 0xA : c >= 'A' ? c - 'A' + 0xA : c - '0'; Executed by:
| 1537-5146 | ||||||||||||||||||
185 | } | - | ||||||||||||||||||
186 | - | |||||||||||||||||||
187 | // if the sequence at input is 2*HEXDIG, returns its decoding | - | ||||||||||||||||||
188 | // returns -1 if it isn't. | - | ||||||||||||||||||
189 | // assumes that the range has been checked already | - | ||||||||||||||||||
190 | static inline ushort decodePercentEncoding(const ushort *input) | - | ||||||||||||||||||
191 | { | - | ||||||||||||||||||
192 | ushort c1 = input[1]; | - | ||||||||||||||||||
193 | ushort c2 = input[2]; | - | ||||||||||||||||||
194 | if (!isHex(c1) || !isHex(c2))
| 13-2509 | ||||||||||||||||||
195 | return ushort(-1); executed 33 times by 3 tests: return ushort(-1); Executed by:
| 33 | ||||||||||||||||||
196 | return decodeNibble(c1) << 4 | decodeNibble(c2); executed 2489 times by 10 tests: return decodeNibble(c1) << 4 | decodeNibble(c2); Executed by:
| 2489 | ||||||||||||||||||
197 | } | - | ||||||||||||||||||
198 | - | |||||||||||||||||||
199 | static inline ushort encodeNibble(ushort c) | - | ||||||||||||||||||
200 | { | - | ||||||||||||||||||
201 | return ushort(QtMiscUtils::toHexUpper(c)); executed 4470 times by 9 tests: return ushort(QtMiscUtils::toHexUpper(c)); Executed by:
| 4470 | ||||||||||||||||||
202 | } | - | ||||||||||||||||||
203 | - | |||||||||||||||||||
204 | static void ensureDetached(QString &result, ushort *&output, const ushort *begin, const ushort *input, const ushort *end, | - | ||||||||||||||||||
205 | int add = 0) | - | ||||||||||||||||||
206 | { | - | ||||||||||||||||||
207 | if (!output) {
| 1322-1454 | ||||||||||||||||||
208 | // now detach | - | ||||||||||||||||||
209 | // create enough space if the rest of the string needed to be percent-encoded | - | ||||||||||||||||||
210 | int charsProcessed = input - begin; | - | ||||||||||||||||||
211 | int charsRemaining = end - input; | - | ||||||||||||||||||
212 | int spaceNeeded = end - begin + 2 * charsRemaining + add; | - | ||||||||||||||||||
213 | int origSize = result.size(); | - | ||||||||||||||||||
214 | result.resize(origSize + spaceNeeded); | - | ||||||||||||||||||
215 | - | |||||||||||||||||||
216 | // we know that resize() above detached, so we bypass the reference count check | - | ||||||||||||||||||
217 | output = const_cast<ushort *>(reinterpret_cast<const ushort *>(result.constData())) | - | ||||||||||||||||||
218 | + origSize; | - | ||||||||||||||||||
219 | - | |||||||||||||||||||
220 | // copy the chars we've already processed | - | ||||||||||||||||||
221 | int i; | - | ||||||||||||||||||
222 | for (i = 0; i < charsProcessed; ++i)
| 1454-10255 | ||||||||||||||||||
223 | output[i] = begin[i]; executed 10255 times by 9 tests: output[i] = begin[i]; Executed by:
| 10255 | ||||||||||||||||||
224 | output += i; | - | ||||||||||||||||||
225 | } executed 1454 times by 9 tests: end of block Executed by:
| 1454 | ||||||||||||||||||
226 | } executed 2776 times by 9 tests: end of block Executed by:
| 2776 | ||||||||||||||||||
227 | - | |||||||||||||||||||
228 | namespace { | - | ||||||||||||||||||
229 | struct QUrlUtf8Traits : public QUtf8BaseTraitsNoAscii | - | ||||||||||||||||||
230 | { | - | ||||||||||||||||||
231 | // override: our "bytes" are three percent-encoded UTF-16 characters | - | ||||||||||||||||||
232 | static void appendByte(ushort *&ptr, uchar b) | - | ||||||||||||||||||
233 | { | - | ||||||||||||||||||
234 | // b >= 0x80, by construction, so percent-encode | - | ||||||||||||||||||
235 | *ptr++ = '%'; | - | ||||||||||||||||||
236 | *ptr++ = encodeNibble(b >> 4); | - | ||||||||||||||||||
237 | *ptr++ = encodeNibble(b & 0xf); | - | ||||||||||||||||||
238 | } executed 228 times by 4 tests: end of block Executed by:
| 228 | ||||||||||||||||||
239 | - | |||||||||||||||||||
240 | static uchar peekByte(const ushort *ptr, int n = 0) | - | ||||||||||||||||||
241 | { | - | ||||||||||||||||||
242 | // decodePercentEncoding returns ushort(-1) if it can't decode, | - | ||||||||||||||||||
243 | // which means we return 0xff, which is not a valid continuation byte. | - | ||||||||||||||||||
244 | // If ptr[i * 3] is not '%', we'll multiply by zero and return 0, | - | ||||||||||||||||||
245 | // also not a valid continuation byte (if it's '%', we multiply by 1). | - | ||||||||||||||||||
246 | return uchar(decodePercentEncoding(ptr + n * 3)) executed 189 times by 4 tests: return uchar(decodePercentEncoding(ptr + n * 3)) * uchar(ptr[n * 3] == '%'); Executed by:
| 189 | ||||||||||||||||||
247 | * uchar(ptr[n * 3] == '%'); executed 189 times by 4 tests: return uchar(decodePercentEncoding(ptr + n * 3)) * uchar(ptr[n * 3] == '%'); Executed by:
| 189 | ||||||||||||||||||
248 | } | - | ||||||||||||||||||
249 | - | |||||||||||||||||||
250 | static qptrdiff availableBytes(const ushort *ptr, const ushort *end) | - | ||||||||||||||||||
251 | { | - | ||||||||||||||||||
252 | return (end - ptr) / 3; executed 154 times by 5 tests: return (end - ptr) / 3; Executed by:
| 154 | ||||||||||||||||||
253 | } | - | ||||||||||||||||||
254 | - | |||||||||||||||||||
255 | static void advanceByte(const ushort *&ptr, int n = 1) | - | ||||||||||||||||||
256 | { | - | ||||||||||||||||||
257 | ptr += n * 3; | - | ||||||||||||||||||
258 | } executed 96 times by 4 tests: end of block Executed by:
| 96 | ||||||||||||||||||
259 | }; | - | ||||||||||||||||||
260 | } | - | ||||||||||||||||||
261 | - | |||||||||||||||||||
262 | // returns true if we performed an UTF-8 decoding | - | ||||||||||||||||||
263 | static bool encodedUtf8ToUtf16(QString &result, ushort *&output, const ushort *begin, const ushort *&input, | - | ||||||||||||||||||
264 | const ushort *end, ushort decoded) | - | ||||||||||||||||||
265 | { | - | ||||||||||||||||||
266 | uint ucs4, *dst = &ucs4; | - | ||||||||||||||||||
267 | const ushort *src = input + 3;// skip the %XX that yielded \a decoded | - | ||||||||||||||||||
268 | int charsNeeded = QUtf8Functions::fromUtf8<QUrlUtf8Traits>(decoded, dst, src, end); | - | ||||||||||||||||||
269 | if (charsNeeded < 0)
| 96-213 | ||||||||||||||||||
270 | return false; executed 213 times by 3 tests: return false; Executed by:
| 213 | ||||||||||||||||||
271 | - | |||||||||||||||||||
272 | if (!QChar::requiresSurrogates(ucs4)) {
| 4-92 | ||||||||||||||||||
273 | // UTF-8 decoded and no surrogates are required | - | ||||||||||||||||||
274 | // detach if necessary | - | ||||||||||||||||||
275 | // possibilities are: 6 chars (%XX%XX) -> one char; 9 chars (%XX%XX%XX) -> one char | - | ||||||||||||||||||
276 | ensureDetached(result, output, begin, input, end, -3 * charsNeeded + 1); | - | ||||||||||||||||||
277 | *output++ = ucs4; | - | ||||||||||||||||||
278 | } else { executed 92 times by 4 tests: end of block Executed by:
| 92 | ||||||||||||||||||
279 | // UTF-8 decoded to something that requires a surrogate pair | - | ||||||||||||||||||
280 | // compressing from %XX%XX%XX%XX (12 chars) to two | - | ||||||||||||||||||
281 | ensureDetached(result, output, begin, input, end, -10); | - | ||||||||||||||||||
282 | *output++ = QChar::highSurrogate(ucs4); | - | ||||||||||||||||||
283 | *output++ = QChar::lowSurrogate(ucs4); | - | ||||||||||||||||||
284 | } executed 4 times by 2 tests: end of block Executed by:
| 4 | ||||||||||||||||||
285 | - | |||||||||||||||||||
286 | input = src - 1; | - | ||||||||||||||||||
287 | return true; executed 96 times by 4 tests: return true; Executed by:
| 96 | ||||||||||||||||||
288 | } | - | ||||||||||||||||||
289 | - | |||||||||||||||||||
290 | static void unicodeToEncodedUtf8(QString &result, ushort *&output, const ushort *begin, | - | ||||||||||||||||||
291 | const ushort *&input, const ushort *end, ushort decoded) | - | ||||||||||||||||||
292 | { | - | ||||||||||||||||||
293 | // calculate the utf8 length and ensure enough space is available | - | ||||||||||||||||||
294 | int utf8len = QChar::isHighSurrogate(decoded) ? 4 : decoded >= 0x800 ? 3 : 2;
| 11-87 | ||||||||||||||||||
295 | - | |||||||||||||||||||
296 | // detach | - | ||||||||||||||||||
297 | if (!output) {
| 15-83 | ||||||||||||||||||
298 | // we need 3 * utf8len for the encoded UTF-8 sequence | - | ||||||||||||||||||
299 | // but ensureDetached already adds 3 for the char we're processing | - | ||||||||||||||||||
300 | ensureDetached(result, output, begin, input, end, 3*utf8len - 3); | - | ||||||||||||||||||
301 | } else { executed 83 times by 4 tests: end of block Executed by:
| 83 | ||||||||||||||||||
302 | // verify that there's enough space or expand | - | ||||||||||||||||||
303 | int charsRemaining = end - input - 1; // not including this one | - | ||||||||||||||||||
304 | int pos = output - reinterpret_cast<const ushort *>(result.constData()); | - | ||||||||||||||||||
305 | int spaceRemaining = result.size() - pos; | - | ||||||||||||||||||
306 | if (spaceRemaining < 3*charsRemaining + 3*utf8len) {
| 5-10 | ||||||||||||||||||
307 | // must resize | - | ||||||||||||||||||
308 | result.resize(result.size() + 3*utf8len); | - | ||||||||||||||||||
309 | - | |||||||||||||||||||
310 | // we know that resize() above detached, so we bypass the reference count check | - | ||||||||||||||||||
311 | output = const_cast<ushort *>(reinterpret_cast<const ushort *>(result.constData())); | - | ||||||||||||||||||
312 | output += pos; | - | ||||||||||||||||||
313 | } executed 10 times by 2 tests: end of block Executed by:
| 10 | ||||||||||||||||||
314 | } executed 15 times by 3 tests: end of block Executed by:
| 15 | ||||||||||||||||||
315 | - | |||||||||||||||||||
316 | ++input; | - | ||||||||||||||||||
317 | int res = QUtf8Functions::toUtf8<QUrlUtf8Traits>(decoded, output, input, end); | - | ||||||||||||||||||
318 | --input; | - | ||||||||||||||||||
319 | if (res < 0) {
| 2-96 | ||||||||||||||||||
320 | // bad surrogate pair sequence | - | ||||||||||||||||||
321 | // we will encode bad UTF-16 to UTF-8 | - | ||||||||||||||||||
322 | // but they don't get decoded back | - | ||||||||||||||||||
323 | - | |||||||||||||||||||
324 | // first of three bytes | - | ||||||||||||||||||
325 | uchar c = 0xe0 | uchar(decoded >> 12); | - | ||||||||||||||||||
326 | *output++ = '%'; | - | ||||||||||||||||||
327 | *output++ = 'E'; | - | ||||||||||||||||||
328 | *output++ = encodeNibble(c & 0xf); | - | ||||||||||||||||||
329 | - | |||||||||||||||||||
330 | // second byte | - | ||||||||||||||||||
331 | c = 0x80 | (uchar(decoded >> 6) & 0x3f); | - | ||||||||||||||||||
332 | *output++ = '%'; | - | ||||||||||||||||||
333 | *output++ = encodeNibble(c >> 4); | - | ||||||||||||||||||
334 | *output++ = encodeNibble(c & 0xf); | - | ||||||||||||||||||
335 | - | |||||||||||||||||||
336 | // third byte | - | ||||||||||||||||||
337 | c = 0x80 | (decoded & 0x3f); | - | ||||||||||||||||||
338 | *output++ = '%'; | - | ||||||||||||||||||
339 | *output++ = encodeNibble(c >> 4); | - | ||||||||||||||||||
340 | *output++ = encodeNibble(c & 0xf); | - | ||||||||||||||||||
341 | } executed 2 times by 1 test: end of block Executed by:
| 2 | ||||||||||||||||||
342 | } executed 98 times by 4 tests: end of block Executed by:
| 98 | ||||||||||||||||||
343 | - | |||||||||||||||||||
344 | static int recode(QString &result, const ushort *begin, const ushort *end, QUrl::ComponentFormattingOptions encoding, | - | ||||||||||||||||||
345 | const uchar *actionTable, bool retryBadEncoding) | - | ||||||||||||||||||
346 | { | - | ||||||||||||||||||
347 | const int origSize = result.size(); | - | ||||||||||||||||||
348 | const ushort *input = begin; | - | ||||||||||||||||||
349 | ushort *output = 0; | - | ||||||||||||||||||
350 | - | |||||||||||||||||||
351 | EncodingAction action = EncodeCharacter; | - | ||||||||||||||||||
352 | for ( ; input != end; ++input) {
| 8018-37763 | ||||||||||||||||||
353 | ushort c; | - | ||||||||||||||||||
354 | // try a run where no change is necessary | - | ||||||||||||||||||
355 | for ( ; input != end; ++input) {
| 32947-782497 | ||||||||||||||||||
356 | c = *input; | - | ||||||||||||||||||
357 | if (c < 0x20U)
| 20-782477 | ||||||||||||||||||
358 | action = EncodeCharacter; executed 20 times by 3 tests: action = EncodeCharacter; Executed by:
| 20 | ||||||||||||||||||
359 | if (c < 0x20U || c >= 0x80U) // also: (c - 0x20 < 0x60U)
| 20-782477 | ||||||||||||||||||
360 | goto non_trivial; executed 371 times by 4 tests: goto non_trivial; Executed by:
| 371 | ||||||||||||||||||
361 | action = EncodingAction(actionTable[c - ' ']); | - | ||||||||||||||||||
362 | if (action == EncodeCharacter)
| 4445-777681 | ||||||||||||||||||
363 | goto non_trivial; executed 4445 times by 11 tests: goto non_trivial; Executed by:
| 4445 | ||||||||||||||||||
364 | if (output)
| 8347-769334 | ||||||||||||||||||
365 | *output++ = c; executed 8347 times by 7 tests: *output++ = c; Executed by:
| 8347 | ||||||||||||||||||
366 | } executed 777681 times by 52 tests: end of block Executed by:
| 777681 | ||||||||||||||||||
367 | break; executed 32947 times by 52 tests: break; Executed by:
| 32947 | ||||||||||||||||||
368 | - | |||||||||||||||||||
369 | non_trivial: | - | ||||||||||||||||||
370 | uint decoded; | - | ||||||||||||||||||
371 | if (c == '%' && retryBadEncoding) {
| 103-2473 | ||||||||||||||||||
372 | // always write "%25" | - | ||||||||||||||||||
373 | ensureDetached(result, output, begin, input, end); | - | ||||||||||||||||||
374 | *output++ = '%'; | - | ||||||||||||||||||
375 | *output++ = '2'; | - | ||||||||||||||||||
376 | *output++ = '5'; | - | ||||||||||||||||||
377 | continue; executed 103 times by 4 tests: continue; Executed by:
| 103 | ||||||||||||||||||
378 | } else if (c == '%') {
| 2343-2370 | ||||||||||||||||||
379 | // check if the input is valid | - | ||||||||||||||||||
380 | if (input + 2 >= end || (decoded = decodePercentEncoding(input)) == ushort(-1)) {
| 30-2333 | ||||||||||||||||||
381 | // not valid, retry | - | ||||||||||||||||||
382 | result.resize(origSize); | - | ||||||||||||||||||
383 | return recode(result, begin, end, encoding, actionTable, true); executed 67 times by 4 tests: return recode(result, begin, end, encoding, actionTable, true); Executed by:
| 67 | ||||||||||||||||||
384 | } | - | ||||||||||||||||||
385 | - | |||||||||||||||||||
386 | if (decoded >= 0x80) {
| 624-1679 | ||||||||||||||||||
387 | // decode the UTF-8 sequence | - | ||||||||||||||||||
388 | if (!(encoding & QUrl::EncodeUnicode) &&
| 309-315 | ||||||||||||||||||
389 | encodedUtf8ToUtf16(result, output, begin, input, end, decoded))
| 96-213 | ||||||||||||||||||
390 | continue; executed 96 times by 4 tests: continue; Executed by:
| 96 | ||||||||||||||||||
391 | - | |||||||||||||||||||
392 | // decoding the encoded UTF-8 failed | - | ||||||||||||||||||
393 | action = LeaveCharacter; | - | ||||||||||||||||||
394 | } else if (decoded >= 0x20) { executed 528 times by 3 tests: end of block Executed by:
| 335-1344 | ||||||||||||||||||
395 | action = EncodingAction(actionTable[decoded - ' ']); | - | ||||||||||||||||||
396 | } executed 1344 times by 9 tests: end of block Executed by:
| 1344 | ||||||||||||||||||
397 | } else { executed 2207 times by 9 tests: end of block Executed by:
| 2207 | ||||||||||||||||||
398 | decoded = c; | - | ||||||||||||||||||
399 | if (decoded >= 0x80 && encoding & QUrl::EncodeUnicode) {
| 351-1992 | ||||||||||||||||||
400 | // encode the UTF-8 sequence | - | ||||||||||||||||||
401 | unicodeToEncodedUtf8(result, output, begin, input, end, decoded); | - | ||||||||||||||||||
402 | continue; executed 98 times by 4 tests: continue; Executed by:
| 98 | ||||||||||||||||||
403 | } else if (decoded >= 0x80) {
| 253-1992 | ||||||||||||||||||
404 | if (output)
| 0-253 | ||||||||||||||||||
405 | *output++ = c; never executed: *output++ = c; | 0 | ||||||||||||||||||
406 | continue; executed 253 times by 3 tests: continue; Executed by:
| 253 | ||||||||||||||||||
407 | } | - | ||||||||||||||||||
408 | } executed 1992 times by 8 tests: end of block Executed by:
| 1992 | ||||||||||||||||||
409 | - | |||||||||||||||||||
410 | // there are six possibilities: | - | ||||||||||||||||||
411 | // current \ action | DecodeCharacter | LeaveCharacter | EncodeCharacter | - | ||||||||||||||||||
412 | // decoded | 1:leave | 2:leave | 3:encode | - | ||||||||||||||||||
413 | // encoded | 4:decode | 5:leave | 6:leave | - | ||||||||||||||||||
414 | // cases 1 and 2 were handled before this section | - | ||||||||||||||||||
415 | - | |||||||||||||||||||
416 | if (c == '%' && action != DecodeCharacter) {
| 378-2207 | ||||||||||||||||||
417 | // cases 5 and 6: it's encoded and we're leaving it as it is | - | ||||||||||||||||||
418 | // except we're pedantic and we'll uppercase the hex | - | ||||||||||||||||||
419 | if (output || !isUpperHex(input[1]) || !isUpperHex(input[2])) {
| 7-1733 | ||||||||||||||||||
420 | ensureDetached(result, output, begin, input, end); | - | ||||||||||||||||||
421 | *output++ = '%'; | - | ||||||||||||||||||
422 | *output++ = toUpperHex(*++input); | - | ||||||||||||||||||
423 | *output++ = toUpperHex(*++input); | - | ||||||||||||||||||
424 | } executed 124 times by 4 tests: end of block Executed by:
| 124 | ||||||||||||||||||
425 | } else if (c == '%' && action == DecodeCharacter) { executed 1829 times by 6 tests: end of block Executed by:
| 0-1992 | ||||||||||||||||||
426 | // case 4: we need to decode | - | ||||||||||||||||||
427 | ensureDetached(result, output, begin, input, end); | - | ||||||||||||||||||
428 | *output++ = decoded; | - | ||||||||||||||||||
429 | input += 2; | - | ||||||||||||||||||
430 | } else { executed 378 times by 7 tests: end of block Executed by:
| 378 | ||||||||||||||||||
431 | // must be case 3: we need to encode | - | ||||||||||||||||||
432 | ensureDetached(result, output, begin, input, end); | - | ||||||||||||||||||
433 | *output++ = '%'; | - | ||||||||||||||||||
434 | *output++ = encodeNibble(c >> 4); | - | ||||||||||||||||||
435 | *output++ = encodeNibble(c & 0xf); | - | ||||||||||||||||||
436 | } executed 1992 times by 8 tests: end of block Executed by:
| 1992 | ||||||||||||||||||
437 | } | - | ||||||||||||||||||
438 | - | |||||||||||||||||||
439 | if (output) {
| 1452-39513 | ||||||||||||||||||
440 | int len = output - reinterpret_cast<const ushort *>(result.constData()); | - | ||||||||||||||||||
441 | result.truncate(len); | - | ||||||||||||||||||
442 | return len - origSize; executed 1452 times by 9 tests: return len - origSize; Executed by:
| 1452 | ||||||||||||||||||
443 | } | - | ||||||||||||||||||
444 | return 0; executed 39513 times by 52 tests: return 0; Executed by:
| 39513 | ||||||||||||||||||
445 | } | - | ||||||||||||||||||
446 | - | |||||||||||||||||||
447 | /*! | - | ||||||||||||||||||
448 | \since 5.0 | - | ||||||||||||||||||
449 | \internal | - | ||||||||||||||||||
450 | - | |||||||||||||||||||
451 | This function decodes a percent-encoded string located from \a begin to \a | - | ||||||||||||||||||
452 | end, by appending each character to \a appendTo. It returns the number of | - | ||||||||||||||||||
453 | characters appended. Each percent-encoded sequence is decoded as follows: | - | ||||||||||||||||||
454 | - | |||||||||||||||||||
455 | \list | - | ||||||||||||||||||
456 | \li from %00 to %7F: the exact decoded value is appended; | - | ||||||||||||||||||
457 | \li from %80 to %FF: QChar::ReplacementCharacter is appended; | - | ||||||||||||||||||
458 | \li bad encoding: original input is copied to the output, undecoded. | - | ||||||||||||||||||
459 | \endlist | - | ||||||||||||||||||
460 | - | |||||||||||||||||||
461 | Given the above, it's important for the input to already have all UTF-8 | - | ||||||||||||||||||
462 | percent sequences decoded by qt_urlRecode (that is, the input should not | - | ||||||||||||||||||
463 | have been processed with QUrl::EncodeUnicode). | - | ||||||||||||||||||
464 | - | |||||||||||||||||||
465 | The input should also be a valid percent-encoded sequence (the output of | - | ||||||||||||||||||
466 | qt_urlRecode is always valid). | - | ||||||||||||||||||
467 | */ | - | ||||||||||||||||||
468 | static int decode(QString &appendTo, const ushort *begin, const ushort *end) | - | ||||||||||||||||||
469 | { | - | ||||||||||||||||||
470 | const int origSize = appendTo.size(); | - | ||||||||||||||||||
471 | const ushort *input = begin; | - | ||||||||||||||||||
472 | ushort *output = 0; | - | ||||||||||||||||||
473 | while (input != end) {
| 16464-623611 | ||||||||||||||||||
474 | if (*input != '%') {
| 107-623504 | ||||||||||||||||||
475 | if (output)
| 142-623362 | ||||||||||||||||||
476 | *output++ = *input; executed 142 times by 2 tests: *output++ = *input; Executed by:
| 142 | ||||||||||||||||||
477 | ++input; | - | ||||||||||||||||||
478 | continue; executed 623504 times by 22 tests: continue; Executed by:
| 623504 | ||||||||||||||||||
479 | } | - | ||||||||||||||||||
480 | - | |||||||||||||||||||
481 | if (Q_UNLIKELY(end - input < 3 || !isHex(input[1]) || !isHex(input[2]))) {
| 23-84 | ||||||||||||||||||
482 | // badly-encoded data | - | ||||||||||||||||||
483 | appendTo.resize(origSize + (end - begin)); | - | ||||||||||||||||||
484 | memcpy(appendTo.begin() + origSize, begin, (end - begin) * sizeof(ushort)); | - | ||||||||||||||||||
485 | return end - begin; executed 23 times by 2 tests: return end - begin; Executed by:
| 23 | ||||||||||||||||||
486 | } | - | ||||||||||||||||||
487 | - | |||||||||||||||||||
488 | if (Q_UNLIKELY(!output)) {
| 39-45 | ||||||||||||||||||
489 | // detach | - | ||||||||||||||||||
490 | appendTo.resize(origSize + (end - begin)); | - | ||||||||||||||||||
491 | output = reinterpret_cast<ushort *>(appendTo.begin()) + origSize; | - | ||||||||||||||||||
492 | memcpy(output, begin, (input - begin) * sizeof(ushort)); | - | ||||||||||||||||||
493 | output += input - begin; | - | ||||||||||||||||||
494 | } executed 45 times by 2 tests: end of block Executed by:
| 45 | ||||||||||||||||||
495 | - | |||||||||||||||||||
496 | ++input; | - | ||||||||||||||||||
497 | *output++ = decodeNibble(input[0]) << 4 | decodeNibble(input[1]); | - | ||||||||||||||||||
498 | if (output[-1] >= 0x80)
| 18-66 | ||||||||||||||||||
499 | output[-1] = QChar::ReplacementCharacter; executed 18 times by 1 test: output[-1] = QChar::ReplacementCharacter; Executed by:
| 18 | ||||||||||||||||||
500 | input += 2; | - | ||||||||||||||||||
501 | } executed 84 times by 2 tests: end of block Executed by:
| 84 | ||||||||||||||||||
502 | - | |||||||||||||||||||
503 | if (output) {
| 34-16430 | ||||||||||||||||||
504 | int len = output - reinterpret_cast<ushort *>(appendTo.begin()); | - | ||||||||||||||||||
505 | appendTo.truncate(len); | - | ||||||||||||||||||
506 | return len - origSize; executed 34 times by 2 tests: return len - origSize; Executed by:
| 34 | ||||||||||||||||||
507 | } | - | ||||||||||||||||||
508 | return 0; executed 16430 times by 26 tests: return 0; Executed by:
| 16430 | ||||||||||||||||||
509 | } | - | ||||||||||||||||||
510 | - | |||||||||||||||||||
511 | template <size_t N> | - | ||||||||||||||||||
512 | static void maskTable(uchar (&table)[N], const uchar (&mask)[N]) | - | ||||||||||||||||||
513 | { | - | ||||||||||||||||||
514 | for (size_t i = 0; i < N; ++i)
| 709-68064 | ||||||||||||||||||
515 | table[i] &= mask[i]; executed 68064 times by 4 tests: table[i] &= mask[i]; Executed by:
| 68064 | ||||||||||||||||||
516 | } executed 709 times by 4 tests: end of block Executed by:
| 709 | ||||||||||||||||||
517 | - | |||||||||||||||||||
518 | /*! | - | ||||||||||||||||||
519 | \internal | - | ||||||||||||||||||
520 | - | |||||||||||||||||||
521 | Recodes the string from \a begin to \a end. If any transformations are | - | ||||||||||||||||||
522 | done, append them to \a appendTo and return the number of characters added. | - | ||||||||||||||||||
523 | If no transformations were required, return 0. | - | ||||||||||||||||||
524 | - | |||||||||||||||||||
525 | The \a encoding option modifies the default behaviour: | - | ||||||||||||||||||
526 | \list | - | ||||||||||||||||||
527 | \li QUrl::DecodeReserved: if set, reserved characters will be decoded; | - | ||||||||||||||||||
528 | if unset, reserved characters will be encoded | - | ||||||||||||||||||
529 | \li QUrl::EncodeSpaces: if set, spaces will be encoded to "%20"; if unset, they will be " " | - | ||||||||||||||||||
530 | \li QUrl::EncodeUnicode: if set, characters above U+0080 will be encoded to their UTF-8 | - | ||||||||||||||||||
531 | percent-encoded form; if unset, they will be decoded to UTF-16 | - | ||||||||||||||||||
532 | \li QUrl::FullyDecoded: if set, this function will decode all percent-encoded sequences, | - | ||||||||||||||||||
533 | including that of the percent character. The resulting string | - | ||||||||||||||||||
534 | will not be percent-encoded anymore. Use with caution! | - | ||||||||||||||||||
535 | In this mode, the behaviour is undefined if the input string | - | ||||||||||||||||||
536 | contains any percent-encoding sequences above %80. | - | ||||||||||||||||||
537 | Also, the function will not correct bad % sequences. | - | ||||||||||||||||||
538 | \endlist | - | ||||||||||||||||||
539 | - | |||||||||||||||||||
540 | Other flags are ignored (including QUrl::EncodeReserved). | - | ||||||||||||||||||
541 | - | |||||||||||||||||||
542 | The \a tableModifications argument can be used to supply extra | - | ||||||||||||||||||
543 | modifications to the tables, to be applied after the flags above are | - | ||||||||||||||||||
544 | handled. It consists of a sequence of 16-bit values, where the low 8 bits | - | ||||||||||||||||||
545 | indicate the character in question and the high 8 bits are either \c | - | ||||||||||||||||||
546 | EncodeCharacter, \c LeaveCharacter or \c DecodeCharacter. | - | ||||||||||||||||||
547 | - | |||||||||||||||||||
548 | This function corrects percent-encoded errors by interpreting every '%' as | - | ||||||||||||||||||
549 | meaning "%25" (all percents in the same content). | - | ||||||||||||||||||
550 | */ | - | ||||||||||||||||||
551 | - | |||||||||||||||||||
552 | Q_AUTOTEST_EXPORT int | - | ||||||||||||||||||
553 | qt_urlRecode(QString &appendTo, const QChar *begin, const QChar *end, | - | ||||||||||||||||||
554 | QUrl::ComponentFormattingOptions encoding, const ushort *tableModifications) | - | ||||||||||||||||||
555 | { | - | ||||||||||||||||||
556 | uchar actionTable[sizeof defaultActionTable]; | - | ||||||||||||||||||
557 | if (encoding == QUrl::FullyDecoded) {
| 16487-40965 | ||||||||||||||||||
558 | return decode(appendTo, reinterpret_cast<const ushort *>(begin), reinterpret_cast<const ushort *>(end)); executed 16487 times by 26 tests: return decode(appendTo, reinterpret_cast<const ushort *>(begin), reinterpret_cast<const ushort *>(end)); Executed by:
| 16487 | ||||||||||||||||||
559 | } | - | ||||||||||||||||||
560 | - | |||||||||||||||||||
561 | memcpy(actionTable, defaultActionTable, sizeof actionTable); | - | ||||||||||||||||||
562 | if (encoding & QUrl::DecodeReserved)
| 709-40256 | ||||||||||||||||||
563 | maskTable(actionTable, reservedMask); executed 709 times by 4 tests: maskTable(actionTable, reservedMask); Executed by:
| 709 | ||||||||||||||||||
564 | if (!(encoding & QUrl::EncodeSpaces))
| 6513-34452 | ||||||||||||||||||
565 | actionTable[0] = DecodeCharacter; // decode executed 34452 times by 52 tests: actionTable[0] = DecodeCharacter; Executed by:
| 34452 | ||||||||||||||||||
566 | - | |||||||||||||||||||
567 | if (tableModifications) {
| 10784-30181 | ||||||||||||||||||
568 | for (const ushort *p = tableModifications; *p; ++p)
| 30181-234767 | ||||||||||||||||||
569 | actionTable[uchar(*p) - ' '] = *p >> 8; executed 234767 times by 38 tests: actionTable[uchar(*p) - ' '] = *p >> 8; Executed by:
| 234767 | ||||||||||||||||||
570 | } executed 30181 times by 38 tests: end of block Executed by:
| 30181 | ||||||||||||||||||
571 | - | |||||||||||||||||||
572 | return recode(appendTo, reinterpret_cast<const ushort *>(begin), reinterpret_cast<const ushort *>(end), executed 40965 times by 52 tests: return recode(appendTo, reinterpret_cast<const ushort *>(begin), reinterpret_cast<const ushort *>(end), encoding, actionTable, false); Executed by:
| 40965 | ||||||||||||||||||
573 | encoding, actionTable, false); executed 40965 times by 52 tests: return recode(appendTo, reinterpret_cast<const ushort *>(begin), reinterpret_cast<const ushort *>(end), encoding, actionTable, false); Executed by:
| 40965 | ||||||||||||||||||
574 | } | - | ||||||||||||||||||
575 | - | |||||||||||||||||||
576 | /*! | - | ||||||||||||||||||
577 | \internal | - | ||||||||||||||||||
578 | \since 5.0 | - | ||||||||||||||||||
579 | - | |||||||||||||||||||
580 | \a ba contains an 8-bit form of the component and it might be | - | ||||||||||||||||||
581 | percent-encoded already. We can't use QString::fromUtf8 because it might | - | ||||||||||||||||||
582 | contain non-UTF8 sequences. We can't use QByteArray::toPercentEncoding | - | ||||||||||||||||||
583 | because it might already contain percent-encoded sequences. We can't use | - | ||||||||||||||||||
584 | qt_urlRecode because it needs UTF-16 input. | - | ||||||||||||||||||
585 | */ | - | ||||||||||||||||||
586 | Q_AUTOTEST_EXPORT | - | ||||||||||||||||||
587 | QString qt_urlRecodeByteArray(const QByteArray &ba) | - | ||||||||||||||||||
588 | { | - | ||||||||||||||||||
589 | if (ba.isNull())
| 3-40 | ||||||||||||||||||
590 | return QString(); executed 3 times by 2 tests: return QString(); Executed by:
| 3 | ||||||||||||||||||
591 | - | |||||||||||||||||||
592 | // scan ba for anything above or equal to 0x80 | - | ||||||||||||||||||
593 | // control points below 0x20 are fine in QString | - | ||||||||||||||||||
594 | const char *in = ba.constData(); | - | ||||||||||||||||||
595 | const char *const end = ba.constEnd(); | - | ||||||||||||||||||
596 | for ( ; in < end; ++in) {
| 35-552 | ||||||||||||||||||
597 | if (*in & 0x80)
| 5-547 | ||||||||||||||||||
598 | break; executed 5 times by 2 tests: break; Executed by:
| 5 | ||||||||||||||||||
599 | } executed 547 times by 2 tests: end of block Executed by:
| 547 | ||||||||||||||||||
600 | - | |||||||||||||||||||
601 | if (in == end) {
| 5-35 | ||||||||||||||||||
602 | // no non-ASCII found, we're safe to convert to QString | - | ||||||||||||||||||
603 | return QString::fromLatin1(ba, ba.size()); executed 35 times by 2 tests: return QString::fromLatin1(ba, ba.size()); Executed by:
| 35 | ||||||||||||||||||
604 | } | - | ||||||||||||||||||
605 | - | |||||||||||||||||||
606 | // we found something that we need to encode | - | ||||||||||||||||||
607 | QByteArray intermediate = ba; | - | ||||||||||||||||||
608 | intermediate.resize(ba.size() * 3 - (in - ba.constData())); | - | ||||||||||||||||||
609 | uchar *out = reinterpret_cast<uchar *>(intermediate.data() + (in - ba.constData())); | - | ||||||||||||||||||
610 | for ( ; in < end; ++in) {
| 5-10 | ||||||||||||||||||
611 | if (*in & 0x80) {
| 0-10 | ||||||||||||||||||
612 | // encode | - | ||||||||||||||||||
613 | *out++ = '%'; | - | ||||||||||||||||||
614 | *out++ = encodeNibble(uchar(*in) >> 4); | - | ||||||||||||||||||
615 | *out++ = encodeNibble(uchar(*in) & 0xf); | - | ||||||||||||||||||
616 | } else { executed 10 times by 2 tests: end of block Executed by:
| 10 | ||||||||||||||||||
617 | // keep | - | ||||||||||||||||||
618 | *out++ = uchar(*in); | - | ||||||||||||||||||
619 | } never executed: end of block | 0 | ||||||||||||||||||
620 | } | - | ||||||||||||||||||
621 | - | |||||||||||||||||||
622 | // now it's safe to call fromLatin1 | - | ||||||||||||||||||
623 | return QString::fromLatin1(intermediate, out - reinterpret_cast<uchar *>(intermediate.data())); executed 5 times by 2 tests: return QString::fromLatin1(intermediate, out - reinterpret_cast<uchar *>(intermediate.data())); Executed by:
| 5 | ||||||||||||||||||
624 | } | - | ||||||||||||||||||
625 | - | |||||||||||||||||||
626 | QT_END_NAMESPACE | - | ||||||||||||||||||
Source code | Switch to Preprocessed file |