1 | // Copyright (C) 2022 The Qt Company Ltd. |
---|---|
2 | // Copyright (C) 2016 Intel Corporation. |
3 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
4 | |
5 | #ifndef QBYTEARRAY_H |
6 | #define QBYTEARRAY_H |
7 | |
8 | #include <QtCore/qrefcount.h> |
9 | #include <QtCore/qnamespace.h> |
10 | #include <QtCore/qarraydata.h> |
11 | #include <QtCore/qarraydatapointer.h> |
12 | #include <QtCore/qcompare.h> |
13 | #include <QtCore/qcontainerfwd.h> |
14 | #include <QtCore/qbytearrayalgorithms.h> |
15 | #include <QtCore/qbytearrayview.h> |
16 | |
17 | #include <stdlib.h> |
18 | #include <string.h> |
19 | |
20 | #include <string> |
21 | #include <iterator> |
22 | |
23 | #ifndef QT5_NULL_STRINGS |
24 | // Would ideally be off, but in practice breaks too much (Qt 6.0). |
25 | #define QT5_NULL_STRINGS 1 |
26 | #endif |
27 | |
28 | #ifdef truncate |
29 | #error qbytearray.h must be included before any header file that defines truncate |
30 | #endif |
31 | |
32 | #if defined(Q_OS_DARWIN) || defined(Q_QDOC) |
33 | Q_FORWARD_DECLARE_CF_TYPE(CFData); |
34 | Q_FORWARD_DECLARE_OBJC_CLASS(NSData); |
35 | #endif |
36 | |
37 | #if defined(Q_OS_WASM) || defined(Q_QDOC) |
38 | namespace emscripten { |
39 | class val; |
40 | } |
41 | #endif |
42 | |
43 | class tst_QByteArray; |
44 | |
45 | QT_BEGIN_NAMESPACE |
46 | |
47 | class QString; |
48 | class QDataStream; |
49 | |
50 | using QByteArrayData = QArrayDataPointer<char>; |
51 | |
52 | # define QByteArrayLiteral(str) \ |
53 | (QByteArray(QByteArrayData(nullptr, const_cast<char *>(str), sizeof(str) - 1))) \ |
54 | /**/ |
55 | |
56 | class Q_CORE_EXPORT QByteArray |
57 | { |
58 | public: |
59 | using DataPointer = QByteArrayData; |
60 | private: |
61 | typedef QTypedArrayData<char> Data; |
62 | |
63 | DataPointer d; |
64 | static const char _empty; |
65 | |
66 | friend class ::tst_QByteArray; |
67 | |
68 | template <typename InputIterator> |
69 | using if_input_iterator = QtPrivate::IfIsInputIterator<InputIterator>; |
70 | public: |
71 | enum Base64Option { |
72 | Base64Encoding = 0, |
73 | Base64UrlEncoding = 1, |
74 | |
75 | KeepTrailingEquals = 0, |
76 | OmitTrailingEquals = 2, |
77 | |
78 | IgnoreBase64DecodingErrors = 0, |
79 | AbortOnBase64DecodingErrors = 4, |
80 | }; |
81 | Q_DECLARE_FLAGS(Base64Options, Base64Option) |
82 | |
83 | enum class Base64DecodingStatus { |
84 | Ok, |
85 | IllegalInputLength, |
86 | IllegalCharacter, |
87 | IllegalPadding, |
88 | }; |
89 | |
90 | inline constexpr QByteArray() noexcept; |
91 | QByteArray(const char *, qsizetype size = -1); |
92 | QByteArray(qsizetype size, char c); |
93 | QByteArray(qsizetype size, Qt::Initialization); |
94 | explicit QByteArray(QByteArrayView v) : QByteArray(v.data(), v.size()) {} |
95 | inline QByteArray(const QByteArray &) noexcept; |
96 | inline ~QByteArray(); |
97 | |
98 | QByteArray &operator=(const QByteArray &) noexcept; |
99 | QByteArray &operator=(const char *str); |
100 | inline QByteArray(QByteArray && other) noexcept |
101 | = default; |
102 | QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QByteArray) |
103 | inline void swap(QByteArray &other) noexcept |
104 | { d.swap(other&: other.d); } |
105 | |
106 | bool isEmpty() const noexcept { return size() == 0; } |
107 | void resize(qsizetype size); |
108 | void resize(qsizetype size, char c); |
109 | void resizeForOverwrite(qsizetype size); |
110 | |
111 | QByteArray &fill(char c, qsizetype size = -1); |
112 | |
113 | inline qsizetype capacity() const; |
114 | inline void reserve(qsizetype size); |
115 | inline void squeeze(); |
116 | |
117 | #ifndef QT_NO_CAST_FROM_BYTEARRAY |
118 | inline operator const char *() const; |
119 | inline operator const void *() const; |
120 | #endif |
121 | inline char *data(); |
122 | inline const char *data() const noexcept; |
123 | const char *constData() const noexcept { return data(); } |
124 | inline void detach(); |
125 | inline bool isDetached() const; |
126 | inline bool isSharedWith(const QByteArray &other) const noexcept |
127 | { return data() == other.data() && size() == other.size(); } |
128 | void clear(); |
129 | |
130 | inline char at(qsizetype i) const; |
131 | inline char operator[](qsizetype i) const; |
132 | [[nodiscard]] inline char &operator[](qsizetype i); |
133 | [[nodiscard]] char front() const { return at(i: 0); } |
134 | [[nodiscard]] inline char &front(); |
135 | [[nodiscard]] char back() const { return at(i: size() - 1); } |
136 | [[nodiscard]] inline char &back(); |
137 | |
138 | QT_CORE_INLINE_SINCE(6, 8) |
139 | qsizetype indexOf(char c, qsizetype from = 0) const; |
140 | qsizetype indexOf(QByteArrayView bv, qsizetype from = 0) const |
141 | { return QtPrivate::findByteArray(haystack: qToByteArrayViewIgnoringNull(b: *this), from, needle: bv); } |
142 | |
143 | QT_CORE_INLINE_SINCE(6, 8) |
144 | qsizetype lastIndexOf(char c, qsizetype from = -1) const; |
145 | qsizetype lastIndexOf(QByteArrayView bv) const |
146 | { return lastIndexOf(bv, from: size()); } |
147 | qsizetype lastIndexOf(QByteArrayView bv, qsizetype from) const |
148 | { return QtPrivate::lastIndexOf(haystack: qToByteArrayViewIgnoringNull(b: *this), from, needle: bv); } |
149 | |
150 | inline bool contains(char c) const; |
151 | inline bool contains(QByteArrayView bv) const; |
152 | qsizetype count(char c) const; |
153 | qsizetype count(QByteArrayView bv) const |
154 | { return QtPrivate::count(haystack: qToByteArrayViewIgnoringNull(b: *this), needle: bv); } |
155 | |
156 | inline int compare(QByteArrayView a, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept; |
157 | |
158 | #if QT_CORE_REMOVED_SINCE(6, 7) |
159 | QByteArray left(qsizetype len) const; |
160 | QByteArray right(qsizetype len) const; |
161 | QByteArray mid(qsizetype index, qsizetype len = -1) const; |
162 | QByteArray first(qsizetype n) const; |
163 | QByteArray last(qsizetype n) const; |
164 | QByteArray sliced(qsizetype pos) const; |
165 | QByteArray sliced(qsizetype pos, qsizetype n) const; |
166 | QByteArray chopped(qsizetype len) const; |
167 | #else |
168 | [[nodiscard]] QByteArray left(qsizetype n) const & |
169 | { |
170 | if (n >= size()) |
171 | return *this; |
172 | return first(n: qMax(a: n, b: 0)); |
173 | } |
174 | [[nodiscard]] QByteArray left(qsizetype n) && |
175 | { |
176 | if (n >= size()) |
177 | return std::move(*this); |
178 | return std::move(*this).first(n: qMax(a: n, b: 0)); |
179 | } |
180 | [[nodiscard]] QByteArray right(qsizetype n) const & |
181 | { |
182 | if (n >= size()) |
183 | return *this; |
184 | return last(n: qMax(a: n, b: 0)); |
185 | } |
186 | [[nodiscard]] QByteArray right(qsizetype n) && |
187 | { |
188 | if (n >= size()) |
189 | return std::move(*this); |
190 | return std::move(*this).last(n: qMax(a: n, b: 0)); |
191 | } |
192 | [[nodiscard]] QByteArray mid(qsizetype index, qsizetype len = -1) const &; |
193 | [[nodiscard]] QByteArray mid(qsizetype index, qsizetype len = -1) &&; |
194 | |
195 | [[nodiscard]] QByteArray first(qsizetype n) const & |
196 | { verify(pos: 0, n); return sliced(pos: 0, n); } |
197 | [[nodiscard]] QByteArray last(qsizetype n) const & |
198 | { verify(pos: 0, n); return sliced(pos: size() - n, n); } |
199 | [[nodiscard]] QByteArray sliced(qsizetype pos) const & |
200 | { verify(pos, n: 0); return sliced(pos, n: size() - pos); } |
201 | [[nodiscard]] QByteArray sliced(qsizetype pos, qsizetype n) const & |
202 | { verify(pos, n); return QByteArray(d.data() + pos, n); } |
203 | [[nodiscard]] QByteArray chopped(qsizetype len) const & |
204 | { verify(pos: 0, n: len); return sliced(pos: 0, n: size() - len); } |
205 | |
206 | [[nodiscard]] QByteArray first(qsizetype n) && |
207 | { |
208 | verify(pos: 0, n); |
209 | resize(size: n); // may detach and allocate memory |
210 | return std::move(*this); |
211 | } |
212 | [[nodiscard]] QByteArray last(qsizetype n) && |
213 | { verify(pos: 0, n); return sliced_helper(a&: *this, pos: size() - n, n); } |
214 | [[nodiscard]] QByteArray sliced(qsizetype pos) && |
215 | { verify(pos, n: 0); return sliced_helper(a&: *this, pos, n: size() - pos); } |
216 | [[nodiscard]] QByteArray sliced(qsizetype pos, qsizetype n) && |
217 | { verify(pos, n); return sliced_helper(a&: *this, pos, n); } |
218 | [[nodiscard]] QByteArray chopped(qsizetype len) && |
219 | { verify(pos: 0, n: len); return std::move(*this).first(n: size() - len); } |
220 | #endif |
221 | |
222 | bool startsWith(QByteArrayView bv) const |
223 | { return QtPrivate::startsWith(haystack: qToByteArrayViewIgnoringNull(b: *this), needle: bv); } |
224 | bool startsWith(char c) const { return size() > 0 && front() == c; } |
225 | |
226 | bool endsWith(char c) const { return size() > 0 && back() == c; } |
227 | bool endsWith(QByteArrayView bv) const |
228 | { return QtPrivate::endsWith(haystack: qToByteArrayViewIgnoringNull(b: *this), needle: bv); } |
229 | |
230 | bool isUpper() const; |
231 | bool isLower() const; |
232 | |
233 | [[nodiscard]] bool isValidUtf8() const noexcept |
234 | { |
235 | return QtPrivate::isValidUtf8(s: qToByteArrayViewIgnoringNull(b: *this)); |
236 | } |
237 | |
238 | void truncate(qsizetype pos); |
239 | void chop(qsizetype n); |
240 | |
241 | QByteArray &slice(qsizetype pos) |
242 | { verify(pos, n: 0); return remove(index: 0, len: pos); } |
243 | QByteArray &slice(qsizetype pos, qsizetype n) |
244 | { |
245 | verify(pos, n); |
246 | if (isNull()) |
247 | return *this; |
248 | resize(size: pos + n); |
249 | return remove(index: 0, len: pos); |
250 | } |
251 | |
252 | #if !defined(Q_QDOC) |
253 | [[nodiscard]] QByteArray toLower() const & |
254 | { return toLower_helper(a: *this); } |
255 | [[nodiscard]] QByteArray toLower() && |
256 | { return toLower_helper(a&: *this); } |
257 | [[nodiscard]] QByteArray toUpper() const & |
258 | { return toUpper_helper(a: *this); } |
259 | [[nodiscard]] QByteArray toUpper() && |
260 | { return toUpper_helper(a&: *this); } |
261 | [[nodiscard]] QByteArray trimmed() const & |
262 | { return trimmed_helper(a: *this); } |
263 | [[nodiscard]] QByteArray trimmed() && |
264 | { return trimmed_helper(a&: *this); } |
265 | [[nodiscard]] QByteArray simplified() const & |
266 | { return simplified_helper(a: *this); } |
267 | [[nodiscard]] QByteArray simplified() && |
268 | { return simplified_helper(a&: *this); } |
269 | #else |
270 | [[nodiscard]] QByteArray toLower() const; |
271 | [[nodiscard]] QByteArray toUpper() const; |
272 | [[nodiscard]] QByteArray trimmed() const; |
273 | [[nodiscard]] QByteArray simplified() const; |
274 | #endif |
275 | |
276 | [[nodiscard]] QByteArray leftJustified(qsizetype width, char fill = ' ', bool truncate = false) const; |
277 | [[nodiscard]] QByteArray rightJustified(qsizetype width, char fill = ' ', bool truncate = false) const; |
278 | |
279 | QByteArray &prepend(char c) |
280 | { return insert(i: 0, data: QByteArrayView(&c, 1)); } |
281 | inline QByteArray &prepend(qsizetype count, char c); |
282 | QByteArray &prepend(const char *s) |
283 | { return insert(i: 0, data: QByteArrayView(s, qsizetype(qstrlen(str: s)))); } |
284 | QByteArray &prepend(const char *s, qsizetype len) |
285 | { return insert(i: 0, data: QByteArrayView(s, len)); } |
286 | QByteArray &prepend(const QByteArray &a); |
287 | QByteArray &prepend(QByteArrayView a) |
288 | { return insert(i: 0, data: a); } |
289 | |
290 | QByteArray &append(char c); |
291 | inline QByteArray &append(qsizetype count, char c); |
292 | QByteArray &append(const char *s) |
293 | { return append(s, len: -1); } |
294 | QByteArray &append(const char *s, qsizetype len) |
295 | { return append(a: QByteArrayView(s, len < 0 ? qsizetype(qstrlen(str: s)) : len)); } |
296 | QByteArray &append(const QByteArray &a); |
297 | QByteArray &append(QByteArrayView a) |
298 | { return insert(i: size(), data: a); } |
299 | |
300 | QByteArray &assign(QByteArrayView v); |
301 | QByteArray &assign(qsizetype n, char c) |
302 | { |
303 | Q_ASSERT(n >= 0); |
304 | return fill(c, size: n); |
305 | } |
306 | template <typename InputIterator, if_input_iterator<InputIterator> = true> |
307 | QByteArray &assign(InputIterator first, InputIterator last) |
308 | { |
309 | d.assign(first, last); |
310 | if (d.data()) |
311 | d.data()[d.size] = '\0'; |
312 | return *this; |
313 | } |
314 | |
315 | QByteArray &insert(qsizetype i, QByteArrayView data); |
316 | inline QByteArray &insert(qsizetype i, const char *s) |
317 | { return insert(i, data: QByteArrayView(s)); } |
318 | inline QByteArray &insert(qsizetype i, const QByteArray &data) |
319 | { return insert(i, data: QByteArrayView(data)); } |
320 | QByteArray &insert(qsizetype i, qsizetype count, char c); |
321 | QByteArray &insert(qsizetype i, char c) |
322 | { return insert(i, data: QByteArrayView(&c, 1)); } |
323 | QByteArray &insert(qsizetype i, const char *s, qsizetype len) |
324 | { return insert(i, data: QByteArrayView(s, len)); } |
325 | |
326 | QByteArray &remove(qsizetype index, qsizetype len); |
327 | QByteArray &removeAt(qsizetype pos) |
328 | { return size_t(pos) < size_t(size()) ? remove(index: pos, len: 1) : *this; } |
329 | QByteArray &removeFirst() { return !isEmpty() ? remove(index: 0, len: 1) : *this; } |
330 | QByteArray &removeLast() { return !isEmpty() ? remove(index: size() - 1, len: 1) : *this; } |
331 | |
332 | template <typename Predicate> |
333 | QByteArray &removeIf(Predicate pred) |
334 | { |
335 | removeIf_helper(pred); |
336 | return *this; |
337 | } |
338 | |
339 | QByteArray &replace(qsizetype index, qsizetype len, const char *s, qsizetype alen) |
340 | { return replace(index, len, s: QByteArrayView(s, alen)); } |
341 | QByteArray &replace(qsizetype index, qsizetype len, QByteArrayView s); |
342 | QByteArray &replace(char before, QByteArrayView after) |
343 | { return replace(before: QByteArrayView(&before, 1), after); } |
344 | QByteArray &replace(const char *before, qsizetype bsize, const char *after, qsizetype asize) |
345 | { return replace(before: QByteArrayView(before, bsize), after: QByteArrayView(after, asize)); } |
346 | QByteArray &replace(QByteArrayView before, QByteArrayView after); |
347 | QByteArray &replace(char before, char after); |
348 | |
349 | QByteArray &operator+=(char c) |
350 | { return append(c); } |
351 | QByteArray &operator+=(const char *s) |
352 | { return append(s); } |
353 | QByteArray &operator+=(const QByteArray &a) |
354 | { return append(a); } |
355 | QByteArray &operator+=(QByteArrayView a) |
356 | { return append(a); } |
357 | |
358 | QList<QByteArray> split(char sep) const; |
359 | |
360 | [[nodiscard]] QByteArray repeated(qsizetype times) const; |
361 | |
362 | #if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII) |
363 | #if QT_CORE_REMOVED_SINCE(6, 8) |
364 | QT_ASCII_CAST_WARN inline bool operator==(const QString &s2) const; |
365 | QT_ASCII_CAST_WARN inline bool operator!=(const QString &s2) const; |
366 | QT_ASCII_CAST_WARN inline bool operator<(const QString &s2) const; |
367 | QT_ASCII_CAST_WARN inline bool operator>(const QString &s2) const; |
368 | QT_ASCII_CAST_WARN inline bool operator<=(const QString &s2) const; |
369 | QT_ASCII_CAST_WARN inline bool operator>=(const QString &s2) const; |
370 | #endif // QT_CORE_REMOVED_SINCE(6, 8) |
371 | #endif // !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII) |
372 | |
373 | short toShort(bool *ok = nullptr, int base = 10) const; |
374 | ushort toUShort(bool *ok = nullptr, int base = 10) const; |
375 | int toInt(bool *ok = nullptr, int base = 10) const; |
376 | uint toUInt(bool *ok = nullptr, int base = 10) const; |
377 | long toLong(bool *ok = nullptr, int base = 10) const; |
378 | ulong toULong(bool *ok = nullptr, int base = 10) const; |
379 | qlonglong toLongLong(bool *ok = nullptr, int base = 10) const; |
380 | qulonglong toULongLong(bool *ok = nullptr, int base = 10) const; |
381 | float toFloat(bool *ok = nullptr) const; |
382 | double toDouble(bool *ok = nullptr) const; |
383 | QByteArray toBase64(Base64Options options = Base64Encoding) const; |
384 | QByteArray toHex(char separator = '\0') const; |
385 | QByteArray toPercentEncoding(const QByteArray &exclude = QByteArray(), |
386 | const QByteArray &include = QByteArray(), |
387 | char percent = '%') const; |
388 | [[nodiscard]] QByteArray percentDecoded(char percent = '%') const; |
389 | |
390 | inline QByteArray &setNum(short, int base = 10); |
391 | inline QByteArray &setNum(ushort, int base = 10); |
392 | inline QByteArray &setNum(int, int base = 10); |
393 | inline QByteArray &setNum(uint, int base = 10); |
394 | inline QByteArray &setNum(long, int base = 10); |
395 | inline QByteArray &setNum(ulong, int base = 10); |
396 | QByteArray &setNum(qlonglong, int base = 10); |
397 | QByteArray &setNum(qulonglong, int base = 10); |
398 | inline QByteArray &setNum(float, char format = 'g', int precision = 6); |
399 | QByteArray &setNum(double, char format = 'g', int precision = 6); |
400 | QByteArray &setRawData(const char *a, qsizetype n); |
401 | |
402 | [[nodiscard]] static QByteArray number(int, int base = 10); |
403 | [[nodiscard]] static QByteArray number(uint, int base = 10); |
404 | [[nodiscard]] static QByteArray number(long, int base = 10); |
405 | [[nodiscard]] static QByteArray number(ulong, int base = 10); |
406 | [[nodiscard]] static QByteArray number(qlonglong, int base = 10); |
407 | [[nodiscard]] static QByteArray number(qulonglong, int base = 10); |
408 | [[nodiscard]] static QByteArray number(double, char format = 'g', int precision = 6); |
409 | [[nodiscard]] static QByteArray fromRawData(const char *data, qsizetype size) |
410 | { |
411 | return QByteArray(DataPointer(nullptr, const_cast<char *>(data), size)); |
412 | } |
413 | |
414 | class FromBase64Result; |
415 | [[nodiscard]] static FromBase64Result fromBase64Encoding(QByteArray &&base64, Base64Options options = Base64Encoding); |
416 | [[nodiscard]] static FromBase64Result fromBase64Encoding(const QByteArray &base64, Base64Options options = Base64Encoding); |
417 | [[nodiscard]] static QByteArray fromBase64(const QByteArray &base64, Base64Options options = Base64Encoding); |
418 | [[nodiscard]] static QByteArray fromHex(const QByteArray &hexEncoded); |
419 | [[nodiscard]] static QByteArray fromPercentEncoding(const QByteArray &pctEncoded, char percent = '%'); |
420 | |
421 | #if defined(Q_OS_DARWIN) || defined(Q_QDOC) |
422 | static QByteArray fromCFData(CFDataRef data); |
423 | static QByteArray fromRawCFData(CFDataRef data); |
424 | CFDataRef toCFData() const Q_DECL_CF_RETURNS_RETAINED; |
425 | CFDataRef toRawCFData() const Q_DECL_CF_RETURNS_RETAINED; |
426 | static QByteArray fromNSData(const NSData *data); |
427 | static QByteArray fromRawNSData(const NSData *data); |
428 | NSData *toNSData() const Q_DECL_NS_RETURNS_AUTORELEASED; |
429 | NSData *toRawNSData() const Q_DECL_NS_RETURNS_AUTORELEASED; |
430 | #endif |
431 | |
432 | #if defined(Q_OS_WASM) || defined(Q_QDOC) |
433 | static QByteArray fromEcmaUint8Array(emscripten::val uint8array); |
434 | emscripten::val toEcmaUint8Array(); |
435 | #endif |
436 | |
437 | typedef char *iterator; |
438 | typedef const char *const_iterator; |
439 | typedef iterator Iterator; |
440 | typedef const_iterator ConstIterator; |
441 | typedef std::reverse_iterator<iterator> reverse_iterator; |
442 | typedef std::reverse_iterator<const_iterator> const_reverse_iterator; |
443 | iterator begin() { return data(); } |
444 | const_iterator begin() const noexcept { return d.data(); } |
445 | const_iterator cbegin() const noexcept { return begin(); } |
446 | const_iterator constBegin() const noexcept { return begin(); } |
447 | iterator end() { return begin() + size(); } |
448 | const_iterator end() const noexcept { return begin() + size(); } |
449 | const_iterator cend() const noexcept { return end(); } |
450 | const_iterator constEnd() const noexcept { return end(); } |
451 | reverse_iterator rbegin() { return reverse_iterator(end()); } |
452 | reverse_iterator rend() { return reverse_iterator(begin()); } |
453 | const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); } |
454 | const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); } |
455 | const_reverse_iterator crbegin() const noexcept { return rbegin(); } |
456 | const_reverse_iterator crend() const noexcept { return rend(); } |
457 | |
458 | // stl compatibility |
459 | typedef qsizetype size_type; |
460 | typedef qptrdiff difference_type; |
461 | typedef const char & const_reference; |
462 | typedef char & reference; |
463 | typedef char *pointer; |
464 | typedef const char *const_pointer; |
465 | typedef char value_type; |
466 | void push_back(char c) |
467 | { append(c); } |
468 | void push_back(const char *s) |
469 | { append(s); } |
470 | void push_back(const QByteArray &a) |
471 | { append(a); } |
472 | void push_back(QByteArrayView a) |
473 | { append(a); } |
474 | void push_front(char c) |
475 | { prepend(c); } |
476 | void push_front(const char *c) |
477 | { prepend(s: c); } |
478 | void push_front(const QByteArray &a) |
479 | { prepend(a); } |
480 | void push_front(QByteArrayView a) |
481 | { prepend(a); } |
482 | void shrink_to_fit() { squeeze(); } |
483 | iterator erase(const_iterator first, const_iterator last); |
484 | inline iterator erase(const_iterator it) { return erase(first: it, last: it + 1); } |
485 | constexpr qsizetype max_size() const noexcept |
486 | { |
487 | return maxSize(); |
488 | } |
489 | |
490 | static QByteArray fromStdString(const std::string &s); |
491 | std::string toStdString() const; |
492 | |
493 | static constexpr qsizetype maxSize() noexcept |
494 | { |
495 | // -1 to deal with the NUL terminator |
496 | return Data::maxSize() - 1; |
497 | } |
498 | inline qsizetype size() const noexcept { return d.size; } |
499 | #if QT_DEPRECATED_SINCE(6, 4) |
500 | QT_DEPRECATED_VERSION_X_6_4("Use size() or length() instead.") |
501 | inline qsizetype count() const noexcept { return size(); } |
502 | #endif |
503 | inline qsizetype length() const noexcept { return size(); } |
504 | QT_CORE_INLINE_SINCE(6, 4) |
505 | bool isNull() const noexcept; |
506 | |
507 | inline const DataPointer &data_ptr() const { return d; } |
508 | inline DataPointer &data_ptr() { return d; } |
509 | #if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) |
510 | explicit inline QByteArray(const DataPointer &dd) : d(dd) {} |
511 | #endif |
512 | explicit inline QByteArray(DataPointer &&dd) : d(std::move(dd)) {} |
513 | |
514 | private: |
515 | friend bool comparesEqual(const QByteArray &lhs, const QByteArrayView &rhs) noexcept |
516 | { return QByteArrayView(lhs) == rhs; } |
517 | friend Qt::strong_ordering |
518 | compareThreeWay(const QByteArray &lhs, const QByteArrayView &rhs) noexcept |
519 | { |
520 | const int res = QtPrivate::compareMemory(lhs: QByteArrayView(lhs), rhs); |
521 | return Qt::compareThreeWay(lhs: res, rhs: 0); |
522 | } |
523 | Q_DECLARE_STRONGLY_ORDERED(QByteArray) |
524 | Q_DECLARE_STRONGLY_ORDERED(QByteArray, QByteArrayView) |
525 | Q_DECLARE_STRONGLY_ORDERED(QByteArray, const char *) |
526 | #if defined(__GLIBCXX__) && defined(__cpp_lib_three_way_comparison) |
527 | // libstdc++ has a bug [0] when `operator const void *()` is preferred over |
528 | // `operator<=>()` when calling std::less<> and other similar methods. |
529 | // Fix it by explicitly providing relational operators in such case. |
530 | // [0]: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114153 |
531 | friend bool operator<(const QByteArray &lhs, const QByteArray &rhs) noexcept |
532 | { return is_lt(compareThreeWay(lhs, rhs)); } |
533 | friend bool operator<=(const QByteArray &lhs, const QByteArray &rhs) noexcept |
534 | { return is_lteq(compareThreeWay(lhs, rhs)); } |
535 | friend bool operator>(const QByteArray &lhs, const QByteArray &rhs) noexcept |
536 | { return is_gt(compareThreeWay(lhs, rhs)); } |
537 | friend bool operator>=(const QByteArray &lhs, const QByteArray &rhs) noexcept |
538 | { return is_gteq(compareThreeWay(lhs, rhs)); } |
539 | #endif // defined(__GLIBCXX__) && defined(__cpp_lib_three_way_comparison) |
540 | |
541 | // Check isEmpty() instead of isNull() for backwards compatibility. |
542 | friend bool comparesEqual(const QByteArray &lhs, std::nullptr_t) noexcept |
543 | { return lhs.isEmpty(); } |
544 | friend Qt::strong_ordering compareThreeWay(const QByteArray &lhs, std::nullptr_t) noexcept |
545 | { return lhs.isEmpty() ? Qt::strong_ordering::equivalent : Qt::strong_ordering::greater; } |
546 | Q_DECLARE_STRONGLY_ORDERED(QByteArray, std::nullptr_t) |
547 | |
548 | // defined in qstring.cpp |
549 | friend Q_CORE_EXPORT bool comparesEqual(const QByteArray &lhs, const QChar &rhs) noexcept; |
550 | friend Q_CORE_EXPORT Qt::strong_ordering |
551 | compareThreeWay(const QByteArray &lhs, const QChar &rhs) noexcept; |
552 | friend Q_CORE_EXPORT bool comparesEqual(const QByteArray &lhs, char16_t rhs) noexcept; |
553 | friend Q_CORE_EXPORT Qt::strong_ordering |
554 | compareThreeWay(const QByteArray &lhs, char16_t rhs) noexcept; |
555 | #if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII) |
556 | Q_DECLARE_STRONGLY_ORDERED(QByteArray, QChar, QT_ASCII_CAST_WARN) |
557 | Q_DECLARE_STRONGLY_ORDERED(QByteArray, char16_t, QT_ASCII_CAST_WARN) |
558 | #endif // !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII) |
559 | |
560 | |
561 | void reallocData(qsizetype alloc, QArrayData::AllocationOption option); |
562 | void reallocGrowData(qsizetype n); |
563 | void expand(qsizetype i); |
564 | |
565 | Q_ALWAYS_INLINE constexpr void verify([[maybe_unused]] qsizetype pos = 0, |
566 | [[maybe_unused]] qsizetype n = 1) const |
567 | { |
568 | Q_ASSERT(pos >= 0); |
569 | Q_ASSERT(pos <= d.size); |
570 | Q_ASSERT(n >= 0); |
571 | Q_ASSERT(n <= d.size - pos); |
572 | } |
573 | |
574 | static QByteArray sliced_helper(QByteArray &a, qsizetype pos, qsizetype n); |
575 | static QByteArray toLower_helper(const QByteArray &a); |
576 | static QByteArray toLower_helper(QByteArray &a); |
577 | static QByteArray toUpper_helper(const QByteArray &a); |
578 | static QByteArray toUpper_helper(QByteArray &a); |
579 | static QByteArray trimmed_helper(const QByteArray &a); |
580 | static QByteArray trimmed_helper(QByteArray &a); |
581 | static QByteArray simplified_helper(const QByteArray &a); |
582 | static QByteArray simplified_helper(QByteArray &a); |
583 | template <typename Predicate> |
584 | qsizetype removeIf_helper(Predicate pred) |
585 | { |
586 | const qsizetype result = d->eraseIf(pred); |
587 | if (result > 0) |
588 | d.data()[d.size] = '\0'; |
589 | return result; |
590 | } |
591 | |
592 | friend class QString; |
593 | friend Q_CORE_EXPORT QByteArray qUncompress(const uchar *data, qsizetype nbytes); |
594 | |
595 | template <typename T> friend qsizetype erase(QByteArray &ba, const T &t); |
596 | template <typename Predicate> friend qsizetype erase_if(QByteArray &ba, Predicate pred); |
597 | }; |
598 | |
599 | Q_DECLARE_OPERATORS_FOR_FLAGS(QByteArray::Base64Options) |
600 | |
601 | inline constexpr QByteArray::QByteArray() noexcept {} |
602 | inline QByteArray::~QByteArray() {} |
603 | |
604 | inline char QByteArray::at(qsizetype i) const |
605 | { verify(pos: i, n: 1); return d.data()[i]; } |
606 | inline char QByteArray::operator[](qsizetype i) const |
607 | { verify(pos: i, n: 1); return d.data()[i]; } |
608 | |
609 | #ifndef QT_NO_CAST_FROM_BYTEARRAY |
610 | inline QByteArray::operator const char *() const |
611 | { return data(); } |
612 | inline QByteArray::operator const void *() const |
613 | { return data(); } |
614 | #endif |
615 | inline char *QByteArray::data() |
616 | { |
617 | detach(); |
618 | Q_ASSERT(d.data()); |
619 | return d.data(); |
620 | } |
621 | inline const char *QByteArray::data() const noexcept |
622 | { |
623 | #if QT5_NULL_STRINGS == 1 |
624 | return d.data() ? d.data() : &_empty; |
625 | #else |
626 | return d.data(); |
627 | #endif |
628 | } |
629 | inline void QByteArray::detach() |
630 | { if (d.needsDetach()) reallocData(alloc: size(), option: QArrayData::KeepSize); } |
631 | inline bool QByteArray::isDetached() const |
632 | { return !d.isShared(); } |
633 | inline QByteArray::QByteArray(const QByteArray &a) noexcept : d(a.d) |
634 | {} |
635 | |
636 | inline qsizetype QByteArray::capacity() const { return qsizetype(d.constAllocatedCapacity()); } |
637 | |
638 | inline void QByteArray::reserve(qsizetype asize) |
639 | { |
640 | if (d.needsDetach() || asize > capacity() - d.freeSpaceAtBegin()) |
641 | reallocData(alloc: qMax(a: size(), b: asize), option: QArrayData::KeepSize); |
642 | if (d.constAllocatedCapacity()) |
643 | d.setFlag(Data::CapacityReserved); |
644 | } |
645 | |
646 | inline void QByteArray::squeeze() |
647 | { |
648 | if (!d.isMutable()) |
649 | return; |
650 | if (d.needsDetach() || size() < capacity()) |
651 | reallocData(alloc: size(), option: QArrayData::KeepSize); |
652 | if (d.constAllocatedCapacity()) |
653 | d.clearFlag(f: Data::CapacityReserved); |
654 | } |
655 | |
656 | inline char &QByteArray::operator[](qsizetype i) |
657 | { verify(pos: i, n: 1); return data()[i]; } |
658 | inline char &QByteArray::front() { return operator[](i: 0); } |
659 | inline char &QByteArray::back() { return operator[](i: size() - 1); } |
660 | inline QByteArray &QByteArray::append(qsizetype n, char ch) |
661 | { return insert(i: size(), count: n, c: ch); } |
662 | inline QByteArray &QByteArray::prepend(qsizetype n, char ch) |
663 | { return insert(i: 0, count: n, c: ch); } |
664 | inline bool QByteArray::contains(char c) const |
665 | { return indexOf(c) != -1; } |
666 | inline bool QByteArray::contains(QByteArrayView bv) const |
667 | { return indexOf(bv) != -1; } |
668 | inline int QByteArray::compare(QByteArrayView a, Qt::CaseSensitivity cs) const noexcept |
669 | { |
670 | return cs == Qt::CaseSensitive ? QtPrivate::compareMemory(lhs: *this, rhs: a) : |
671 | qstrnicmp(data(), size(), a.data(), a.size()); |
672 | } |
673 | #if !defined(QT_USE_QSTRINGBUILDER) |
674 | inline QByteArray operator+(const QByteArray &a1, const QByteArray &a2) |
675 | { return QByteArray(a1) += a2; } |
676 | inline QByteArray operator+(QByteArray &&lhs, const QByteArray &rhs) |
677 | { return std::move(lhs += rhs); } |
678 | inline QByteArray operator+(const QByteArray &a1, const char *a2) |
679 | { return QByteArray(a1) += a2; } |
680 | inline QByteArray operator+(QByteArray &&lhs, const char *rhs) |
681 | { return std::move(lhs += rhs); } |
682 | inline QByteArray operator+(const QByteArray &a1, char a2) |
683 | { return QByteArray(a1) += a2; } |
684 | inline QByteArray operator+(QByteArray &&lhs, char rhs) |
685 | { return std::move(lhs += rhs); } |
686 | inline QByteArray operator+(const char *a1, const QByteArray &a2) |
687 | { return QByteArray(a1) += a2; } |
688 | inline QByteArray operator+(char a1, const QByteArray &a2) |
689 | { return QByteArray(&a1, 1) += a2; } |
690 | #endif // QT_USE_QSTRINGBUILDER |
691 | |
692 | inline QByteArray &QByteArray::setNum(short n, int base) |
693 | { return setNum(qlonglong(n), base); } |
694 | inline QByteArray &QByteArray::setNum(ushort n, int base) |
695 | { return setNum(qulonglong(n), base); } |
696 | inline QByteArray &QByteArray::setNum(int n, int base) |
697 | { return setNum(qlonglong(n), base); } |
698 | inline QByteArray &QByteArray::setNum(uint n, int base) |
699 | { return setNum(qulonglong(n), base); } |
700 | inline QByteArray &QByteArray::setNum(long n, int base) |
701 | { return setNum(qlonglong(n), base); } |
702 | inline QByteArray &QByteArray::setNum(ulong n, int base) |
703 | { return setNum(qulonglong(n), base); } |
704 | inline QByteArray &QByteArray::setNum(float n, char format, int precision) |
705 | { return setNum(double(n), format, precision); } |
706 | |
707 | #if QT_CORE_INLINE_IMPL_SINCE(6, 4) |
708 | bool QByteArray::isNull() const noexcept |
709 | { |
710 | return d.isNull(); |
711 | } |
712 | #endif |
713 | #if QT_CORE_INLINE_IMPL_SINCE(6, 8) |
714 | qsizetype QByteArray::indexOf(char ch, qsizetype from) const |
715 | { |
716 | return qToByteArrayViewIgnoringNull(b: *this).indexOf(ch, from); |
717 | } |
718 | qsizetype QByteArray::lastIndexOf(char ch, qsizetype from) const |
719 | { |
720 | return qToByteArrayViewIgnoringNull(b: *this).lastIndexOf(ch, from); |
721 | } |
722 | #endif |
723 | |
724 | #if !defined(QT_NO_DATASTREAM) || defined(QT_BOOTSTRAPPED) |
725 | Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QByteArray &); |
726 | Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QByteArray &); |
727 | #endif |
728 | |
729 | #ifndef QT_NO_COMPRESS |
730 | Q_CORE_EXPORT QByteArray qCompress(const uchar* data, qsizetype nbytes, int compressionLevel = -1); |
731 | Q_CORE_EXPORT QByteArray qUncompress(const uchar* data, qsizetype nbytes); |
732 | inline QByteArray qCompress(const QByteArray& data, int compressionLevel = -1) |
733 | { return qCompress(data: reinterpret_cast<const uchar *>(data.constData()), nbytes: data.size(), compressionLevel); } |
734 | inline QByteArray qUncompress(const QByteArray& data) |
735 | { return qUncompress(data: reinterpret_cast<const uchar*>(data.constData()), nbytes: data.size()); } |
736 | #endif |
737 | |
738 | Q_DECLARE_SHARED(QByteArray) |
739 | |
740 | class QByteArray::FromBase64Result |
741 | { |
742 | public: |
743 | QByteArray decoded; |
744 | QByteArray::Base64DecodingStatus decodingStatus; |
745 | |
746 | void swap(QByteArray::FromBase64Result &other) noexcept |
747 | { |
748 | decoded.swap(other&: other.decoded); |
749 | std::swap(a&: decodingStatus, b&: other.decodingStatus); |
750 | } |
751 | |
752 | explicit operator bool() const noexcept { return decodingStatus == QByteArray::Base64DecodingStatus::Ok; } |
753 | |
754 | #if defined(Q_COMPILER_REF_QUALIFIERS) && !defined(Q_QDOC) |
755 | QByteArray &operator*() & noexcept { return decoded; } |
756 | const QByteArray &operator*() const & noexcept { return decoded; } |
757 | QByteArray &&operator*() && noexcept { return std::move(decoded); } |
758 | #else |
759 | QByteArray &operator*() noexcept { return decoded; } |
760 | const QByteArray &operator*() const noexcept { return decoded; } |
761 | #endif |
762 | |
763 | friend inline bool operator==(const QByteArray::FromBase64Result &lhs, const QByteArray::FromBase64Result &rhs) noexcept |
764 | { |
765 | if (lhs.decodingStatus != rhs.decodingStatus) |
766 | return false; |
767 | |
768 | if (lhs.decodingStatus == QByteArray::Base64DecodingStatus::Ok && lhs.decoded != rhs.decoded) |
769 | return false; |
770 | |
771 | return true; |
772 | } |
773 | |
774 | friend inline bool operator!=(const QByteArray::FromBase64Result &lhs, const QByteArray::FromBase64Result &rhs) noexcept |
775 | { |
776 | return !(lhs == rhs); |
777 | } |
778 | }; |
779 | |
780 | Q_DECLARE_SHARED(QByteArray::FromBase64Result) |
781 | |
782 | |
783 | Q_CORE_EXPORT Q_DECL_PURE_FUNCTION size_t qHash(const QByteArray::FromBase64Result &key, size_t seed = 0) noexcept; |
784 | |
785 | template <typename T> |
786 | qsizetype erase(QByteArray &ba, const T &t) |
787 | { |
788 | return ba.removeIf_helper([&t](const auto &e) { return t == e; }); |
789 | } |
790 | |
791 | template <typename Predicate> |
792 | qsizetype erase_if(QByteArray &ba, Predicate pred) |
793 | { |
794 | return ba.removeIf_helper(pred); |
795 | } |
796 | |
797 | // |
798 | // QByteArrayView members that require QByteArray: |
799 | // |
800 | QByteArray QByteArrayView::toByteArray() const |
801 | { |
802 | return QByteArray(*this); |
803 | } |
804 | |
805 | namespace Qt { |
806 | inline namespace Literals { |
807 | inline namespace StringLiterals { |
808 | |
809 | inline QByteArray operator""_ba(const char *str, size_t size) noexcept |
810 | { |
811 | return QByteArray(QByteArrayData(nullptr, const_cast<char *>(str), qsizetype(size))); |
812 | } |
813 | |
814 | } // StringLiterals |
815 | } // Literals |
816 | } // Qt |
817 | |
818 | inline namespace QtLiterals { |
819 | #if QT_DEPRECATED_SINCE(6, 8) |
820 | |
821 | QT_DEPRECATED_VERSION_X_6_8("Use _ba from Qt::StringLiterals namespace instead.") |
822 | inline QByteArray operator""_qba(const char *str, size_t size) noexcept |
823 | { |
824 | return Qt::StringLiterals::operator""_ba(str, size); |
825 | } |
826 | |
827 | #endif // QT_DEPRECATED_SINCE(6, 8) |
828 | } // QtLiterals |
829 | |
830 | QT_END_NAMESPACE |
831 | |
832 | #endif // QBYTEARRAY_H |
833 |
Definitions
- QByteArray
- Base64Option
- Base64DecodingStatus
- QByteArray
- QByteArray
- swap
- isEmpty
- constData
- isSharedWith
- front
- back
- indexOf
- lastIndexOf
- lastIndexOf
- count
- left
- left
- right
- right
- first
- last
- sliced
- sliced
- chopped
- first
- last
- sliced
- sliced
- chopped
- startsWith
- startsWith
- endsWith
- endsWith
- isValidUtf8
- slice
- slice
- toLower
- toLower
- toUpper
- toUpper
- trimmed
- trimmed
- simplified
- simplified
- prepend
- prepend
- prepend
- prepend
- append
- append
- append
- assign
- assign
- insert
- insert
- insert
- insert
- removeAt
- removeFirst
- removeLast
- removeIf
- replace
- replace
- replace
- operator+=
- operator+=
- operator+=
- operator+=
- fromRawData
- begin
- begin
- cbegin
- constBegin
- end
- end
- cend
- constEnd
- rbegin
- rend
- rbegin
- rend
- crbegin
- crend
- push_back
- push_back
- push_back
- push_back
- push_front
- push_front
- push_front
- push_front
- shrink_to_fit
- erase
- max_size
- maxSize
- size
- count
- length
- data_ptr
- data_ptr
- QByteArray
- QByteArray
- comparesEqual
- compareThreeWay
- comparesEqual
- compareThreeWay
- verify
- removeIf_helper
- QByteArray
- ~QByteArray
- at
- operator[]
- operator const char *
- operator const void *
- data
- data
- detach
- isDetached
- QByteArray
- capacity
- reserve
- squeeze
- operator[]
- front
- back
- append
- prepend
- contains
- contains
- compare
- setNum
- setNum
- setNum
- setNum
- setNum
- setNum
- setNum
- isNull
- indexOf
- lastIndexOf
- qCompress
- qUncompress
- FromBase64Result
- swap
- operator bool
- operator*
- operator*
- operator*
- operator==
- operator!=
- erase
- erase_if
- toByteArray
- operator""_ba
Learn Advanced QML with KDAB
Find out more