diff options
Diffstat (limited to 'src/corelib/tools/qvarlengtharray.h')
-rw-r--r-- | src/corelib/tools/qvarlengtharray.h | 130 |
1 files changed, 59 insertions, 71 deletions
diff --git a/src/corelib/tools/qvarlengtharray.h b/src/corelib/tools/qvarlengtharray.h index 2957bf0eb4..f0e4342e06 100644 --- a/src/corelib/tools/qvarlengtharray.h +++ b/src/corelib/tools/qvarlengtharray.h @@ -1,12 +1,11 @@ /**************************************************************************** ** -** Copyright (C) 2021 The Qt Company Ltd. +** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:COMM$ -** +** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the @@ -15,25 +14,26 @@ ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** -** $QT_END_LICENSE$ -** -** -** -** -** -** -** -** -** -** -** -** -** -** -** -** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** +** $QT_END_LICENSE$ ** ****************************************************************************/ @@ -49,6 +49,7 @@ #include <algorithm> #include <initializer_list> #include <iterator> +#include <memory> #include <new> #include <string.h> #include <stdlib.h> @@ -152,19 +153,18 @@ public: if (s == a) { // i.e. s != 0 T copy(t); realloc(s, s<<1); - const int idx = s++; - new (ptr + idx) T(std::move(copy)); + new (end()) T(std::move(copy)); } else { - const int idx = s++; - new (ptr + idx) T(t); + new (end()) T(t); } + ++s; } void append(T &&t) { if (s == a) realloc(s, s << 1); - const int idx = s++; - new (ptr + idx) T(std::move(t)); + new (end()) T(std::move(t)); + ++s; } void append(const T *buf, int size); @@ -238,6 +238,20 @@ public: private: void realloc(int size, int alloc); + void resize_impl(int newSize, const T &t) + { + const auto increment = newSize - size(); + if (increment > 0 && QtPrivate::q_points_into_range(&t, cbegin(), cend())) { + resize_impl(newSize, T(t)); + return; + } + realloc(qMin(size(), newSize), qMax(newSize, capacity())); + + if (increment > 0) + std::uninitialized_fill_n(end(), increment, t); + s = newSize; + } + int a; // capacity int s; // size T *ptr; // data @@ -476,57 +490,25 @@ Q_OUTOFLINE_TEMPLATE typename QVarLengthArray<T, Prealloc>::iterator QVarLengthA { Q_ASSERT_X(isValidIterator(before), "QVarLengthArray::insert", "The specified const_iterator argument 'before' is invalid"); - int offset = int(before - ptr); - reserve(s + 1); - if (!QTypeInfo<T>::isRelocatable) { - T *b = ptr + offset; - T *i = ptr + s; - T *j = i + 1; - // The new end-element needs to be constructed, the rest must be move assigned - if (i != b) { - new (--j) T(std::move(*--i)); - while (i != b) - *--j = std::move(*--i); - *b = std::move(t); - } else { - new (b) T(std::move(t)); - } - } else { - T *b = ptr + offset; - memmove(static_cast<void *>(b + 1), static_cast<const void *>(b), (s - offset) * sizeof(T)); - new (b) T(std::move(t)); - } - s += 1; - return ptr + offset; + const int offset = int(before - ptr); + append(std::move(t)); + const auto b = begin() + offset; + const auto e = end(); + QtPrivate::q_rotate(b, e - 1, e); + return b; } template <class T, int Prealloc> -Q_OUTOFLINE_TEMPLATE typename QVarLengthArray<T, Prealloc>::iterator QVarLengthArray<T, Prealloc>::insert(const_iterator before, size_type n, const T &t) +Q_OUTOFLINE_TEMPLATE typename QVarLengthArray<T, Prealloc>::iterator QVarLengthArray<T, Prealloc>::insert(const_iterator before, int n, const T &t) { Q_ASSERT_X(isValidIterator(before), "QVarLengthArray::insert", "The specified const_iterator argument 'before' is invalid"); - int offset = int(before - ptr); - if (n != 0) { - resize(s + n); - const T copy(t); - if (!QTypeInfoQuery<T>::isRelocatable) { - T *b = ptr + offset; - T *j = ptr + s; - T *i = j - n; - while (i != b) - *--j = *--i; - i = b + n; - while (i != b) - *--i = copy; - } else { - T *b = ptr + offset; - T *i = b + n; - memmove(static_cast<void *>(i), static_cast<const void *>(b), (s - offset - n) * sizeof(T)); - while (i != b) - new (--i) T(copy); - } - } - return ptr + offset; + const int offset = int(before - cbegin()); + resize_impl(size() + n, t); + const auto b = begin() + offset; + const auto e = end(); + QtPrivate::q_rotate(b, e - n, e); + return b; } template <class T, int Prealloc> @@ -538,6 +520,12 @@ Q_OUTOFLINE_TEMPLATE typename QVarLengthArray<T, Prealloc>::iterator QVarLengthA int f = int(abegin - ptr); int l = int(aend - ptr); int n = l - f; + + if (n == 0) // avoid UB in std::copy() below + return data() + f; + + Q_ASSERT(n > 0); // aend must be reachable from abegin + if (QTypeInfo<T>::isComplex) { std::copy(ptr + l, ptr + s, QT_MAKE_CHECKED_ARRAY_ITERATOR(ptr + f, s - f)); T *i = ptr + s; |