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