Qt 4.8
qbytearray.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qbytearray.h"
43 #include "qbytearraymatcher.h"
44 #include "qtools_p.h"
45 #include "qstring.h"
46 #include "qlist.h"
47 #include "qlocale.h"
48 #include "qlocale_p.h"
49 #include "qscopedpointer.h"
50 #include <qdatastream.h>
51 
52 #ifndef QT_NO_COMPRESS
53 #include <zlib.h>
54 #endif
55 #include <ctype.h>
56 #include <limits.h>
57 #include <string.h>
58 #include <stdlib.h>
59 
60 #define IS_RAW_DATA(d) ((d)->data != (d)->array)
61 
63 
64 
65 int qFindByteArray(
66  const char *haystack0, int haystackLen, int from,
67  const char *needle0, int needleLen);
68 
69 
70 int qAllocMore(int alloc, int extra)
71 {
72  Q_ASSERT(alloc >= 0 && extra >= 0);
73  Q_ASSERT_X(alloc < (1 << 30) - extra, "qAllocMore", "Requested size is too large!");
74 
75  if (alloc == 0 && extra == 0)
76  return 0;
77  const int page = 1 << 12;
78  int nalloc;
79  alloc += extra;
80  if (alloc < 1<<6) {
81  nalloc = (1<<3) + ((alloc >>3) << 3);
82  } else {
83  // don't do anything if the loop will overflow signed int.
84  if (alloc >= INT_MAX/2)
85  return INT_MAX;
86  nalloc = (alloc < page) ? 1 << 3 : page;
87  while (nalloc < alloc) {
88  if (nalloc <= 0)
89  return INT_MAX;
90  nalloc *= 2;
91  }
92  }
93  return nalloc - extra;
94 }
95 
96 /*****************************************************************************
97  Safe and portable C string functions; extensions to standard string.h
98  *****************************************************************************/
99 
114 char *qstrdup(const char *src)
115 {
116  if (!src)
117  return 0;
118  char *dst = new char[strlen(src) + 1];
119  return qstrcpy(dst, src);
120 }
121 
137 char *qstrcpy(char *dst, const char *src)
138 {
139  if (!src)
140  return 0;
141 #if defined(_MSC_VER) && _MSC_VER >= 1400
142  int len = qstrlen(src);
143  // This is actually not secure!!! It will be fixed
144  // properly in a later release!
145  if (len >= 0 && strcpy_s(dst, len+1, src) == 0)
146  return dst;
147  return 0;
148 #else
149  return strcpy(dst, src);
150 #endif
151 }
152 
175 char *qstrncpy(char *dst, const char *src, uint len)
176 {
177  if (!src || !dst)
178  return 0;
179 #if defined(_MSC_VER) && _MSC_VER >= 1400
180  strncpy_s(dst, len, src, len-1);
181 #else
182  strncpy(dst, src, len);
183 #endif
184  if (len > 0)
185  dst[len-1] = '\0';
186  return dst;
187 }
188 
231 int qstrcmp(const char *str1, const char *str2)
232 {
233  return (str1 && str2) ? strcmp(str1, str2)
234  : (str1 ? 1 : (str2 ? -1 : 0));
235 }
236 
279 int qstricmp(const char *str1, const char *str2)
280 {
281  register const uchar *s1 = reinterpret_cast<const uchar *>(str1);
282  register const uchar *s2 = reinterpret_cast<const uchar *>(str2);
283  int res;
284  uchar c;
285  if (!s1 || !s2)
286  return s1 ? 1 : (s2 ? -1 : 0);
287  for (; !(res = (c = QChar::toLower((ushort)*s1)) - QChar::toLower((ushort)*s2)); s1++, s2++)
288  if (!c) // strings are equal
289  break;
290  return res;
291 }
292 
316 int qstrnicmp(const char *str1, const char *str2, uint len)
317 {
318  register const uchar *s1 = reinterpret_cast<const uchar *>(str1);
319  register const uchar *s2 = reinterpret_cast<const uchar *>(str2);
320  int res;
321  uchar c;
322  if (!s1 || !s2)
323  return s1 ? 1 : (s2 ? -1 : 0);
324  for (; len--; s1++, s2++) {
325  if ((res = (c = QChar::toLower((ushort)*s1)) - QChar::toLower((ushort)*s2)))
326  return res;
327  if (!c) // strings are equal
328  break;
329  }
330  return 0;
331 }
332 
336 int qstrcmp(const QByteArray &str1, const char *str2)
337 {
338  if (!str2)
339  return str1.isEmpty() ? 0 : +1;
340 
341  const char *str1data = str1.constData();
342  const char *str1end = str1data + str1.length();
343  for ( ; str1data < str1end && *str2; ++str1data, ++str2) {
344  register int diff = int(uchar(*str1data)) - uchar(*str2);
345  if (diff)
346  // found a difference
347  return diff;
348  }
349 
350  // Why did we stop?
351  if (*str2 != '\0')
352  // not the null, so we stopped because str1 is shorter
353  return -1;
354  if (str1data < str1end)
355  // we haven't reached the end, so str1 must be longer
356  return +1;
357  return 0;
358 }
359 
363 int qstrcmp(const QByteArray &str1, const QByteArray &str2)
364 {
365  int l1 = str1.length();
366  int l2 = str2.length();
367  int ret = memcmp(str1, str2, qMin(l1, l2));
368  if (ret != 0)
369  return ret;
370 
371  // they matched qMin(l1, l2) bytes
372  // so the longer one is lexically after the shorter one
373  return l1 - l2;
374 }
375 
376 // the CRC table below is created by the following piece of code
377 #if 0
378 static void createCRC16Table() // build CRC16 lookup table
379 {
380  register unsigned int i;
381  register unsigned int j;
382  unsigned short crc_tbl[16];
383  unsigned int v0, v1, v2, v3;
384  for (i = 0; i < 16; i++) {
385  v0 = i & 1;
386  v1 = (i >> 1) & 1;
387  v2 = (i >> 2) & 1;
388  v3 = (i >> 3) & 1;
389  j = 0;
390 #undef SET_BIT
391 #define SET_BIT(x, b, v) (x) |= (v) << (b)
392  SET_BIT(j, 0, v0);
393  SET_BIT(j, 7, v0);
394  SET_BIT(j, 12, v0);
395  SET_BIT(j, 1, v1);
396  SET_BIT(j, 8, v1);
397  SET_BIT(j, 13, v1);
398  SET_BIT(j, 2, v2);
399  SET_BIT(j, 9, v2);
400  SET_BIT(j, 14, v2);
401  SET_BIT(j, 3, v3);
402  SET_BIT(j, 10, v3);
403  SET_BIT(j, 15, v3);
404  crc_tbl[i] = j;
405  }
406  printf("static const quint16 crc_tbl[16] = {\n");
407  for (int i = 0; i < 16; i +=4)
408  printf(" 0x%04x, 0x%04x, 0x%04x, 0x%04x,\n", crc_tbl[i], crc_tbl[i+1], crc_tbl[i+2], crc_tbl[i+3]);
409  printf("};\n");
410 }
411 #endif
412 
413 static const quint16 crc_tbl[16] = {
414  0x0000, 0x1081, 0x2102, 0x3183,
415  0x4204, 0x5285, 0x6306, 0x7387,
416  0x8408, 0x9489, 0xa50a, 0xb58b,
417  0xc60c, 0xd68d, 0xe70e, 0xf78f
418 };
419 
434 quint16 qChecksum(const char *data, uint len)
435 {
436  register quint16 crc = 0xffff;
437  uchar c;
438  const uchar *p = reinterpret_cast<const uchar *>(data);
439  while (len--) {
440  c = *p++;
441  crc = ((crc >> 4) & 0x0fff) ^ crc_tbl[((crc ^ c) & 15)];
442  c >>= 4;
443  crc = ((crc >> 4) & 0x0fff) ^ crc_tbl[((crc ^ c) & 15)];
444  }
445  return ~crc & 0xffff;
446 }
447 
482 #ifndef QT_NO_COMPRESS
483 QByteArray qCompress(const uchar* data, int nbytes, int compressionLevel)
484 {
485  if (nbytes == 0) {
486  return QByteArray(4, '\0');
487  }
488  if (!data) {
489  qWarning("qCompress: Data is null");
490  return QByteArray();
491  }
492  if (compressionLevel < -1 || compressionLevel > 9)
493  compressionLevel = -1;
494 
495  ulong len = nbytes + nbytes / 100 + 13;
496  QByteArray bazip;
497  int res;
498  do {
499  bazip.resize(len + 4);
500  res = ::compress2((uchar*)bazip.data()+4, &len, (uchar*)data, nbytes, compressionLevel);
501 
502  switch (res) {
503  case Z_OK:
504  bazip.resize(len + 4);
505  bazip[0] = (nbytes & 0xff000000) >> 24;
506  bazip[1] = (nbytes & 0x00ff0000) >> 16;
507  bazip[2] = (nbytes & 0x0000ff00) >> 8;
508  bazip[3] = (nbytes & 0x000000ff);
509  break;
510  case Z_MEM_ERROR:
511  qWarning("qCompress: Z_MEM_ERROR: Not enough memory");
512  bazip.resize(0);
513  break;
514  case Z_BUF_ERROR:
515  len *= 2;
516  break;
517  }
518  } while (res == Z_BUF_ERROR);
519 
520  return bazip;
521 }
522 #endif
523 
561 #ifndef QT_NO_COMPRESS
562 QByteArray qUncompress(const uchar* data, int nbytes)
563 {
564  if (!data) {
565  qWarning("qUncompress: Data is null");
566  return QByteArray();
567  }
568  if (nbytes <= 4) {
569  if (nbytes < 4 || (data[0]!=0 || data[1]!=0 || data[2]!=0 || data[3]!=0))
570  qWarning("qUncompress: Input data is corrupted");
571  return QByteArray();
572  }
573  ulong expectedSize = (data[0] << 24) | (data[1] << 16) |
574  (data[2] << 8) | (data[3] );
575  ulong len = qMax(expectedSize, 1ul);
577 
578  forever {
579  ulong alloc = len;
580  if (len >= ulong(1 << 31) - sizeof(QByteArray::Data)) {
581  //QByteArray does not support that huge size anyway.
582  qWarning("qUncompress: Input data is corrupted");
583  return QByteArray();
584  }
585  QByteArray::Data *p = static_cast<QByteArray::Data *>(qRealloc(d.data(), sizeof(QByteArray::Data) + alloc));
586  if (!p) {
587  // we are not allowed to crash here when compiling with QT_NO_EXCEPTIONS
588  qWarning("qUncompress: could not allocate enough memory to uncompress data");
589  return QByteArray();
590  }
591  d.take(); // realloc was successful
592  d.reset(p);
593 
594  int res = ::uncompress((uchar*)d->array, &len,
595  (uchar*)data+4, nbytes-4);
596 
597  switch (res) {
598  case Z_OK:
599  if (len != alloc) {
600  if (len >= ulong(1 << 31) - sizeof(QByteArray::Data)) {
601  //QByteArray does not support that huge size anyway.
602  qWarning("qUncompress: Input data is corrupted");
603  return QByteArray();
604  }
605  QByteArray::Data *p = static_cast<QByteArray::Data *>(qRealloc(d.data(), sizeof(QByteArray::Data) + len));
606  if (!p) {
607  // we are not allowed to crash here when compiling with QT_NO_EXCEPTIONS
608  qWarning("qUncompress: could not allocate enough memory to uncompress data");
609  return QByteArray();
610  }
611  d.take(); // realloc was successful
612  d.reset(p);
613  }
614  d->ref = 1;
615  d->alloc = d->size = len;
616  d->data = d->array;
617  d->array[len] = 0;
618 
619  return QByteArray(d.take(), 0, 0);
620 
621  case Z_MEM_ERROR:
622  qWarning("qUncompress: Z_MEM_ERROR: Not enough memory");
623  return QByteArray();
624 
625  case Z_BUF_ERROR:
626  len *= 2;
627  continue;
628 
629  case Z_DATA_ERROR:
630  qWarning("qUncompress: Z_DATA_ERROR: Input data is corrupted");
631  return QByteArray();
632  }
633  }
634 }
635 #endif
636 
637 static inline bool qIsUpper(char c)
638 {
639  return c >= 'A' && c <= 'Z';
640 }
641 
642 static inline char qToLower(char c)
643 {
644  if (c >= 'A' && c <= 'Z')
645  return c - 'A' + 'a';
646  else
647  return c;
648 }
649 
651  0, 0, shared_null.array, {0} };
653  0, 0, shared_empty.array, {0} };
654 
936 {
937  other.d->ref.ref();
938  if (!d->ref.deref())
939  qFree(d);
940  d = other.d;
941  return *this;
942 }
943 
944 
955 {
956  Data *x;
957  if (!str) {
958  x = &shared_null;
959  } else if (!*str) {
960  x = &shared_empty;
961  } else {
962  int len = qstrlen(str);
963  if (d->ref != 1 || len > d->alloc || (len < d->size && len < d->alloc >> 1))
964  realloc(len);
965  x = d;
966  memcpy(x->data, str, len + 1); // include null terminator
967  x->size = len;
968  }
969  x->ref.ref();
970  if (!d->ref.deref())
971  qFree(d);
972  d = x;
973  return *this;
974 }
975 
1271 {
1272  if (pos < d->size)
1273  resize(pos);
1274 }
1275 
1289 void QByteArray::chop(int n)
1290 {
1291  if (n > 0)
1292  resize(d->size - n);
1293 }
1294 
1295 
1401 QByteArray::QByteArray(const char *str)
1402 {
1403  if (!str) {
1404  d = &shared_null;
1405  } else if (!*str) {
1406  d = &shared_empty;
1407  } else {
1408  int len = qstrlen(str);
1409  d = static_cast<Data *>(qMalloc(sizeof(Data)+len));
1410  Q_CHECK_PTR(d);
1411  d->ref = 0;;
1412  d->alloc = d->size = len;
1413  d->data = d->array;
1414  memcpy(d->array, str, len+1); // include null terminator
1415  }
1416  d->ref.ref();
1417 }
1418 
1431 {
1432  if (!data) {
1433  d = &shared_null;
1434  } else if (size <= 0) {
1435  d = &shared_empty;
1436  } else {
1437  d = static_cast<Data *>(qMalloc(sizeof(Data) + size));
1438  Q_CHECK_PTR(d);
1439  d->ref = 0;
1440  d->alloc = d->size = size;
1441  d->data = d->array;
1442  memcpy(d->array, data, size);
1443  d->array[size] = '\0';
1444  }
1445  d->ref.ref();
1446 }
1447 
1456 {
1457  if (size <= 0) {
1458  d = &shared_null;
1459  } else {
1460  d = static_cast<Data *>(qMalloc(sizeof(Data)+size));
1461  Q_CHECK_PTR(d);
1462  d->ref = 0;
1463  d->alloc = d->size = size;
1464  d->data = d->array;
1465  d->array[size] = '\0';
1466  memset(d->array, ch, size);
1467  }
1468  d->ref.ref();
1469 }
1470 
1481 {
1482  if (size <= 0) {
1483  d = &shared_empty;
1484  } else {
1485  d = static_cast<Data *>(qMalloc(sizeof(Data)+size));
1486  Q_CHECK_PTR(d);
1487  d->ref = 0;
1488  d->alloc = d->size = size;
1489  d->data = d->array;
1490  d->array[size] = '\0';
1491  }
1492  d->ref.ref();
1493 }
1494 
1509 {
1510  if (size <= 0) {
1511  Data *x = &shared_empty;
1512  x->ref.ref();
1513  if (!d->ref.deref())
1514  qFree(d);
1515  d = x;
1516  } else if (d == &shared_null) {
1517  //
1518  // Optimize the idiom:
1519  // QByteArray a;
1520  // a.resize(sz);
1521  // ...
1522  // which is used in place of the Qt 3 idiom:
1523  // QByteArray a(sz);
1524  //
1525  Data *x = static_cast<Data *>(qMalloc(sizeof(Data)+size));
1526  Q_CHECK_PTR(x);
1527  x->ref = 1;
1528  x->alloc = x->size = size;
1529  x->data = x->array;
1530  x->array[size] = '\0';
1531  (void) d->ref.deref(); // cannot be 0, x points to shared_null
1532  d = x;
1533  } else {
1534  if (d->ref != 1 || size > d->alloc || (size < d->size && size < d->alloc >> 1))
1535  realloc(qAllocMore(size, sizeof(Data)));
1536  if (d->alloc >= size) {
1537  d->size = size;
1538  if (d->data == d->array) {
1539  d->array[size] = '\0';
1540  }
1541  }
1542  }
1543 }
1544 
1557 {
1558  resize(size < 0 ? d->size : size);
1559  if (d->size)
1560  memset(d->data, ch, d->size);
1561  return *this;
1562 }
1563 
1564 void QByteArray::realloc(int alloc)
1565 {
1566  if (d->ref != 1 || d->data != d->array) {
1567  Data *x = static_cast<Data *>(qMalloc(sizeof(Data) + alloc));
1568  Q_CHECK_PTR(x);
1569  x->size = qMin(alloc, d->size);
1570  ::memcpy(x->array, d->data, x->size);
1571  x->array[x->size] = '\0';
1572  x->ref = 1;
1573  x->alloc = alloc;
1574  x->data = x->array;
1575  if (!d->ref.deref())
1576  qFree(d);
1577  d = x;
1578  } else {
1579  Data *x = static_cast<Data *>(qRealloc(d, sizeof(Data) + alloc));
1580  Q_CHECK_PTR(x);
1581  x->alloc = alloc;
1582  x->data = x->array;
1583  d = x;
1584  }
1585 }
1586 
1588 {
1589  resize(qMax(i + 1, d->size));
1590 }
1591 
1605 {
1606  // is this fromRawData?
1607  if (d->data == d->array)
1608  return *this; // no, then we're sure we're zero terminated
1609 
1610  QByteArray copy(*this);
1611  copy.detach();
1612  return copy;
1613 }
1614 
1637 {
1638  if ((d == &shared_null || d == &shared_empty) && !IS_RAW_DATA(ba.d)) {
1639  *this = ba;
1640  } else if (ba.d != &shared_null) {
1641  QByteArray tmp = *this;
1642  *this = ba;
1643  append(tmp);
1644  }
1645  return *this;
1646 }
1647 
1658 {
1659  return prepend(str, qstrlen(str));
1660 }
1661 
1672 QByteArray &QByteArray::prepend(const char *str, int len)
1673 {
1674  if (str) {
1675  if (d->ref != 1 || d->size + len > d->alloc)
1676  realloc(qAllocMore(d->size + len, sizeof(Data)));
1677  memmove(d->data+len, d->data, d->size);
1678  memcpy(d->data, str, len);
1679  d->size += len;
1680  d->data[d->size] = '\0';
1681  }
1682  return *this;
1683 }
1684 
1695 {
1696  if (d->ref != 1 || d->size + 1 > d->alloc)
1697  realloc(qAllocMore(d->size + 1, sizeof(Data)));
1698  memmove(d->data+1, d->data, d->size);
1699  d->data[0] = ch;
1700  ++d->size;
1701  d->data[d->size] = '\0';
1702  return *this;
1703 }
1704 
1730 {
1731  if ((d == &shared_null || d == &shared_empty) && !IS_RAW_DATA(ba.d)) {
1732  *this = ba;
1733  } else if (ba.d != &shared_null) {
1734  if (d->ref != 1 || d->size + ba.d->size > d->alloc)
1735  realloc(qAllocMore(d->size + ba.d->size, sizeof(Data)));
1736  memcpy(d->data + d->size, ba.d->data, ba.d->size);
1737  d->size += ba.d->size;
1738  d->data[d->size] = '\0';
1739  }
1740  return *this;
1741 }
1742 
1768 {
1769  if (str) {
1770  int len = qstrlen(str);
1771  if (d->ref != 1 || d->size + len > d->alloc)
1772  realloc(qAllocMore(d->size + len, sizeof(Data)));
1773  memcpy(d->data + d->size, str, len + 1); // include null terminator
1774  d->size += len;
1775  }
1776  return *this;
1777 }
1778 
1794 QByteArray &QByteArray::append(const char *str, int len)
1795 {
1796  if (len < 0)
1797  len = qstrlen(str);
1798  if (str && len) {
1799  if (d->ref != 1 || d->size + len > d->alloc)
1800  realloc(qAllocMore(d->size + len, sizeof(Data)));
1801  memcpy(d->data + d->size, str, len); // include null terminator
1802  d->size += len;
1803  d->data[d->size] = '\0';
1804  }
1805  return *this;
1806 }
1807 
1818 {
1819  if (d->ref != 1 || d->size + 1 > d->alloc)
1820  realloc(qAllocMore(d->size + 1, sizeof(Data)));
1821  d->data[d->size++] = ch;
1822  d->data[d->size] = '\0';
1823  return *this;
1824 }
1825 
1835  int pos, const char *arr, int len)
1836 {
1837  Q_ASSERT(pos >= 0);
1838 
1839  if (pos < 0 || len <= 0 || arr == 0)
1840  return *ba;
1841 
1842  int oldsize = ba->size();
1843  ba->resize(qMax(pos, oldsize) + len);
1844  char *dst = ba->data();
1845  if (pos > oldsize)
1846  ::memset(dst + oldsize, 0x20, pos - oldsize);
1847  else
1848  ::memmove(dst + pos + len, dst + pos, oldsize - pos);
1849  memcpy(dst + pos, arr, len);
1850  return *ba;
1851 }
1852 
1864 {
1865  QByteArray copy(ba);
1866  return qbytearray_insert(this, i, copy.d->data, copy.d->size);
1867 }
1868 
1901 QByteArray &QByteArray::insert(int i, const char *str)
1902 {
1903  return qbytearray_insert(this, i, str, qstrlen(str));
1904 }
1905 
1920 QByteArray &QByteArray::insert(int i, const char *str, int len)
1921 {
1922  return qbytearray_insert(this, i, str, len);
1923 }
1924 
1937 {
1938  return qbytearray_insert(this, i, &ch, 1);
1939 }
1940 
1955 QByteArray &QByteArray::remove(int pos, int len)
1956 {
1957  if (len <= 0 || pos >= d->size || pos < 0)
1958  return *this;
1959  detach();
1960  if (pos + len >= d->size) {
1961  resize(pos);
1962  } else {
1963  memmove(d->data + pos, d->data + pos + len, d->size - pos - len);
1964  resize(d->size - len);
1965  }
1966  return *this;
1967 }
1968 
1979 QByteArray &QByteArray::replace(int pos, int len, const QByteArray &after)
1980 {
1981  if (len == after.d->size && (pos + len <= d->size)) {
1982  detach();
1983  memmove(d->data + pos, after.d->data, len*sizeof(char));
1984  return *this;
1985  } else {
1986  QByteArray copy(after);
1987  // ### optimize me
1988  remove(pos, len);
1989  return insert(pos, copy);
1990  }
1991 }
1992 
2002 QByteArray &QByteArray::replace(int pos, int len, const char *after)
2003 {
2004  return replace(pos,len,after,qstrlen(after));
2005 }
2006 
2016 QByteArray &QByteArray::replace(int pos, int len, const char *after, int alen)
2017 {
2018  if (len == alen && (pos + len <= d->size)) {
2019  detach();
2020  memcpy(d->data + pos, after, len*sizeof(char));
2021  return *this;
2022  } else {
2023  remove(pos, len);
2024  return qbytearray_insert(this, pos, after, alen);
2025  }
2026 }
2027 
2028 // ### optimize all other replace method, by offering
2029 // QByteArray::replace(const char *before, int blen, const char *after, int alen)
2030 
2045 {
2046  if (isNull() || before.d == after.d)
2047  return *this;
2048 
2049  QByteArray aft = after;
2050  if (after.d == d)
2051  aft.detach();
2052 
2053  return replace(before.constData(), before.size(), aft.constData(), aft.size());
2054 }
2055 
2064 QByteArray &QByteArray::replace(const char *c, const QByteArray &after)
2065 {
2066  QByteArray aft = after;
2067  if (after.d == d)
2068  aft.detach();
2069 
2070  return replace(c, qstrlen(c), aft.constData(), aft.size());
2071 }
2072 
2082 QByteArray &QByteArray::replace(const char *before, int bsize, const char *after, int asize)
2083 {
2084  if (isNull() || (before == after && bsize == asize))
2085  return *this;
2086 
2087  // protect against before or after being part of this
2088  const char *a = after;
2089  const char *b = before;
2090  if (after >= d->data && after < d->data + d->size) {
2091  char *copy = (char *)malloc(asize);
2092  Q_CHECK_PTR(copy);
2093  memcpy(copy, after, asize);
2094  a = copy;
2095  }
2096  if (before >= d->data && before < d->data + d->size) {
2097  char *copy = (char *)malloc(bsize);
2098  Q_CHECK_PTR(copy);
2099  memcpy(copy, before, bsize);
2100  b = copy;
2101  }
2102 
2103  QByteArrayMatcher matcher(before, bsize);
2104  int index = 0;
2105  int len = d->size;
2106  char *d = data();
2107 
2108  if (bsize == asize) {
2109  if (bsize) {
2110  while ((index = matcher.indexIn(*this, index)) != -1) {
2111  memcpy(d + index, after, asize);
2112  index += bsize;
2113  }
2114  }
2115  } else if (asize < bsize) {
2116  uint to = 0;
2117  uint movestart = 0;
2118  uint num = 0;
2119  while ((index = matcher.indexIn(*this, index)) != -1) {
2120  if (num) {
2121  int msize = index - movestart;
2122  if (msize > 0) {
2123  memmove(d + to, d + movestart, msize);
2124  to += msize;
2125  }
2126  } else {
2127  to = index;
2128  }
2129  if (asize) {
2130  memcpy(d + to, after, asize);
2131  to += asize;
2132  }
2133  index += bsize;
2134  movestart = index;
2135  num++;
2136  }
2137  if (num) {
2138  int msize = len - movestart;
2139  if (msize > 0)
2140  memmove(d + to, d + movestart, msize);
2141  resize(len - num*(bsize-asize));
2142  }
2143  } else {
2144  // the most complex case. We don't want to lose performance by doing repeated
2145  // copies and reallocs of the string.
2146  while (index != -1) {
2147  uint indices[4096];
2148  uint pos = 0;
2149  while(pos < 4095) {
2150  index = matcher.indexIn(*this, index);
2151  if (index == -1)
2152  break;
2153  indices[pos++] = index;
2154  index += bsize;
2155  // avoid infinite loop
2156  if (!bsize)
2157  index++;
2158  }
2159  if (!pos)
2160  break;
2161 
2162  // we have a table of replacement positions, use them for fast replacing
2163  int adjust = pos*(asize-bsize);
2164  // index has to be adjusted in case we get back into the loop above.
2165  if (index != -1)
2166  index += adjust;
2167  int newlen = len + adjust;
2168  int moveend = len;
2169  if (newlen > len) {
2170  resize(newlen);
2171  len = newlen;
2172  }
2173  d = this->d->data;
2174 
2175  while(pos) {
2176  pos--;
2177  int movestart = indices[pos] + bsize;
2178  int insertstart = indices[pos] + pos*(asize-bsize);
2179  int moveto = insertstart + asize;
2180  memmove(d + moveto, d + movestart, (moveend - movestart));
2181  if (asize)
2182  memcpy(d + insertstart, after, asize);
2183  moveend = movestart - bsize;
2184  }
2185  }
2186  }
2187 
2188  if (a != after)
2189  ::free((char *)a);
2190  if (b != before)
2191  ::free((char *)b);
2192 
2193 
2194  return *this;
2195 }
2196 
2197 
2247 QByteArray &QByteArray::replace(char before, const QByteArray &after)
2248 {
2249  char b[2] = { before, '\0' };
2250  QByteArray cb = fromRawData(b, 1);
2251  return replace(cb, after);
2252 }
2253 
2288 QByteArray &QByteArray::replace(char before, char after)
2289 {
2290  if (d->size) {
2291  char *i = data();
2292  char *e = i + d->size;
2293  for (; i != e; ++i)
2294  if (*i == before)
2295  * i = after;
2296  }
2297  return *this;
2298 }
2299 
2308 {
2309  QList<QByteArray> list;
2310  int start = 0;
2311  int end;
2312  while ((end = indexOf(sep, start)) != -1) {
2313  list.append(mid(start, end - start));
2314  start = end + 1;
2315  }
2316  list.append(mid(start));
2317  return list;
2318 }
2319 
2338 {
2339  if (d->size == 0)
2340  return *this;
2341 
2342  if (times <= 1) {
2343  if (times == 1)
2344  return *this;
2345  return QByteArray();
2346  }
2347 
2348  const int resultSize = times * d->size;
2349 
2350  QByteArray result;
2351  result.reserve(resultSize);
2352  if (result.d->alloc != resultSize)
2353  return QByteArray(); // not enough memory
2354 
2355  memcpy(result.d->data, d->data, d->size);
2356 
2357  int sizeSoFar = d->size;
2358  char *end = result.d->data + sizeSoFar;
2359 
2360  const int halfResultSize = resultSize >> 1;
2361  while (sizeSoFar <= halfResultSize) {
2362  memcpy(end, result.d->data, sizeSoFar);
2363  end += sizeSoFar;
2364  sizeSoFar <<= 1;
2365  }
2366  memcpy(end, result.d->data, resultSize - sizeSoFar);
2367  result.d->data[resultSize] = '\0';
2368  result.d->size = resultSize;
2369  return result;
2370 }
2371 
2372 #define REHASH(a) \
2373  if (ol_minus_1 < sizeof(uint) * CHAR_BIT) \
2374  hashHaystack -= (a) << ol_minus_1; \
2375  hashHaystack <<= 1
2376 
2388 int QByteArray::indexOf(const QByteArray &ba, int from) const
2389 {
2390  const int ol = ba.d->size;
2391  if (ol == 0)
2392  return from;
2393  if (ol == 1)
2394  return indexOf(*ba.d->data, from);
2395 
2396  const int l = d->size;
2397  if (from > d->size || ol + from > l)
2398  return -1;
2399 
2400  return qFindByteArray(d->data, d->size, from, ba.d->data, ol);
2401 }
2402 
2430 int QByteArray::indexOf(const char *c, int from) const
2431 {
2432  const int ol = qstrlen(c);
2433  if (ol == 1)
2434  return indexOf(*c, from);
2435 
2436  const int l = d->size;
2437  if (from > d->size || ol + from > l)
2438  return -1;
2439  if (ol == 0)
2440  return from;
2441 
2442  return qFindByteArray(d->data, d->size, from, c, ol);
2443 }
2444 
2461 int QByteArray::indexOf(char ch, int from) const
2462 {
2463  if (from < 0)
2464  from = qMax(from + d->size, 0);
2465  if (from < d->size) {
2466  const char *n = d->data + from - 1;
2467  const char *e = d->data + d->size;
2468  while (++n != e)
2469  if (*n == ch)
2470  return n - d->data;
2471  }
2472  return -1;
2473 }
2474 
2475 
2476 static int lastIndexOfHelper(const char *haystack, int l, const char *needle, int ol, int from)
2477 {
2478  int delta = l - ol;
2479  if (from < 0)
2480  from = delta;
2481  if (from < 0 || from > l)
2482  return -1;
2483  if (from > delta)
2484  from = delta;
2485 
2486  const char *end = haystack;
2487  haystack += from;
2488  const uint ol_minus_1 = ol - 1;
2489  const char *n = needle + ol_minus_1;
2490  const char *h = haystack + ol_minus_1;
2491  uint hashNeedle = 0, hashHaystack = 0;
2492  int idx;
2493  for (idx = 0; idx < ol; ++idx) {
2494  hashNeedle = ((hashNeedle<<1) + *(n-idx));
2495  hashHaystack = ((hashHaystack<<1) + *(h-idx));
2496  }
2497  hashHaystack -= *haystack;
2498  while (haystack >= end) {
2499  hashHaystack += *haystack;
2500  if (hashHaystack == hashNeedle && memcmp(needle, haystack, ol) == 0)
2501  return haystack - end;
2502  --haystack;
2503  REHASH(*(haystack + ol));
2504  }
2505  return -1;
2506 
2507 }
2508 
2526 int QByteArray::lastIndexOf(const QByteArray &ba, int from) const
2527 {
2528  const int ol = ba.d->size;
2529  if (ol == 1)
2530  return lastIndexOf(*ba.d->data, from);
2531 
2532  return lastIndexOfHelper(d->data, d->size, ba.d->data, ol, from);
2533 }
2534 
2563 int QByteArray::lastIndexOf(const char *str, int from) const
2564 {
2565  const int ol = qstrlen(str);
2566  if (ol == 1)
2567  return lastIndexOf(*str, from);
2568 
2569  return lastIndexOfHelper(d->data, d->size, str, ol, from);
2570 }
2571 
2589 int QByteArray::lastIndexOf(char ch, int from) const
2590 {
2591  if (from < 0)
2592  from += d->size;
2593  else if (from > d->size)
2594  from = d->size-1;
2595  if (from >= 0) {
2596  const char *b = d->data;
2597  const char *n = d->data + from + 1;
2598  while (n-- != b)
2599  if (*n == ch)
2600  return n - b;
2601  }
2602  return -1;
2603 }
2604 
2612 int QByteArray::count(const QByteArray &ba) const
2613 {
2614  int num = 0;
2615  int i = -1;
2616  if (d->size > 500 && ba.d->size > 5) {
2617  QByteArrayMatcher matcher(ba);
2618  while ((i = matcher.indexIn(*this, i + 1)) != -1)
2619  ++num;
2620  } else {
2621  while ((i = indexOf(ba, i + 1)) != -1)
2622  ++num;
2623  }
2624  return num;
2625 }
2626 
2637 int QByteArray::count(const char *str) const
2638 {
2639  return count(fromRawData(str, qstrlen(str)));
2640 }
2641 
2654 int QByteArray::count(char ch) const
2655 {
2656  int num = 0;
2657  const char *i = d->data + d->size;
2658  const char *b = d->data;
2659  while (i != b)
2660  if (*--i == ch)
2661  ++num;
2662  return num;
2663 }
2664 
2684 bool QByteArray::startsWith(const QByteArray &ba) const
2685 {
2686  if (d == ba.d || ba.d->size == 0)
2687  return true;
2688  if (d->size < ba.d->size)
2689  return false;
2690  return memcmp(d->data, ba.d->data, ba.d->size) == 0;
2691 }
2692 
2701 bool QByteArray::startsWith(const char *str) const
2702 {
2703  if (!str || !*str)
2704  return true;
2705  int len = qstrlen(str);
2706  if (d->size < len)
2707  return false;
2708  return qstrncmp(d->data, str, len) == 0;
2709 }
2710 
2719 bool QByteArray::startsWith(char ch) const
2720 {
2721  if (d->size == 0)
2722  return false;
2723  return d->data[0] == ch;
2724 }
2725 
2735 bool QByteArray::endsWith(const QByteArray &ba) const
2736 {
2737  if (d == ba.d || ba.d->size == 0)
2738  return true;
2739  if (d->size < ba.d->size)
2740  return false;
2741  return memcmp(d->data + d->size - ba.d->size, ba.d->data, ba.d->size) == 0;
2742 }
2743 
2752 bool QByteArray::endsWith(const char *str) const
2753 {
2754  if (!str || !*str)
2755  return true;
2756  int len = qstrlen(str);
2757  if (d->size < len)
2758  return false;
2759  return qstrncmp(d->data + d->size - len, str, len) == 0;
2760 }
2761 
2770 bool QByteArray::endsWith(char ch) const
2771 {
2772  if (d->size == 0)
2773  return false;
2774  return d->data[d->size - 1] == ch;
2775 }
2776 
2791 {
2792  if (len >= d->size)
2793  return *this;
2794  if (len < 0)
2795  len = 0;
2796  return QByteArray(d->data, len);
2797 }
2798 
2813 {
2814  if (len >= d->size)
2815  return *this;
2816  if (len < 0)
2817  len = 0;
2818  return QByteArray(d->data + d->size - len, len);
2819 }
2820 
2835 QByteArray QByteArray::mid(int pos, int len) const
2836 {
2837  if (d == &shared_null || d == &shared_empty || pos >= d->size)
2838  return QByteArray();
2839  if (len < 0)
2840  len = d->size - pos;
2841  if (pos < 0) {
2842  len += pos;
2843  pos = 0;
2844  }
2845  if (len + pos > d->size)
2846  len = d->size - pos;
2847  if (pos == 0 && len == d->size)
2848  return *this;
2849  return QByteArray(d->data + pos, len);
2850 }
2851 
2862 {
2863  QByteArray s(*this);
2864  register uchar *p = reinterpret_cast<uchar *>(s.data());
2865  if (p) {
2866  while (*p) {
2867  *p = QChar::toLower((ushort)*p);
2868  p++;
2869  }
2870  }
2871  return s;
2872 }
2873 
2885 {
2886  QByteArray s(*this);
2887  register uchar *p = reinterpret_cast<uchar *>(s.data());
2888  if (p) {
2889  while (*p) {
2890  *p = QChar::toUpper((ushort)*p);
2891  p++;
2892  }
2893  }
2894  return s;
2895 }
2896 
2908 {
2909  if (!d->ref.deref())
2910  qFree(d);
2911  d = &shared_null;
2912  d->ref.ref();
2913 }
2914 
2915 #if !defined(QT_NO_DATASTREAM) || (defined(QT_BOOTSTRAPPED) && !defined(QT_BUILD_QMAKE))
2916 
2929 {
2930  if (ba.isNull() && out.version() >= 6) {
2931  out << (quint32)0xffffffff;
2932  return out;
2933  }
2934  return out.writeBytes(ba, ba.size());
2935 }
2936 
2949 {
2950  ba.clear();
2951  quint32 len;
2952  in >> len;
2953  if (len == 0xffffffff)
2954  return in;
2955 
2956  const quint32 Step = 1024 * 1024;
2957  quint32 allocated = 0;
2958 
2959  do {
2960  int blockSize = qMin(Step, len - allocated);
2961  ba.resize(allocated + blockSize);
2962  if (in.readRawData(ba.data() + allocated, blockSize) != blockSize) {
2963  ba.clear();
2965  return in;
2966  }
2967  allocated += blockSize;
2968  } while (allocated < len);
2969 
2970  return in;
2971 }
2972 #endif // QT_NO_DATASTREAM
2973 
3349 {
3350  if (d->size == 0)
3351  return *this;
3352  QByteArray result(d->size, Qt::Uninitialized);
3353  const char *from = d->data;
3354  const char *fromend = from + d->size;
3355  int outc=0;
3356  char *to = result.d->data;
3357  for (;;) {
3358  while (from!=fromend && isspace(uchar(*from)))
3359  from++;
3360  while (from!=fromend && !isspace(uchar(*from)))
3361  to[outc++] = *from++;
3362  if (from!=fromend)
3363  to[outc++] = ' ';
3364  else
3365  break;
3366  }
3367  if (outc > 0 && to[outc-1] == ' ')
3368  outc--;
3369  result.resize(outc);
3370  return result;
3371 }
3372 
3389 {
3390  if (d->size == 0)
3391  return *this;
3392  const char *s = d->data;
3393  if (!isspace(uchar(*s)) && !isspace(uchar(s[d->size-1])))
3394  return *this;
3395  int start = 0;
3396  int end = d->size - 1;
3397  while (start<=end && isspace(uchar(s[start]))) // skip white space from start
3398  start++;
3399  if (start <= end) { // only white space
3400  while (end && isspace(uchar(s[end]))) // skip white space from end
3401  end--;
3402  }
3403  int l = end - start + 1;
3404  if (l <= 0) {
3405  shared_empty.ref.ref();
3406  return QByteArray(&shared_empty, 0, 0);
3407  }
3408  return QByteArray(s+start, l);
3409 }
3410 
3430 {
3431  QByteArray result;
3432  int len = d->size;
3433  int padlen = width - len;
3434  if (padlen > 0) {
3435  result.resize(len+padlen);
3436  if (len)
3437  memcpy(result.d->data, d->data, len);
3438  memset(result.d->data+len, fill, padlen);
3439  } else {
3440  if (truncate)
3441  result = left(width);
3442  else
3443  result = *this;
3444  }
3445  return result;
3446 }
3447 
3467 {
3468  QByteArray result;
3469  int len = d->size;
3470  int padlen = width - len;
3471  if (padlen > 0) {
3472  result.resize(len+padlen);
3473  if (len)
3474  memcpy(result.d->data+padlen, data(), len);
3475  memset(result.d->data, fill, padlen);
3476  } else {
3477  if (truncate)
3478  result = left(width);
3479  else
3480  result = *this;
3481  }
3482  return result;
3483 }
3484 
3485 bool QByteArray::isNull() const { return d == &shared_null; }
3486 
3487 
3509 {
3510 #if defined(QT_CHECK_RANGE)
3511  if (base != 0 && (base < 2 || base > 36)) {
3512  qWarning("QByteArray::toLongLong: Invalid base %d", base);
3513  base = 10;
3514  }
3515 #endif
3516 
3518 }
3519 
3542 {
3543 #if defined(QT_CHECK_RANGE)
3544  if (base != 0 && (base < 2 || base > 36)) {
3545  qWarning("QByteArray::toULongLong: Invalid base %d", base);
3546  base = 10;
3547  }
3548 #endif
3549 
3551 }
3552 
3553 
3576 int QByteArray::toInt(bool *ok, int base) const
3577 {
3578  qlonglong v = toLongLong(ok, base);
3579  if (v < INT_MIN || v > INT_MAX) {
3580  if (ok)
3581  *ok = false;
3582  v = 0;
3583  }
3584  return int(v);
3585 }
3586 
3607 uint QByteArray::toUInt(bool *ok, int base) const
3608 {
3609  qulonglong v = toULongLong(ok, base);
3610  if (v > UINT_MAX) {
3611  if (ok)
3612  *ok = false;
3613  v = 0;
3614  }
3615  return uint(v);
3616 }
3617 
3641 long QByteArray::toLong(bool *ok, int base) const
3642 {
3643  qlonglong v = toLongLong(ok, base);
3644  if (v < LONG_MIN || v > LONG_MAX) {
3645  if (ok)
3646  *ok = false;
3647  v = 0;
3648  }
3649  return long(v);
3650 }
3651 
3673 ulong QByteArray::toULong(bool *ok, int base) const
3674 {
3675  qulonglong v = toULongLong(ok, base);
3676  if (v > ULONG_MAX) {
3677  if (ok)
3678  *ok = false;
3679  v = 0;
3680  }
3681  return ulong(v);
3682 }
3683 
3704 short QByteArray::toShort(bool *ok, int base) const
3705 {
3706  qlonglong v = toLongLong(ok, base);
3707  if (v < SHRT_MIN || v > SHRT_MAX) {
3708  if (ok)
3709  *ok = false;
3710  v = 0;
3711  }
3712  return short(v);
3713 }
3714 
3735 ushort QByteArray::toUShort(bool *ok, int base) const
3736 {
3737  qulonglong v = toULongLong(ok, base);
3738  if (v > USHRT_MAX) {
3739  if (ok)
3740  *ok = false;
3741  v = 0;
3742  }
3743  return ushort(v);
3744 }
3745 
3746 
3763 double QByteArray::toDouble(bool *ok) const
3764 {
3766 }
3767 
3782 float QByteArray::toFloat(bool *ok) const
3783 {
3784  return float(toDouble(ok));
3785 }
3786 
3797 {
3798  const char alphabet[] = "ABCDEFGH" "IJKLMNOP" "QRSTUVWX" "YZabcdef"
3799  "ghijklmn" "opqrstuv" "wxyz0123" "456789+/";
3800  const char padchar = '=';
3801  int padlen = 0;
3802 
3803  QByteArray tmp((d->size * 4) / 3 + 3, Qt::Uninitialized);
3804 
3805  int i = 0;
3806  char *out = tmp.data();
3807  while (i < d->size) {
3808  int chunk = 0;
3809  chunk |= int(uchar(d->data[i++])) << 16;
3810  if (i == d->size) {
3811  padlen = 2;
3812  } else {
3813  chunk |= int(uchar(d->data[i++])) << 8;
3814  if (i == d->size) padlen = 1;
3815  else chunk |= int(uchar(d->data[i++]));
3816  }
3817 
3818  int j = (chunk & 0x00fc0000) >> 18;
3819  int k = (chunk & 0x0003f000) >> 12;
3820  int l = (chunk & 0x00000fc0) >> 6;
3821  int m = (chunk & 0x0000003f);
3822  *out++ = alphabet[j];
3823  *out++ = alphabet[k];
3824  if (padlen > 1) *out++ = padchar;
3825  else *out++ = alphabet[l];
3826  if (padlen > 0) *out++ = padchar;
3827  else *out++ = alphabet[m];
3828  }
3829 
3830  tmp.truncate(out - tmp.data());
3831  return tmp;
3832 }
3833 
3881 {
3882 #if defined(QT_CHECK_RANGE)
3883  if (base < 2 || base > 36) {
3884  qWarning("QByteArray::setNum: Invalid base %d", base);
3885  base = 10;
3886  }
3887 #endif
3888  QLocale locale(QLocale::C);
3889  *this = locale.d()->longLongToString(n, -1, base).toLatin1();
3890  return *this;
3891 }
3892 
3900 {
3901 #if defined(QT_CHECK_RANGE)
3902  if (base < 2 || base > 36) {
3903  qWarning("QByteArray::setNum: Invalid base %d", base);
3904  base = 10;
3905  }
3906 #endif
3907  QLocale locale(QLocale::C);
3908  *this = locale.d()->unsLongLongToString(n, -1, base).toLatin1();
3909  return *this;
3910 }
3911 
3943 QByteArray &QByteArray::setNum(double n, char f, int prec)
3944 {
3946  uint flags = 0;
3947 
3948  if (qIsUpper(f))
3950  f = qToLower(f);
3951 
3952  switch (f) {
3953  case 'f':
3955  break;
3956  case 'e':
3958  break;
3959  case 'g':
3961  break;
3962  default:
3963 #if defined(QT_CHECK_RANGE)
3964  qWarning("QByteArray::setNum: Invalid format char '%c'", f);
3965 #endif
3966  break;
3967  }
3968 
3969  QLocale locale(QLocale::C);
3970  *this = locale.d()->doubleToString(n, prec, form, -1, flags).toLatin1();
3971  return *this;
3972 }
3973 
4005 {
4006  QByteArray s;
4007  s.setNum(n, base);
4008  return s;
4009 }
4010 
4017 {
4018  QByteArray s;
4019  s.setNum(n, base);
4020  return s;
4021 }
4022 
4029 {
4030  QByteArray s;
4031  s.setNum(n, base);
4032  return s;
4033 }
4034 
4041 {
4042  QByteArray s;
4043  s.setNum(n, base);
4044  return s;
4045 }
4046 
4079 QByteArray QByteArray::number(double n, char f, int prec)
4080 {
4081  QByteArray s;
4082  s.setNum(n, f, prec);
4083  return s;
4084 }
4085 
4122 {
4123  Data *x = static_cast<Data *>(qMalloc(sizeof(Data)));
4124  Q_CHECK_PTR(x);
4125  if (data) {
4126  x->data = const_cast<char *>(data);
4127  } else {
4128  x->data = x->array;
4129  size = 0;
4130  }
4131  x->ref = 1;
4132  x->alloc = x->size = size;
4133  *x->array = '\0';
4134  return QByteArray(x, 0, 0);
4135 }
4136 
4155 {
4156  if (d->ref != 1 || d->alloc) {
4157  *this = fromRawData(data, size);
4158  } else {
4159  if (data) {
4160  d->data = const_cast<char *>(data);
4161  } else {
4162  d->data = d->array;
4163  size = 0;
4164  }
4165  d->alloc = d->size = size;
4166  *d->array = '\0';
4167  }
4168  return *this;
4169 }
4170 
4185 {
4186  unsigned int buf = 0;
4187  int nbits = 0;
4188  QByteArray tmp((base64.size() * 3) / 4, Qt::Uninitialized);
4189 
4190  int offset = 0;
4191  for (int i = 0; i < base64.size(); ++i) {
4192  int ch = base64.at(i);
4193  int d;
4194 
4195  if (ch >= 'A' && ch <= 'Z')
4196  d = ch - 'A';
4197  else if (ch >= 'a' && ch <= 'z')
4198  d = ch - 'a' + 26;
4199  else if (ch >= '0' && ch <= '9')
4200  d = ch - '0' + 52;
4201  else if (ch == '+')
4202  d = 62;
4203  else if (ch == '/')
4204  d = 63;
4205  else
4206  d = -1;
4207 
4208  if (d != -1) {
4209  buf = (buf << 6) | d;
4210  nbits += 6;
4211  if (nbits >= 8) {
4212  nbits -= 8;
4213  tmp[offset++] = buf >> nbits;
4214  buf &= (1 << nbits) - 1;
4215  }
4216  }
4217  }
4218 
4219  tmp.truncate(offset);
4220  return tmp;
4221 }
4222 
4235 {
4236  QByteArray res((hexEncoded.size() + 1)/ 2, Qt::Uninitialized);
4237  uchar *result = (uchar *)res.data() + res.size();
4238 
4239  bool odd_digit = true;
4240  for (int i = hexEncoded.size() - 1; i >= 0; --i) {
4241  int ch = hexEncoded.at(i);
4242  int tmp;
4243  if (ch >= '0' && ch <= '9')
4244  tmp = ch - '0';
4245  else if (ch >= 'a' && ch <= 'f')
4246  tmp = ch - 'a' + 10;
4247  else if (ch >= 'A' && ch <= 'F')
4248  tmp = ch - 'A' + 10;
4249  else
4250  continue;
4251  if (odd_digit) {
4252  --result;
4253  *result = tmp;
4254  odd_digit = false;
4255  } else {
4256  *result |= tmp << 4;
4257  odd_digit = true;
4258  }
4259  }
4260 
4261  res.remove(0, result - (const uchar *)res.constData());
4262  return res;
4263 }
4264 
4272 {
4274  char *hexData = hex.data();
4275  const uchar *data = (const uchar *)d->data;
4276  for (int i = 0; i < d->size; ++i) {
4277  int j = (data[i] >> 4) & 0xf;
4278  if (j <= 9)
4279  hexData[i*2] = (j + '0');
4280  else
4281  hexData[i*2] = (j + 'a' - 10);
4282  j = data[i] & 0xf;
4283  if (j <= 9)
4284  hexData[i*2+1] = (j + '0');
4285  else
4286  hexData[i*2+1] = (j + 'a' - 10);
4287  }
4288  return hex;
4289 }
4290 
4291 static void q_fromPercentEncoding(QByteArray *ba, char percent)
4292 {
4293  if (ba->isEmpty())
4294  return;
4295 
4296  char *data = ba->data();
4297  const char *inputPtr = data;
4298 
4299  int i = 0;
4300  int len = ba->count();
4301  int outlen = 0;
4302  int a, b;
4303  char c;
4304  while (i < len) {
4305  c = inputPtr[i];
4306  if (c == percent && i + 2 < len) {
4307  a = inputPtr[++i];
4308  b = inputPtr[++i];
4309 
4310  if (a >= '0' && a <= '9') a -= '0';
4311  else if (a >= 'a' && a <= 'f') a = a - 'a' + 10;
4312  else if (a >= 'A' && a <= 'F') a = a - 'A' + 10;
4313 
4314  if (b >= '0' && b <= '9') b -= '0';
4315  else if (b >= 'a' && b <= 'f') b = b - 'a' + 10;
4316  else if (b >= 'A' && b <= 'F') b = b - 'A' + 10;
4317 
4318  *data++ = (char)((a << 4) | b);
4319  } else {
4320  *data++ = c;
4321  }
4322 
4323  ++i;
4324  ++outlen;
4325  }
4326 
4327  if (outlen != len)
4328  ba->truncate(outlen);
4329 }
4330 
4332 {
4333  q_fromPercentEncoding(ba, '%');
4334 }
4335 
4355 {
4356  if (input.isNull())
4357  return QByteArray(); // preserve null
4358  if (input.isEmpty())
4359  return QByteArray(input.data(), 0);
4360 
4361  QByteArray tmp = input;
4362  q_fromPercentEncoding(&tmp, percent);
4363  return tmp;
4364 }
4365 
4366 static inline bool q_strchr(const char str[], char chr)
4367 {
4368  if (!str) return false;
4369 
4370  const char *ptr = str;
4371  char c;
4372  while ((c = *ptr++))
4373  if (c == chr)
4374  return true;
4375  return false;
4376 }
4377 
4378 static inline char toHexHelper(char c)
4379 {
4380  static const char hexnumbers[] = "0123456789ABCDEF";
4381  return hexnumbers[c & 0xf];
4382 }
4383 
4384 static void q_toPercentEncoding(QByteArray *ba, const char *dontEncode, const char *alsoEncode, char percent)
4385 {
4386  if (ba->isEmpty())
4387  return;
4388 
4389  QByteArray input = *ba;
4390  int len = input.count();
4391  const char *inputData = input.constData();
4392  char *output = 0;
4393  int length = 0;
4394 
4395  for (int i = 0; i < len; ++i) {
4396  unsigned char c = *inputData++;
4397  if (((c >= 0x61 && c <= 0x7A) // ALPHA
4398  || (c >= 0x41 && c <= 0x5A) // ALPHA
4399  || (c >= 0x30 && c <= 0x39) // DIGIT
4400  || c == 0x2D // -
4401  || c == 0x2E // .
4402  || c == 0x5F // _
4403  || c == 0x7E // ~
4404  || q_strchr(dontEncode, c))
4405  && !q_strchr(alsoEncode, c)) {
4406  if (output)
4407  output[length] = c;
4408  ++length;
4409  } else {
4410  if (!output) {
4411  // detach now
4412  ba->resize(len*3); // worst case
4413  output = ba->data();
4414  }
4415  output[length++] = percent;
4416  output[length++] = toHexHelper((c & 0xf0) >> 4);
4417  output[length++] = toHexHelper(c & 0xf);
4418  }
4419  }
4420  if (output)
4421  ba->truncate(length);
4422 }
4423 
4424 void q_toPercentEncoding(QByteArray *ba, const char *exclude, const char *include)
4425 {
4426  q_toPercentEncoding(ba, exclude, include, '%');
4427 }
4428 
4429 void q_normalizePercentEncoding(QByteArray *ba, const char *exclude)
4430 {
4431  q_fromPercentEncoding(ba, '%');
4432  q_toPercentEncoding(ba, exclude, 0, '%');
4433 }
4434 
4468  char percent) const
4469 {
4470  if (isNull())
4471  return QByteArray(); // preserve null
4472  if (isEmpty())
4473  return QByteArray(data(), 0);
4474 
4475  QByteArray include2 = include;
4476  if (percent != '%') // the default
4477  if ((percent >= 0x61 && percent <= 0x7A) // ALPHA
4478  || (percent >= 0x41 && percent <= 0x5A) // ALPHA
4479  || (percent >= 0x30 && percent <= 0x39) // DIGIT
4480  || percent == 0x2D // -
4481  || percent == 0x2E // .
4482  || percent == 0x5F // _
4483  || percent == 0x7E) // ~
4484  include2 += percent;
4485 
4486  QByteArray result = *this;
4487  q_toPercentEncoding(&result, exclude.nulTerminated().constData(), include2.nulTerminated().constData(), percent);
4488 
4489  return result;
4490 }
4491 
double d
Definition: qnumeric_p.h:62
static QByteArray fromHex(const QByteArray &hexEncoded)
Returns a decoded copy of the hex encoded array hexEncoded.
const int blockSize
void chop(int n)
Removes n bytes from the end of the byte array.
int qFindByteArray(const char *haystack0, int haystackLen, int from, const char *needle0, int needleLen)
static int lastIndexOfHelper(const char *haystack, int l, const char *needle, int ol, int from)
int qstrncmp(const char *str1, const char *str2, uint len)
Definition: qbytearray.h:101
static QByteArray & qbytearray_insert(QByteArray *ba, int pos, const char *arr, int len)
Inserts len bytes from the array arr at position pos and returns a reference the modified byte array...
void truncate(int pos)
Truncates the byte array at index position pos.
QByteArray & fill(char c, int size=-1)
Sets every byte in the byte array to character ch.
static qint64 bytearrayToLongLong(const char *num, int base, bool *ok, bool *overflow=0)
Definition: qlocale.cpp:3186
unsigned char c[8]
Definition: qnumeric_p.h:62
Q_DECL_CONSTEXPR const T & qMin(const T &a, const T &b)
Definition: qglobal.h:1215
short toShort(bool *ok=0, int base=10) const
Returns the byte array converted to a short using base base, which is 10 by default and must be betwe...
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
char * data()
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:429
QByteArray toUpper() const
Returns an uppercase copy of the byte array.
T * data() const
Returns the value of the pointer referenced by this object.
static void q_fromPercentEncoding(QByteArray *ba, char percent)
QByteArray & append(char c)
Appends the character ch to this byte array.
Data * d
Definition: qbytearray.h:386
static QByteArray fromPercentEncoding(const QByteArray &pctEncoded, char percent='%')
Returns a decoded copy of the URI/URL-style percent-encoded input.
qlonglong toLongLong(bool *ok=0, int base=10) const
Returns the byte array converted to a {long long} using base base, which is 10 by default and must be...
Q_CORE_EXPORT void qFree(void *ptr)
Definition: qmalloc.cpp:58
QByteArray rightJustified(int width, char fill=' ', bool truncate=false) const
Returns a byte array of size width that contains the fill character followed by this byte array...
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
T * take()
Returns the value of the pointer referenced by this object.
QBasicAtomicInt ref
Definition: qbytearray.h:139
QByteArray()
Constructs an empty byte array.
Definition: qbytearray.h:400
QByteArray toLower() const
Returns a lowercase copy of the byte array.
ulong toULong(bool *ok=0, int base=10) const
long toLong(bool *ok=0, int base=10) const
long ASN1_INTEGER_get ASN1_INTEGER * a
void setStatus(Status status)
Sets the status of the data stream to the status given.
Q_CORE_EXPORT void * qMalloc(size_t size)
Definition: qmalloc.cpp:53
int count() const
Same as size().
Definition: qbytearray.h:355
Q_CORE_EXPORT void * qRealloc(void *ptr, size_t size)
Definition: qmalloc.cpp:63
QByteArray & prepend(char c)
Prepends the character ch to this byte array.
static double bytearrayToDouble(const char *num, bool *ok, bool *overflow=0)
Definition: qlocale.cpp:3134
int qstrcmp(const char *str1, const char *str2)
A safe strcmp() function.
Definition: qbytearray.cpp:231
static bool q_strchr(const char str[], char chr)
QByteArray toHex() const
Returns a hex encoded copy of the byte array.
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
bool startsWith(const QByteArray &a) const
Returns true if this byte array starts with byte array ba; otherwise returns false.
#define Q_BASIC_ATOMIC_INITIALIZER(a)
Definition: qbasicatomic.h:218
static const uint base
Definition: qurl.cpp:268
QByteArray & setRawData(const char *a, uint n)
Resets the QByteArray to use the first size bytes of the data array.
Q_CORE_EXPORT QTextStream & hex(QTextStream &s)
Q_DECL_CONSTEXPR const T & qMax(const T &a, const T &b)
Definition: qglobal.h:1217
The QScopedPointer class stores a pointer to a dynamically allocated object, and deletes it upon dest...
static QString doubleToString(const QChar zero, const QChar plus, const QChar minus, const QChar exponent, const QChar group, const QChar decimal, double d, int precision, DoubleForm form, int width, unsigned flags)
Definition: qlocale.cpp:2613
static const quint16 crc_tbl[16]
Definition: qbytearray.cpp:413
QByteArray simplified() const
Returns a byte array that has whitespace removed from the start and the end, and which has each seque...
char * qstrcpy(char *dst, const char *src)
Copies all the characters up to and including the &#39;\0&#39; from src into dst and returns a pointer to dst...
Definition: qbytearray.cpp:137
QByteArray right(int len) const
Returns a byte array that contains the rightmost len bytes of this byte array.
void realloc(int alloc)
for(int ii=mo->methodOffset();ii< mo->methodCount();++ii)
unsigned char uchar
Definition: qglobal.h:994
static QString unsLongLongToString(const QChar zero, const QChar group, const QChar plus, quint64 l, int precision, int base, int width, unsigned flags)
Definition: qlocale.cpp:2870
void append(const T &t)
Inserts value at the end of the list.
Definition: qlist.h:507
quint16 qChecksum(const char *data, uint len)
Returns the CRC-16 checksum of the first len bytes of data.
Definition: qbytearray.cpp:434
QByteArray qUncompress(const QByteArray &data)
Uncompresses the data byte array and returns a new byte array with the uncompressed data...
Definition: qbytearray.h:606
static QString longLongToString(const QChar zero, const QChar group, const QChar plus, const QChar minus, qint64 l, int precision, int base, int width, unsigned flags)
Definition: qlocale.cpp:2775
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
int qAllocMore(int alloc, int extra)
Definition: qbytearray.cpp:70
int lastIndexOf(char c, int from=-1) const
Returns the index position of the last occurrence of character ch in the byte array, searching backward from index position from.
QByteArray & operator=(const QByteArray &)
Assigns other to this byte array and returns a reference to this byte array.
Definition: qbytearray.cpp:935
int readRawData(char *, int len)
Reads at most len bytes from the stream into s and returns the number of bytes read.
QDataStream & writeBytes(const char *, uint len)
Writes the length specifier len and the buffer s to the stream and returns a reference to the stream...
QByteArray trimmed() const
Returns a byte array that has whitespace removed from the start and the end.
static QByteArray fromRawData(const char *, int size)
Constructs a QByteArray that uses the first size bytes of the data array.
QByteArray leftJustified(int width, char fill=' ', bool truncate=false) const
Returns a byte array of size width that contains this byte array padded by the fill character...
qulonglong toULongLong(bool *ok=0, int base=10) const
Returns the byte array converted to an {unsigned long long} using base base, which is 10 by default a...
unsigned short quint16
Definition: qglobal.h:936
Q_CORE_EXPORT void qWarning(const char *,...)
static const char * data(const QByteArray &arr)
unsigned int uint
Definition: qglobal.h:996
static Bigint * diff(Bigint *a, Bigint *b)
void expand(int i)
static quint64 bytearrayToUnsLongLong(const char *num, int base, bool *ok)
Definition: qlocale.cpp:3228
QChar toUpper() const
Returns the uppercase equivalent if the character is lowercase or titlecase; otherwise returns the ch...
Definition: qchar.cpp:1287
void q_normalizePercentEncoding(QByteArray *ba, const char *exclude)
const T * ptr(const T &t)
float toFloat(bool *ok=0) const
Returns the byte array converted to a float value.
QByteArray toLatin1() const Q_REQUIRED_RESULT
Returns a Latin-1 representation of the string as a QByteArray.
Definition: qstring.cpp:3993
QByteArray left(int len) const
Returns a byte array that contains the leftmost len bytes of this byte array.
int qstrnicmp(const char *str1, const char *str2, uint len)
A safe strnicmp() function.
Definition: qbytearray.cpp:316
unsigned long ulong
Definition: qglobal.h:997
The QByteArrayMatcher class holds a sequence of bytes that can be quickly matched in a byte array...
bool isNull() const
Returns true if this byte array is null; otherwise returns false.
QByteArray mid(int index, int len=-1) const
Returns a byte array containing len bytes from this byte array, starting at position pos...
int indexOf(char c, int from=0) const
Returns the index position of the first occurrence of the character ch in the byte array...
int qstricmp(const char *str1, const char *str2)
A safe stricmp() function.
Definition: qbytearray.cpp:279
QDataStream & operator<<(QDataStream &out, const QByteArray &ba)
Writes byte array ba to the stream out and returns a reference to the stream.
QByteArray nulTerminated() const
Return a QByteArray that is sure to be NUL-terminated.
void reset(T *other=0)
Deletes the existing object it is pointing to if any, and sets its pointer to other.
int version() const
Returns the version number of the data serialization format.
Definition: qdatastream.h:212
int length() const
Same as size().
Definition: qbytearray.h:356
const char * constData() const
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:433
static QByteArray fromBase64(const QByteArray &base64)
Returns a decoded copy of the Base64 array base64.
QList< QByteArray > split(char sep) const
Splits the byte array into subarrays wherever sep occurs, and returns the list of those arrays...
#define Q_CHECK_PTR(p)
Definition: qglobal.h:1853
#define Q_ASSERT_X(cond, where, what)
Definition: qglobal.h:1837
const QLocalePrivate * d() const
Definition: qlocale.cpp:761
static void q_toPercentEncoding(QByteArray *ba, const char *dontEncode, const char *alsoEncode, char percent)
int count(char c) const
Returns the number of occurrences of character ch in the byte array.
static bool qIsUpper(char c)
Definition: qbytearray.cpp:637
unsigned short ushort
Definition: qglobal.h:995
QByteArray repeated(int times) const
Returns a copy of this byte array repeated the specified number of times.
int toInt(bool *ok=0, int base=10) const
Returns the byte array converted to an int using base base, which is 10 by default and must be betwee...
uint qstrlen(const char *str)
Definition: qbytearray.h:79
void resize(int size)
Sets the size of the byte array to size bytes.
QByteArray & setNum(short, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: qbytearray.h:584
unsigned int quint32
Definition: qglobal.h:938
#define IS_RAW_DATA(d)
Definition: qbytearray.cpp:60
QFactoryLoader * l
QByteArray toBase64() const
Returns a copy of the byte array, encoded as Base64.
int size() const
Returns the number of bytes in this byte array.
Definition: qbytearray.h:402
static Data shared_null
Definition: qbytearray.h:384
quint16 index
static char toHexHelper(char c)
QByteArray toPercentEncoding(const QByteArray &exclude=QByteArray(), const QByteArray &include=QByteArray(), char percent='%') const
Returns a URI/URL-style percent-encoded copy of this byte array.
char * qstrdup(const char *src)
Returns a duplicate string.
Definition: qbytearray.cpp:114
QDataStream & operator>>(QDataStream &in, QByteArray &ba)
Reads a byte array into ba from the stream in and returns a reference to the stream.
QByteArray & replace(int index, int len, const char *s)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Initialization
Definition: qnamespace.h:1729
bool isEmpty() const
Returns true if the byte array has size 0; otherwise returns false.
Definition: qbytearray.h:421
The QDataStream class provides serialization of binary data to a QIODevice.
Definition: qdatastream.h:71
quint64 qulonglong
Definition: qglobal.h:952
QByteArray qCompress(const uchar *data, int nbytes, int compressionLevel)
Compresses the first nbytes of data and returns the compressed data in a new byte array...
Definition: qbytearray.cpp:483
double toDouble(bool *ok=0) const
Returns the byte array converted to a double value.
#define REHASH(a)
char at(int i) const
Returns the character at index position i in the byte array.
Definition: qbytearray.h:413
void reserve(int size)
Attempts to allocate memory for at least size bytes.
Definition: qbytearray.h:449
char * qstrncpy(char *dst, const char *src, uint len)
A safe strncpy() function.
Definition: qbytearray.cpp:175
uint toUInt(bool *ok=0, int base=10) const
Returns the byte array converted to an {unsigned int} using base base, which is 10 by default and mus...
qint64 qlonglong
Definition: qglobal.h:951
void detach()
Definition: qbytearray.h:435
iterator end()
Definition: qbytearray.h:499
QChar toLower() const
Returns the lowercase equivalent if the character is uppercase or titlecase; otherwise returns the ch...
Definition: qchar.cpp:1239
static QByteArray number(int, int base=10)
Returns a byte array containing the string equivalent of the number n to base base (10 by default)...
#define INT_MAX
static Data shared_empty
Definition: qbytearray.h:385
QByteArray & remove(int index, int len)
Removes len bytes from the array, starting at index position pos, and returns a reference to the arra...
int indexIn(const QByteArray &ba, int from=0) const
Searches the byte array ba, from byte position from (default 0, i.e.
void clear()
Clears the contents of the byte array and makes it empty.
ushort toUShort(bool *ok=0, int base=10) const
Returns the byte array converted to an {unsigned short} using base base, which is 10 by default and m...
bool endsWith(const QByteArray &a) const
Returns true if this byte array ends with byte array ba; otherwise returns false. ...
static char qToLower(char c)
Definition: qbytearray.cpp:642
QByteArray & insert(int i, char c)
Inserts character ch at index position i in the byte array.
#define forever
This macro is provided for convenience for writing infinite loops.
Definition: qglobal.h:2452