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/qcontainerfwd.h> |
13 | #include <QtCore/qbytearrayalgorithms.h> |
14 | #include <QtCore/qbytearrayview.h> |
15 | |
16 | #include <stdlib.h> |
17 | #include <string.h> |
18 | #include <stdarg.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 | |
72 | enum Base64Option { |
73 | Base64Encoding = 0, |
74 | Base64UrlEncoding = 1, |
75 | |
76 | KeepTrailingEquals = 0, |
77 | OmitTrailingEquals = 2, |
78 | |
79 | IgnoreBase64DecodingErrors = 0, |
80 | AbortOnBase64DecodingErrors = 4, |
81 | }; |
82 | Q_DECLARE_FLAGS(Base64Options, Base64Option) |
83 | |
84 | enum class Base64DecodingStatus { |
85 | Ok, |
86 | IllegalInputLength, |
87 | IllegalCharacter, |
88 | IllegalPadding, |
89 | }; |
90 | |
91 | inline constexpr QByteArray() noexcept; |
92 | QByteArray(const char *, qsizetype size = -1); |
93 | QByteArray(qsizetype size, char c); |
94 | QByteArray(qsizetype size, Qt::Initialization); |
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 | |
110 | QByteArray &fill(char c, qsizetype size = -1); |
111 | |
112 | inline qsizetype capacity() const; |
113 | inline void reserve(qsizetype size); |
114 | inline void squeeze(); |
115 | |
116 | #ifndef QT_NO_CAST_FROM_BYTEARRAY |
117 | inline operator const char *() const; |
118 | inline operator const void *() const; |
119 | #endif |
120 | inline char *data(); |
121 | inline const char *data() const noexcept; |
122 | const char *constData() const noexcept { return data(); } |
123 | inline void detach(); |
124 | inline bool isDetached() const; |
125 | inline bool isSharedWith(const QByteArray &other) const noexcept |
126 | { return data() == other.data() && size() == other.size(); } |
127 | void clear(); |
128 | |
129 | inline char at(qsizetype i) const; |
130 | inline char operator[](qsizetype i) const; |
131 | [[nodiscard]] inline char &operator[](qsizetype i); |
132 | [[nodiscard]] char front() const { return at(i: 0); } |
133 | [[nodiscard]] inline char &front(); |
134 | [[nodiscard]] char back() const { return at(i: size() - 1); } |
135 | [[nodiscard]] inline char &back(); |
136 | |
137 | qsizetype indexOf(char c, qsizetype from = 0) const; |
138 | qsizetype indexOf(QByteArrayView bv, qsizetype from = 0) const |
139 | { return QtPrivate::findByteArray(haystack: qToByteArrayViewIgnoringNull(b: *this), from, needle: bv); } |
140 | |
141 | qsizetype lastIndexOf(char c, qsizetype from = -1) const; |
142 | qsizetype lastIndexOf(QByteArrayView bv) const |
143 | { return lastIndexOf(bv, from: size()); } |
144 | qsizetype lastIndexOf(QByteArrayView bv, qsizetype from) const |
145 | { return QtPrivate::lastIndexOf(haystack: qToByteArrayViewIgnoringNull(b: *this), from, needle: bv); } |
146 | |
147 | inline bool contains(char c) const; |
148 | inline bool contains(QByteArrayView bv) const; |
149 | qsizetype count(char c) const; |
150 | qsizetype count(QByteArrayView bv) const |
151 | { return QtPrivate::count(haystack: qToByteArrayViewIgnoringNull(b: *this), needle: bv); } |
152 | |
153 | inline int compare(QByteArrayView a, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept; |
154 | |
155 | [[nodiscard]] QByteArray left(qsizetype len) const; |
156 | [[nodiscard]] QByteArray right(qsizetype len) const; |
157 | [[nodiscard]] QByteArray mid(qsizetype index, qsizetype len = -1) const; |
158 | |
159 | [[nodiscard]] QByteArray first(qsizetype n) const |
160 | { Q_ASSERT(n >= 0); Q_ASSERT(n <= size()); return QByteArray(data(), n); } |
161 | [[nodiscard]] QByteArray last(qsizetype n) const |
162 | { Q_ASSERT(n >= 0); Q_ASSERT(n <= size()); return QByteArray(data() + size() - n, n); } |
163 | [[nodiscard]] QByteArray sliced(qsizetype pos) const |
164 | { Q_ASSERT(pos >= 0); Q_ASSERT(pos <= size()); return QByteArray(data() + pos, size() - pos); } |
165 | [[nodiscard]] QByteArray sliced(qsizetype pos, qsizetype n) const |
166 | { Q_ASSERT(pos >= 0); Q_ASSERT(n >= 0); Q_ASSERT(size_t(pos) + size_t(n) <= size_t(size())); return QByteArray(data() + pos, n); } |
167 | [[nodiscard]] QByteArray chopped(qsizetype len) const |
168 | { Q_ASSERT(len >= 0); Q_ASSERT(len <= size()); return first(n: size() - len); } |
169 | |
170 | bool startsWith(QByteArrayView bv) const |
171 | { return QtPrivate::startsWith(haystack: qToByteArrayViewIgnoringNull(b: *this), needle: bv); } |
172 | bool startsWith(char c) const { return size() > 0 && front() == c; } |
173 | |
174 | bool endsWith(char c) const { return size() > 0 && back() == c; } |
175 | bool endsWith(QByteArrayView bv) const |
176 | { return QtPrivate::endsWith(haystack: qToByteArrayViewIgnoringNull(b: *this), needle: bv); } |
177 | |
178 | bool isUpper() const; |
179 | bool isLower() const; |
180 | |
181 | [[nodiscard]] bool isValidUtf8() const noexcept |
182 | { |
183 | return QtPrivate::isValidUtf8(s: qToByteArrayViewIgnoringNull(b: *this)); |
184 | } |
185 | |
186 | void truncate(qsizetype pos); |
187 | void chop(qsizetype n); |
188 | |
189 | #if !defined(Q_QDOC) |
190 | [[nodiscard]] QByteArray toLower() const & |
191 | { return toLower_helper(a: *this); } |
192 | [[nodiscard]] QByteArray toLower() && |
193 | { return toLower_helper(a&: *this); } |
194 | [[nodiscard]] QByteArray toUpper() const & |
195 | { return toUpper_helper(a: *this); } |
196 | [[nodiscard]] QByteArray toUpper() && |
197 | { return toUpper_helper(a&: *this); } |
198 | [[nodiscard]] QByteArray trimmed() const & |
199 | { return trimmed_helper(a: *this); } |
200 | [[nodiscard]] QByteArray trimmed() && |
201 | { return trimmed_helper(a&: *this); } |
202 | [[nodiscard]] QByteArray simplified() const & |
203 | { return simplified_helper(a: *this); } |
204 | [[nodiscard]] QByteArray simplified() && |
205 | { return simplified_helper(a&: *this); } |
206 | #else |
207 | [[nodiscard]] QByteArray toLower() const; |
208 | [[nodiscard]] QByteArray toUpper() const; |
209 | [[nodiscard]] QByteArray trimmed() const; |
210 | [[nodiscard]] QByteArray simplified() const; |
211 | #endif |
212 | |
213 | [[nodiscard]] QByteArray leftJustified(qsizetype width, char fill = ' ', bool truncate = false) const; |
214 | [[nodiscard]] QByteArray rightJustified(qsizetype width, char fill = ' ', bool truncate = false) const; |
215 | |
216 | QByteArray &prepend(char c) |
217 | { return insert(i: 0, data: QByteArrayView(&c, 1)); } |
218 | inline QByteArray &prepend(qsizetype count, char c); |
219 | QByteArray &prepend(const char *s) |
220 | { return insert(i: 0, data: QByteArrayView(s, qsizetype(qstrlen(str: s)))); } |
221 | QByteArray &prepend(const char *s, qsizetype len) |
222 | { return insert(i: 0, data: QByteArrayView(s, len)); } |
223 | QByteArray &prepend(const QByteArray &a); |
224 | QByteArray &prepend(QByteArrayView a) |
225 | { return insert(i: 0, data: a); } |
226 | |
227 | QByteArray &append(char c); |
228 | inline QByteArray &append(qsizetype count, char c); |
229 | QByteArray &append(const char *s) |
230 | { return append(s, len: -1); } |
231 | QByteArray &append(const char *s, qsizetype len) |
232 | { return append(a: QByteArrayView(s, len < 0 ? qsizetype(qstrlen(str: s)) : len)); } |
233 | QByteArray &append(const QByteArray &a); |
234 | QByteArray &append(QByteArrayView a) |
235 | { return insert(i: size(), data: a); } |
236 | |
237 | QByteArray &assign(QByteArrayView v); |
238 | QByteArray &assign(qsizetype n, char c) |
239 | { |
240 | Q_ASSERT(n >= 0); |
241 | return fill(c, size: n); |
242 | } |
243 | template <typename InputIterator, if_input_iterator<InputIterator> = true> |
244 | QByteArray &assign(InputIterator first, InputIterator last) |
245 | { |
246 | d.assign(first, last); |
247 | d.data()[d.size] = '\0'; |
248 | return *this; |
249 | } |
250 | |
251 | QByteArray &insert(qsizetype i, QByteArrayView data); |
252 | inline QByteArray &insert(qsizetype i, const char *s) |
253 | { return insert(i, data: QByteArrayView(s)); } |
254 | inline QByteArray &insert(qsizetype i, const QByteArray &data) |
255 | { return insert(i, data: QByteArrayView(data)); } |
256 | QByteArray &insert(qsizetype i, qsizetype count, char c); |
257 | QByteArray &insert(qsizetype i, char c) |
258 | { return insert(i, data: QByteArrayView(&c, 1)); } |
259 | QByteArray &insert(qsizetype i, const char *s, qsizetype len) |
260 | { return insert(i, data: QByteArrayView(s, len)); } |
261 | |
262 | QByteArray &remove(qsizetype index, qsizetype len); |
263 | QByteArray &removeAt(qsizetype pos) |
264 | { return size_t(pos) < size_t(size()) ? remove(index: pos, len: 1) : *this; } |
265 | QByteArray &removeFirst() { return !isEmpty() ? remove(index: 0, len: 1) : *this; } |
266 | QByteArray &removeLast() { return !isEmpty() ? remove(index: size() - 1, len: 1) : *this; } |
267 | |
268 | template <typename Predicate> |
269 | QByteArray &removeIf(Predicate pred) |
270 | { |
271 | removeIf_helper(pred); |
272 | return *this; |
273 | } |
274 | |
275 | QByteArray &replace(qsizetype index, qsizetype len, const char *s, qsizetype alen) |
276 | { return replace(index, len, s: QByteArrayView(s, alen)); } |
277 | QByteArray &replace(qsizetype index, qsizetype len, QByteArrayView s); |
278 | QByteArray &replace(char before, QByteArrayView after) |
279 | { return replace(before: QByteArrayView(&before, 1), after); } |
280 | QByteArray &replace(const char *before, qsizetype bsize, const char *after, qsizetype asize) |
281 | { return replace(before: QByteArrayView(before, bsize), after: QByteArrayView(after, asize)); } |
282 | QByteArray &replace(QByteArrayView before, QByteArrayView after); |
283 | QByteArray &replace(char before, char after); |
284 | |
285 | QByteArray &operator+=(char c) |
286 | { return append(c); } |
287 | QByteArray &operator+=(const char *s) |
288 | { return append(s); } |
289 | QByteArray &operator+=(const QByteArray &a) |
290 | { return append(a); } |
291 | QByteArray &operator+=(QByteArrayView a) |
292 | { return append(a); } |
293 | |
294 | QList<QByteArray> split(char sep) const; |
295 | |
296 | [[nodiscard]] QByteArray repeated(qsizetype times) const; |
297 | |
298 | #if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII) |
299 | QT_ASCII_CAST_WARN inline bool operator==(const QString &s2) const; |
300 | QT_ASCII_CAST_WARN inline bool operator!=(const QString &s2) const; |
301 | QT_ASCII_CAST_WARN inline bool operator<(const QString &s2) const; |
302 | QT_ASCII_CAST_WARN inline bool operator>(const QString &s2) const; |
303 | QT_ASCII_CAST_WARN inline bool operator<=(const QString &s2) const; |
304 | QT_ASCII_CAST_WARN inline bool operator>=(const QString &s2) const; |
305 | #endif |
306 | friend inline bool operator==(const QByteArray &a1, const QByteArray &a2) noexcept |
307 | { return QByteArrayView(a1) == QByteArrayView(a2); } |
308 | friend inline bool operator==(const QByteArray &a1, const char *a2) noexcept |
309 | { return QByteArrayView(a1) == QByteArrayView(a2); } |
310 | friend inline bool operator==(const char *a1, const QByteArray &a2) noexcept |
311 | { return QByteArrayView(a1) == QByteArrayView(a2); } |
312 | friend inline bool operator!=(const QByteArray &a1, const QByteArray &a2) noexcept |
313 | { return !(a1==a2); } |
314 | friend inline bool operator!=(const QByteArray &a1, const char *a2) noexcept |
315 | { return QByteArrayView(a1) != QByteArrayView(a2); } |
316 | friend inline bool operator!=(const char *a1, const QByteArray &a2) noexcept |
317 | { return QByteArrayView(a1) != QByteArrayView(a2); } |
318 | friend inline bool operator<(const QByteArray &a1, const QByteArray &a2) noexcept |
319 | { return QtPrivate::compareMemory(lhs: QByteArrayView(a1), rhs: QByteArrayView(a2)) < 0; } |
320 | friend inline bool operator<(const QByteArray &a1, const char *a2) noexcept |
321 | { return QtPrivate::compareMemory(lhs: a1, rhs: a2) < 0; } |
322 | friend inline bool operator<(const char *a1, const QByteArray &a2) noexcept |
323 | { return QtPrivate::compareMemory(lhs: a1, rhs: a2) < 0; } |
324 | friend inline bool operator<=(const QByteArray &a1, const QByteArray &a2) noexcept |
325 | { return QtPrivate::compareMemory(lhs: QByteArrayView(a1), rhs: QByteArrayView(a2)) <= 0; } |
326 | friend inline bool operator<=(const QByteArray &a1, const char *a2) noexcept |
327 | { return QtPrivate::compareMemory(lhs: a1, rhs: a2) <= 0; } |
328 | friend inline bool operator<=(const char *a1, const QByteArray &a2) noexcept |
329 | { return QtPrivate::compareMemory(lhs: a1, rhs: a2) <= 0; } |
330 | friend inline bool operator>(const QByteArray &a1, const QByteArray &a2) noexcept |
331 | { return QtPrivate::compareMemory(lhs: QByteArrayView(a1), rhs: QByteArrayView(a2)) > 0; } |
332 | friend inline bool operator>(const QByteArray &a1, const char *a2) noexcept |
333 | { return QtPrivate::compareMemory(lhs: a1, rhs: a2) > 0; } |
334 | friend inline bool operator>(const char *a1, const QByteArray &a2) noexcept |
335 | { return QtPrivate::compareMemory(lhs: a1, rhs: a2) > 0; } |
336 | friend inline bool operator>=(const QByteArray &a1, const QByteArray &a2) noexcept |
337 | { return QtPrivate::compareMemory(lhs: QByteArrayView(a1), rhs: QByteArrayView(a2)) >= 0; } |
338 | friend inline bool operator>=(const QByteArray &a1, const char *a2) noexcept |
339 | { return QtPrivate::compareMemory(lhs: a1, rhs: a2) >= 0; } |
340 | friend inline bool operator>=(const char *a1, const QByteArray &a2) noexcept |
341 | { return QtPrivate::compareMemory(lhs: a1, rhs: a2) >= 0; } |
342 | |
343 | // Check isEmpty() instead of isNull() for backwards compatibility. |
344 | friend inline bool operator==(const QByteArray &a1, std::nullptr_t) noexcept { return a1.isEmpty(); } |
345 | friend inline bool operator!=(const QByteArray &a1, std::nullptr_t) noexcept { return !a1.isEmpty(); } |
346 | friend inline bool operator< (const QByteArray & , std::nullptr_t) noexcept { return false; } |
347 | friend inline bool operator> (const QByteArray &a1, std::nullptr_t) noexcept { return !a1.isEmpty(); } |
348 | friend inline bool operator<=(const QByteArray &a1, std::nullptr_t) noexcept { return a1.isEmpty(); } |
349 | friend inline bool operator>=(const QByteArray & , std::nullptr_t) noexcept { return true; } |
350 | |
351 | friend inline bool operator==(std::nullptr_t, const QByteArray &a2) noexcept { return a2 == nullptr; } |
352 | friend inline bool operator!=(std::nullptr_t, const QByteArray &a2) noexcept { return a2 != nullptr; } |
353 | friend inline bool operator< (std::nullptr_t, const QByteArray &a2) noexcept { return a2 > nullptr; } |
354 | friend inline bool operator> (std::nullptr_t, const QByteArray &a2) noexcept { return a2 < nullptr; } |
355 | friend inline bool operator<=(std::nullptr_t, const QByteArray &a2) noexcept { return a2 >= nullptr; } |
356 | friend inline bool operator>=(std::nullptr_t, const QByteArray &a2) noexcept { return a2 <= nullptr; } |
357 | |
358 | short toShort(bool *ok = nullptr, int base = 10) const; |
359 | ushort toUShort(bool *ok = nullptr, int base = 10) const; |
360 | int toInt(bool *ok = nullptr, int base = 10) const; |
361 | uint toUInt(bool *ok = nullptr, int base = 10) const; |
362 | long toLong(bool *ok = nullptr, int base = 10) const; |
363 | ulong toULong(bool *ok = nullptr, int base = 10) const; |
364 | qlonglong toLongLong(bool *ok = nullptr, int base = 10) const; |
365 | qulonglong toULongLong(bool *ok = nullptr, int base = 10) const; |
366 | float toFloat(bool *ok = nullptr) const; |
367 | double toDouble(bool *ok = nullptr) const; |
368 | QByteArray toBase64(Base64Options options = Base64Encoding) const; |
369 | QByteArray toHex(char separator = '\0') const; |
370 | QByteArray toPercentEncoding(const QByteArray &exclude = QByteArray(), |
371 | const QByteArray &include = QByteArray(), |
372 | char percent = '%') const; |
373 | [[nodiscard]] QByteArray percentDecoded(char percent = '%') const; |
374 | |
375 | inline QByteArray &setNum(short, int base = 10); |
376 | inline QByteArray &setNum(ushort, int base = 10); |
377 | inline QByteArray &setNum(int, int base = 10); |
378 | inline QByteArray &setNum(uint, int base = 10); |
379 | inline QByteArray &setNum(long, int base = 10); |
380 | inline QByteArray &setNum(ulong, int base = 10); |
381 | QByteArray &setNum(qlonglong, int base = 10); |
382 | QByteArray &setNum(qulonglong, int base = 10); |
383 | inline QByteArray &setNum(float, char format = 'g', int precision = 6); |
384 | QByteArray &setNum(double, char format = 'g', int precision = 6); |
385 | QByteArray &setRawData(const char *a, qsizetype n); |
386 | |
387 | [[nodiscard]] static QByteArray number(int, int base = 10); |
388 | [[nodiscard]] static QByteArray number(uint, int base = 10); |
389 | [[nodiscard]] static QByteArray number(long, int base = 10); |
390 | [[nodiscard]] static QByteArray number(ulong, int base = 10); |
391 | [[nodiscard]] static QByteArray number(qlonglong, int base = 10); |
392 | [[nodiscard]] static QByteArray number(qulonglong, int base = 10); |
393 | [[nodiscard]] static QByteArray number(double, char format = 'g', int precision = 6); |
394 | [[nodiscard]] static QByteArray fromRawData(const char *data, qsizetype size) |
395 | { |
396 | return QByteArray(DataPointer(nullptr, const_cast<char *>(data), size)); |
397 | } |
398 | |
399 | class FromBase64Result; |
400 | [[nodiscard]] static FromBase64Result fromBase64Encoding(QByteArray &&base64, Base64Options options = Base64Encoding); |
401 | [[nodiscard]] static FromBase64Result fromBase64Encoding(const QByteArray &base64, Base64Options options = Base64Encoding); |
402 | [[nodiscard]] static QByteArray fromBase64(const QByteArray &base64, Base64Options options = Base64Encoding); |
403 | [[nodiscard]] static QByteArray fromHex(const QByteArray &hexEncoded); |
404 | [[nodiscard]] static QByteArray fromPercentEncoding(const QByteArray &pctEncoded, char percent = '%'); |
405 | |
406 | #if defined(Q_OS_DARWIN) || defined(Q_QDOC) |
407 | static QByteArray fromCFData(CFDataRef data); |
408 | static QByteArray fromRawCFData(CFDataRef data); |
409 | CFDataRef toCFData() const Q_DECL_CF_RETURNS_RETAINED; |
410 | CFDataRef toRawCFData() const Q_DECL_CF_RETURNS_RETAINED; |
411 | static QByteArray fromNSData(const NSData *data); |
412 | static QByteArray fromRawNSData(const NSData *data); |
413 | NSData *toNSData() const Q_DECL_NS_RETURNS_AUTORELEASED; |
414 | NSData *toRawNSData() const Q_DECL_NS_RETURNS_AUTORELEASED; |
415 | #endif |
416 | |
417 | #if defined(Q_OS_WASM) || defined(Q_QDOC) |
418 | static QByteArray fromEcmaUint8Array(emscripten::val uint8array); |
419 | emscripten::val toEcmaUint8Array(); |
420 | #endif |
421 | |
422 | typedef char *iterator; |
423 | typedef const char *const_iterator; |
424 | typedef iterator Iterator; |
425 | typedef const_iterator ConstIterator; |
426 | typedef std::reverse_iterator<iterator> reverse_iterator; |
427 | typedef std::reverse_iterator<const_iterator> const_reverse_iterator; |
428 | iterator begin() { return data(); } |
429 | const_iterator begin() const noexcept { return data(); } |
430 | const_iterator cbegin() const noexcept { return begin(); } |
431 | const_iterator constBegin() const noexcept { return begin(); } |
432 | iterator end() { return data() + size(); } |
433 | const_iterator end() const noexcept { return data() + size(); } |
434 | const_iterator cend() const noexcept { return end(); } |
435 | const_iterator constEnd() const noexcept { return end(); } |
436 | reverse_iterator rbegin() { return reverse_iterator(end()); } |
437 | reverse_iterator rend() { return reverse_iterator(begin()); } |
438 | const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); } |
439 | const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); } |
440 | const_reverse_iterator crbegin() const noexcept { return rbegin(); } |
441 | const_reverse_iterator crend() const noexcept { return rend(); } |
442 | |
443 | // stl compatibility |
444 | typedef qsizetype size_type; |
445 | typedef qptrdiff difference_type; |
446 | typedef const char & const_reference; |
447 | typedef char & reference; |
448 | typedef char *pointer; |
449 | typedef const char *const_pointer; |
450 | typedef char value_type; |
451 | void push_back(char c) |
452 | { append(c); } |
453 | void push_back(const char *s) |
454 | { append(s); } |
455 | void push_back(const QByteArray &a) |
456 | { append(a); } |
457 | void push_back(QByteArrayView a) |
458 | { append(a); } |
459 | void push_front(char c) |
460 | { prepend(c); } |
461 | void push_front(const char *c) |
462 | { prepend(s: c); } |
463 | void push_front(const QByteArray &a) |
464 | { prepend(a); } |
465 | void push_front(QByteArrayView a) |
466 | { prepend(a); } |
467 | void shrink_to_fit() { squeeze(); } |
468 | iterator erase(const_iterator first, const_iterator last); |
469 | inline iterator erase(const_iterator it) { return erase(first: it, last: it + 1); } |
470 | |
471 | static QByteArray fromStdString(const std::string &s); |
472 | std::string toStdString() const; |
473 | |
474 | inline qsizetype size() const noexcept { return d->size; } |
475 | #if QT_DEPRECATED_SINCE(6, 4) |
476 | QT_DEPRECATED_VERSION_X_6_4("Use size() or length() instead." ) |
477 | inline qsizetype count() const noexcept { return size(); } |
478 | #endif |
479 | inline qsizetype length() const noexcept { return size(); } |
480 | QT_CORE_INLINE_SINCE(6, 4) |
481 | bool isNull() const noexcept; |
482 | |
483 | inline DataPointer &data_ptr() { return d; } |
484 | #if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) |
485 | explicit inline QByteArray(const DataPointer &dd) : d(dd) {} |
486 | #endif |
487 | explicit inline QByteArray(DataPointer &&dd) : d(std::move(dd)) {} |
488 | |
489 | private: |
490 | void reallocData(qsizetype alloc, QArrayData::AllocationOption option); |
491 | void reallocGrowData(qsizetype n); |
492 | void expand(qsizetype i); |
493 | |
494 | static QByteArray toLower_helper(const QByteArray &a); |
495 | static QByteArray toLower_helper(QByteArray &a); |
496 | static QByteArray toUpper_helper(const QByteArray &a); |
497 | static QByteArray toUpper_helper(QByteArray &a); |
498 | static QByteArray trimmed_helper(const QByteArray &a); |
499 | static QByteArray trimmed_helper(QByteArray &a); |
500 | static QByteArray simplified_helper(const QByteArray &a); |
501 | static QByteArray simplified_helper(QByteArray &a); |
502 | template <typename Predicate> |
503 | qsizetype removeIf_helper(Predicate pred) |
504 | { |
505 | const qsizetype result = d->eraseIf(pred); |
506 | if (result > 0) |
507 | d.data()[d.size] = '\0'; |
508 | return result; |
509 | } |
510 | |
511 | friend class QString; |
512 | friend Q_CORE_EXPORT QByteArray qUncompress(const uchar *data, qsizetype nbytes); |
513 | |
514 | template <typename T> friend qsizetype erase(QByteArray &ba, const T &t); |
515 | template <typename Predicate> friend qsizetype erase_if(QByteArray &ba, Predicate pred); |
516 | }; |
517 | |
518 | Q_DECLARE_OPERATORS_FOR_FLAGS(QByteArray::Base64Options) |
519 | |
520 | inline constexpr QByteArray::QByteArray() noexcept {} |
521 | inline QByteArray::~QByteArray() {} |
522 | |
523 | inline char QByteArray::at(qsizetype i) const |
524 | { Q_ASSERT(size_t(i) < size_t(size())); return d.data()[i]; } |
525 | inline char QByteArray::operator[](qsizetype i) const |
526 | { Q_ASSERT(size_t(i) < size_t(size())); return d.data()[i]; } |
527 | |
528 | #ifndef QT_NO_CAST_FROM_BYTEARRAY |
529 | inline QByteArray::operator const char *() const |
530 | { return data(); } |
531 | inline QByteArray::operator const void *() const |
532 | { return data(); } |
533 | #endif |
534 | inline char *QByteArray::data() |
535 | { |
536 | detach(); |
537 | Q_ASSERT(d.data()); |
538 | return d.data(); |
539 | } |
540 | inline const char *QByteArray::data() const noexcept |
541 | { |
542 | #if QT5_NULL_STRINGS == 1 |
543 | return d.data() ? d.data() : &_empty; |
544 | #else |
545 | return d.data(); |
546 | #endif |
547 | } |
548 | inline void QByteArray::detach() |
549 | { if (d->needsDetach()) reallocData(alloc: size(), option: QArrayData::KeepSize); } |
550 | inline bool QByteArray::isDetached() const |
551 | { return !d->isShared(); } |
552 | inline QByteArray::QByteArray(const QByteArray &a) noexcept : d(a.d) |
553 | {} |
554 | |
555 | inline qsizetype QByteArray::capacity() const { return qsizetype(d->constAllocatedCapacity()); } |
556 | |
557 | inline void QByteArray::reserve(qsizetype asize) |
558 | { |
559 | if (d->needsDetach() || asize > capacity() - d->freeSpaceAtBegin()) |
560 | reallocData(alloc: qMax(a: size(), b: asize), option: QArrayData::KeepSize); |
561 | if (d->constAllocatedCapacity()) |
562 | d->setFlag(Data::CapacityReserved); |
563 | } |
564 | |
565 | inline void QByteArray::squeeze() |
566 | { |
567 | if (!d.isMutable()) |
568 | return; |
569 | if (d->needsDetach() || size() < capacity()) |
570 | reallocData(alloc: size(), option: QArrayData::KeepSize); |
571 | if (d->constAllocatedCapacity()) |
572 | d->clearFlag(f: Data::CapacityReserved); |
573 | } |
574 | |
575 | inline char &QByteArray::operator[](qsizetype i) |
576 | { Q_ASSERT(i >= 0 && i < size()); return data()[i]; } |
577 | inline char &QByteArray::front() { return operator[](i: 0); } |
578 | inline char &QByteArray::back() { return operator[](i: size() - 1); } |
579 | inline QByteArray &QByteArray::append(qsizetype n, char ch) |
580 | { return insert(i: size(), count: n, c: ch); } |
581 | inline QByteArray &QByteArray::prepend(qsizetype n, char ch) |
582 | { return insert(i: 0, count: n, c: ch); } |
583 | inline bool QByteArray::contains(char c) const |
584 | { return indexOf(c) != -1; } |
585 | inline bool QByteArray::contains(QByteArrayView bv) const |
586 | { return indexOf(bv) != -1; } |
587 | inline int QByteArray::compare(QByteArrayView a, Qt::CaseSensitivity cs) const noexcept |
588 | { |
589 | return cs == Qt::CaseSensitive ? QtPrivate::compareMemory(lhs: *this, rhs: a) : |
590 | qstrnicmp(data(), size(), a.data(), a.size()); |
591 | } |
592 | #if !defined(QT_USE_QSTRINGBUILDER) |
593 | inline QByteArray operator+(const QByteArray &a1, const QByteArray &a2) |
594 | { return QByteArray(a1) += a2; } |
595 | inline QByteArray operator+(QByteArray &&lhs, const QByteArray &rhs) |
596 | { return std::move(lhs += rhs); } |
597 | inline QByteArray operator+(const QByteArray &a1, const char *a2) |
598 | { return QByteArray(a1) += a2; } |
599 | inline QByteArray operator+(QByteArray &&lhs, const char *rhs) |
600 | { return std::move(lhs += rhs); } |
601 | inline QByteArray operator+(const QByteArray &a1, char a2) |
602 | { return QByteArray(a1) += a2; } |
603 | inline QByteArray operator+(QByteArray &&lhs, char rhs) |
604 | { return std::move(lhs += rhs); } |
605 | inline QByteArray operator+(const char *a1, const QByteArray &a2) |
606 | { return QByteArray(a1) += a2; } |
607 | inline QByteArray operator+(char a1, const QByteArray &a2) |
608 | { return QByteArray(&a1, 1) += a2; } |
609 | #endif // QT_USE_QSTRINGBUILDER |
610 | |
611 | inline QByteArray &QByteArray::setNum(short n, int base) |
612 | { return setNum(qlonglong(n), base); } |
613 | inline QByteArray &QByteArray::setNum(ushort n, int base) |
614 | { return setNum(qulonglong(n), base); } |
615 | inline QByteArray &QByteArray::setNum(int n, int base) |
616 | { return setNum(qlonglong(n), base); } |
617 | inline QByteArray &QByteArray::setNum(uint n, int base) |
618 | { return setNum(qulonglong(n), base); } |
619 | inline QByteArray &QByteArray::setNum(long n, int base) |
620 | { return setNum(qlonglong(n), base); } |
621 | inline QByteArray &QByteArray::setNum(ulong n, int base) |
622 | { return setNum(qulonglong(n), base); } |
623 | inline QByteArray &QByteArray::setNum(float n, char format, int precision) |
624 | { return setNum(double(n), format, precision); } |
625 | |
626 | #if QT_CORE_INLINE_IMPL_SINCE(6, 4) |
627 | bool QByteArray::isNull() const noexcept |
628 | { |
629 | return d->isNull(); |
630 | } |
631 | #endif |
632 | |
633 | #if !defined(QT_NO_DATASTREAM) || defined(QT_BOOTSTRAPPED) |
634 | Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QByteArray &); |
635 | Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QByteArray &); |
636 | #endif |
637 | |
638 | #ifndef QT_NO_COMPRESS |
639 | Q_CORE_EXPORT QByteArray qCompress(const uchar* data, qsizetype nbytes, int compressionLevel = -1); |
640 | Q_CORE_EXPORT QByteArray qUncompress(const uchar* data, qsizetype nbytes); |
641 | inline QByteArray qCompress(const QByteArray& data, int compressionLevel = -1) |
642 | { return qCompress(data: reinterpret_cast<const uchar *>(data.constData()), nbytes: data.size(), compressionLevel); } |
643 | inline QByteArray qUncompress(const QByteArray& data) |
644 | { return qUncompress(data: reinterpret_cast<const uchar*>(data.constData()), nbytes: data.size()); } |
645 | #endif |
646 | |
647 | Q_DECLARE_SHARED(QByteArray) |
648 | |
649 | class QByteArray::FromBase64Result |
650 | { |
651 | public: |
652 | QByteArray decoded; |
653 | QByteArray::Base64DecodingStatus decodingStatus; |
654 | |
655 | void swap(QByteArray::FromBase64Result &other) noexcept |
656 | { |
657 | decoded.swap(other&: other.decoded); |
658 | std::swap(a&: decodingStatus, b&: other.decodingStatus); |
659 | } |
660 | |
661 | explicit operator bool() const noexcept { return decodingStatus == QByteArray::Base64DecodingStatus::Ok; } |
662 | |
663 | #if defined(Q_COMPILER_REF_QUALIFIERS) && !defined(Q_QDOC) |
664 | QByteArray &operator*() & noexcept { return decoded; } |
665 | const QByteArray &operator*() const & noexcept { return decoded; } |
666 | QByteArray &&operator*() && noexcept { return std::move(decoded); } |
667 | #else |
668 | QByteArray &operator*() noexcept { return decoded; } |
669 | const QByteArray &operator*() const noexcept { return decoded; } |
670 | #endif |
671 | |
672 | friend inline bool operator==(const QByteArray::FromBase64Result &lhs, const QByteArray::FromBase64Result &rhs) noexcept |
673 | { |
674 | if (lhs.decodingStatus != rhs.decodingStatus) |
675 | return false; |
676 | |
677 | if (lhs.decodingStatus == QByteArray::Base64DecodingStatus::Ok && lhs.decoded != rhs.decoded) |
678 | return false; |
679 | |
680 | return true; |
681 | } |
682 | |
683 | friend inline bool operator!=(const QByteArray::FromBase64Result &lhs, const QByteArray::FromBase64Result &rhs) noexcept |
684 | { |
685 | return !(lhs == rhs); |
686 | } |
687 | }; |
688 | |
689 | Q_DECLARE_SHARED(QByteArray::FromBase64Result) |
690 | |
691 | |
692 | Q_CORE_EXPORT Q_DECL_PURE_FUNCTION size_t qHash(const QByteArray::FromBase64Result &key, size_t seed = 0) noexcept; |
693 | |
694 | template <typename T> |
695 | qsizetype erase(QByteArray &ba, const T &t) |
696 | { |
697 | return ba.removeIf_helper([&t](const auto &e) { return t == e; }); |
698 | } |
699 | |
700 | template <typename Predicate> |
701 | qsizetype erase_if(QByteArray &ba, Predicate pred) |
702 | { |
703 | return ba.removeIf_helper(pred); |
704 | } |
705 | |
706 | // |
707 | // QByteArrayView members that require QByteArray: |
708 | // |
709 | QByteArray QByteArrayView::toByteArray() const |
710 | { |
711 | return QByteArray(data(), size()); |
712 | } |
713 | |
714 | namespace Qt { |
715 | inline namespace Literals { |
716 | inline namespace StringLiterals { |
717 | |
718 | inline QByteArray operator""_ba (const char *str, size_t size) noexcept |
719 | { |
720 | return QByteArray(QByteArrayData(nullptr, const_cast<char *>(str), qsizetype(size))); |
721 | } |
722 | |
723 | } // StringLiterals |
724 | } // Literals |
725 | } // Qt |
726 | |
727 | inline namespace QtLiterals { |
728 | #if QT_DEPRECATED_SINCE(6, 8) |
729 | |
730 | QT_DEPRECATED_VERSION_X_6_8("Use _ba from Qt::StringLiterals namespace instead." ) |
731 | inline QByteArray operator""_qba (const char *str, size_t size) noexcept |
732 | { |
733 | return Qt::StringLiterals::operator""_ba (str, size); |
734 | } |
735 | |
736 | #endif // QT_DEPRECATED_SINCE(6, 8) |
737 | } // QtLiterals |
738 | |
739 | QT_END_NAMESPACE |
740 | |
741 | #endif // QBYTEARRAY_H |
742 | |