From fb591c73661055bf48a44b4742a2399ae8dc684a Mon Sep 17 00:00:00 2001
From: Marc Mutz <marc.mutz@kdab.com>
Date: Wed, 24 Feb 2016 14:56:36 +0100
Subject: [PATCH] QStringBuilder: don't allocate memory in convertFromAscii()

Use new QUtf8::convertToUnicode(QChar*, const char*, int)
overload instead of QString::fromUtf8(). The QUtf8 overload
allocates no memory, and is therefore marked as nothrow.

Using this function in convertFromAscii() allows to mark
this function nothrow, too.

All functions of QAbstractConcatenable can now be marked as
nothrow.

Since QUtf8::convertToUnicode() does not deal with lengths
of -1, insert a strlen() call when the len == -1 ASCII fast
path fails due to non-ASCII chars.

Saves 1.1KiB in text size on optimized GCC 5.3 Linux AMD64
builds of QtCore (other libraries are compiled without
exceptions, so this change should not have an effect on
those).

Change-Id: I7333e35844033831eae2a04203d13d9792c5d460
Reviewed-by: Olivier Goffart (Woboq GmbH) <ogoffart@woboq.com>
---
 src/corelib/tools/qstring.cpp        | 2 +-
 src/corelib/tools/qstringbuilder.cpp | 8 ++++----
 src/corelib/tools/qstringbuilder.h   | 6 +++---
 3 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index 24d43dad888..943d8efe1de 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ -10609,7 +10609,7 @@ QString QString::toHtmlEscaped() const
 /*!
     \internal
  */
-void QAbstractConcatenable::appendLatin1To(const char *a, int len, QChar *out)
+void QAbstractConcatenable::appendLatin1To(const char *a, int len, QChar *out) Q_DECL_NOTHROW
 {
     qt_from_latin1(reinterpret_cast<ushort *>(out), a, uint(len));
 }
diff --git a/src/corelib/tools/qstringbuilder.cpp b/src/corelib/tools/qstringbuilder.cpp
index eba939a413e..85babbd698d 100644
--- a/src/corelib/tools/qstringbuilder.cpp
+++ b/src/corelib/tools/qstringbuilder.cpp
@@ -39,6 +39,7 @@
 
 #include "qstringbuilder.h"
 #include <QtCore/qtextcodec.h>
+#include <private/qutfcodec_p.h>
 
 QT_BEGIN_NAMESPACE
 
@@ -107,7 +108,7 @@ QT_BEGIN_NAMESPACE
 /*!
     \internal
  */
-void QAbstractConcatenable::convertFromAscii(const char *a, int len, QChar *&out)
+void QAbstractConcatenable::convertFromAscii(const char *a, int len, QChar *&out) Q_DECL_NOTHROW
 {
     if (len == -1) {
         if (!a)
@@ -116,6 +117,7 @@ void QAbstractConcatenable::convertFromAscii(const char *a, int len, QChar *&out
             *out++ = QLatin1Char(*a++);
         if (!*a)
             return;
+        len = int(strlen(a));
     } else {
         int i;
         for (i = 0; i < len && uchar(a[i]) < 0x80U; ++i)
@@ -127,9 +129,7 @@ void QAbstractConcatenable::convertFromAscii(const char *a, int len, QChar *&out
     }
 
     // we need to complement with UTF-8 appending
-    QString tmp = QString::fromUtf8(a, len);
-    memcpy(out, reinterpret_cast<const char *>(tmp.constData()), sizeof(QChar) * tmp.size());
-    out += tmp.size();
+    out = QUtf8::convertToUnicode(out, a, len);
 }
 
 QT_END_NAMESPACE
diff --git a/src/corelib/tools/qstringbuilder.h b/src/corelib/tools/qstringbuilder.h
index faf9eb4b4d8..8ce98cbd71e 100644
--- a/src/corelib/tools/qstringbuilder.h
+++ b/src/corelib/tools/qstringbuilder.h
@@ -58,12 +58,12 @@ QT_BEGIN_NAMESPACE
 struct Q_CORE_EXPORT QAbstractConcatenable
 {
 protected:
-    static void convertFromAscii(const char *a, int len, QChar *&out);
-    static inline void convertFromAscii(char a, QChar *&out)
+    static void convertFromAscii(const char *a, int len, QChar *&out) Q_DECL_NOTHROW;
+    static inline void convertFromAscii(char a, QChar *&out) Q_DECL_NOTHROW
     {
         *out++ = QLatin1Char(a);
     }
-    static void appendLatin1To(const char *a, int len, QChar *out);
+    static void appendLatin1To(const char *a, int len, QChar *out) Q_DECL_NOTHROW;
 };
 
 template <typename T> struct QConcatenable {};
-- 
GitLab