Refactor array data operations
Replaced copyAppend implementations with insert(this->end()) where possible. This forced an update of the preconditions in insert Unified moveAppend between generic and movable operations Change-Id: I388c14436e32152ebb969bdd94753ed5452c1b7c Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
2584998c66
commit
01a03a02f9
@ -93,32 +93,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void copyAppend(const T *b, const T *e)
|
void copyAppend(const T *b, const T *e)
|
||||||
{
|
{ insert(this->end(), b, e); }
|
||||||
Q_ASSERT(this->isMutable() || b == e);
|
|
||||||
Q_ASSERT(!this->isShared() || b == e);
|
|
||||||
Q_ASSERT(b <= e);
|
|
||||||
Q_ASSERT(size_t(e - b) <= this->allocatedCapacity() - this->size);
|
|
||||||
|
|
||||||
::memcpy(static_cast<void *>(this->end()), static_cast<const void *>(b),
|
|
||||||
(e - b) * sizeof(T));
|
|
||||||
this->size += e - b;
|
|
||||||
}
|
|
||||||
|
|
||||||
void moveAppend(T *b, T *e)
|
void moveAppend(T *b, T *e)
|
||||||
{ copyAppend(b, e); }
|
{ copyAppend(b, e); }
|
||||||
|
|
||||||
void copyAppend(size_t n, parameter_type t)
|
void copyAppend(size_t n, parameter_type t)
|
||||||
{
|
{ insert(this->end(), n, t); }
|
||||||
Q_ASSERT(this->isMutable() || n == 0);
|
|
||||||
Q_ASSERT(!this->isShared() || n == 0);
|
|
||||||
Q_ASSERT(n <= uint(this->allocatedCapacity() - this->size));
|
|
||||||
|
|
||||||
T *iter = this->end();
|
|
||||||
const T *const end = iter + n;
|
|
||||||
for (; iter != end; ++iter)
|
|
||||||
*iter = t;
|
|
||||||
this->size += int(n);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename ...Args>
|
template <typename ...Args>
|
||||||
void emplaceBack(Args&&... args) { this->emplace(this->end(), T(std::forward<Args>(args)...)); }
|
void emplaceBack(Args&&... args) { this->emplace(this->end(), T(std::forward<Args>(args)...)); }
|
||||||
@ -143,11 +124,11 @@ public:
|
|||||||
|
|
||||||
void insert(T *where, const T *b, const T *e)
|
void insert(T *where, const T *b, const T *e)
|
||||||
{
|
{
|
||||||
Q_ASSERT(this->isMutable());
|
Q_ASSERT(this->isMutable() || (b == e && where == this->end()));
|
||||||
Q_ASSERT(!this->isShared());
|
Q_ASSERT(!this->isShared() || (b == e && where == this->end()));
|
||||||
Q_ASSERT(where >= this->begin() && where <= this->end());
|
Q_ASSERT(where >= this->begin() && where <= this->end());
|
||||||
Q_ASSERT(b <= e);
|
Q_ASSERT(b <= e);
|
||||||
Q_ASSERT(e <= where || b > this->end()); // No overlap
|
Q_ASSERT(e <= where || b > this->end() || where == this->end()); // No overlap or append
|
||||||
Q_ASSERT(size_t(e - b) <= this->allocatedCapacity() - this->size);
|
Q_ASSERT(size_t(e - b) <= this->allocatedCapacity() - this->size);
|
||||||
|
|
||||||
::memmove(static_cast<void *>(where + (e - b)), static_cast<void *>(where),
|
::memmove(static_cast<void *>(where + (e - b)), static_cast<void *>(where),
|
||||||
@ -158,7 +139,7 @@ public:
|
|||||||
|
|
||||||
void insert(T *where, size_t n, parameter_type t)
|
void insert(T *where, size_t n, parameter_type t)
|
||||||
{
|
{
|
||||||
Q_ASSERT(!this->isShared());
|
Q_ASSERT(!this->isShared() || (n == 0 && where == this->end()));
|
||||||
Q_ASSERT(where >= this->begin() && where <= this->end());
|
Q_ASSERT(where >= this->begin() && where <= this->end());
|
||||||
Q_ASSERT(this->allocatedCapacity() - this->size >= n);
|
Q_ASSERT(this->allocatedCapacity() - this->size >= n);
|
||||||
|
|
||||||
@ -275,16 +256,7 @@ struct QGenericArrayOps
|
|||||||
}
|
}
|
||||||
|
|
||||||
void copyAppend(const T *b, const T *e)
|
void copyAppend(const T *b, const T *e)
|
||||||
{
|
{ insert(this->end(), b, e); }
|
||||||
Q_ASSERT(this->isMutable() || b == e);
|
|
||||||
Q_ASSERT(!this->isShared() || b == e);
|
|
||||||
Q_ASSERT(std::distance(b, e) >= 0 && size_t(std::distance(b, e)) <= this->allocatedCapacity() - this->size);
|
|
||||||
|
|
||||||
T *iter = this->end();
|
|
||||||
this->size += e - b;
|
|
||||||
for (; b != e; ++iter, ++b)
|
|
||||||
new (iter) T(*b);
|
|
||||||
}
|
|
||||||
|
|
||||||
void moveAppend(T *b, T *e)
|
void moveAppend(T *b, T *e)
|
||||||
{
|
{
|
||||||
@ -293,26 +265,39 @@ struct QGenericArrayOps
|
|||||||
Q_ASSERT(b <= e);
|
Q_ASSERT(b <= e);
|
||||||
Q_ASSERT(size_t(e - b) <= this->allocatedCapacity() - this->size);
|
Q_ASSERT(size_t(e - b) <= this->allocatedCapacity() - this->size);
|
||||||
|
|
||||||
T *iter = this->end();
|
// Provides strong exception safety guarantee,
|
||||||
for (; b != e; ++iter, ++b) {
|
// provided T::~T() nothrow
|
||||||
new (iter) T(std::move(*b));
|
|
||||||
++this->size;
|
struct CopyConstructor
|
||||||
}
|
{
|
||||||
|
CopyConstructor(T *w) : where(w) {}
|
||||||
|
|
||||||
|
void copy(T *src, const T *const srcEnd)
|
||||||
|
{
|
||||||
|
n = 0;
|
||||||
|
for (; src != srcEnd; ++src) {
|
||||||
|
new (where + n) T(std::move(*src));
|
||||||
|
++n;
|
||||||
|
}
|
||||||
|
n = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
~CopyConstructor()
|
||||||
|
{
|
||||||
|
while (n)
|
||||||
|
where[--n].~T();
|
||||||
|
}
|
||||||
|
|
||||||
|
T *const where;
|
||||||
|
size_t n;
|
||||||
|
} copier(this->end());
|
||||||
|
|
||||||
|
copier.copy(b, e);
|
||||||
|
this->size += (e - b);
|
||||||
}
|
}
|
||||||
|
|
||||||
void copyAppend(size_t n, parameter_type t)
|
void copyAppend(size_t n, parameter_type t)
|
||||||
{
|
{ insert(this->end(), n, t); }
|
||||||
Q_ASSERT(this->isMutable() || n == 0);
|
|
||||||
Q_ASSERT(!this->isShared() || n == 0);
|
|
||||||
Q_ASSERT(n <= size_t(this->allocatedCapacity() - this->size));
|
|
||||||
|
|
||||||
T *iter = this->end();
|
|
||||||
const T *const end = iter + n;
|
|
||||||
for (; iter != end; ++iter) {
|
|
||||||
new (iter) T(t);
|
|
||||||
++this->size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename ...Args>
|
template <typename ...Args>
|
||||||
void emplaceBack(Args&&... args)
|
void emplaceBack(Args&&... args)
|
||||||
@ -349,11 +334,11 @@ struct QGenericArrayOps
|
|||||||
|
|
||||||
void insert(T *where, const T *b, const T *e)
|
void insert(T *where, const T *b, const T *e)
|
||||||
{
|
{
|
||||||
Q_ASSERT(this->isMutable());
|
Q_ASSERT(this->isMutable() || (b == e && where == this->end()));
|
||||||
Q_ASSERT(!this->isShared());
|
Q_ASSERT(!this->isShared() || (b == e && where == this->end()));
|
||||||
Q_ASSERT(where >= this->begin() && where <= this->end());
|
Q_ASSERT(where >= this->begin() && where <= this->end());
|
||||||
Q_ASSERT(b <= e);
|
Q_ASSERT(b <= e);
|
||||||
Q_ASSERT(e <= where || b > this->end()); // No overlap
|
Q_ASSERT(e <= where || b > this->end() || where == this->end()); // No overlap or append
|
||||||
Q_ASSERT(size_t(e - b) <= this->allocatedCapacity() - this->size);
|
Q_ASSERT(size_t(e - b) <= this->allocatedCapacity() - this->size);
|
||||||
|
|
||||||
// Array may be truncated at where in case of exceptions
|
// Array may be truncated at where in case of exceptions
|
||||||
@ -415,7 +400,7 @@ struct QGenericArrayOps
|
|||||||
|
|
||||||
void insert(T *where, size_t n, parameter_type t)
|
void insert(T *where, size_t n, parameter_type t)
|
||||||
{
|
{
|
||||||
Q_ASSERT(!this->isShared());
|
Q_ASSERT(!this->isShared() || (n == 0 && where == this->end()));
|
||||||
Q_ASSERT(where >= this->begin() && where <= this->end());
|
Q_ASSERT(where >= this->begin() && where <= this->end());
|
||||||
Q_ASSERT(this->allocatedCapacity() - this->size >= n);
|
Q_ASSERT(this->allocatedCapacity() - this->size >= n);
|
||||||
|
|
||||||
@ -543,17 +528,18 @@ struct QMovableArrayOps
|
|||||||
{
|
{
|
||||||
// using QGenericArrayOps<T>::appendInitialize;
|
// using QGenericArrayOps<T>::appendInitialize;
|
||||||
// using QGenericArrayOps<T>::copyAppend;
|
// using QGenericArrayOps<T>::copyAppend;
|
||||||
|
// using QGenericArrayOps<T>::moveAppend;
|
||||||
// using QGenericArrayOps<T>::truncate;
|
// using QGenericArrayOps<T>::truncate;
|
||||||
// using QGenericArrayOps<T>::destroyAll;
|
// using QGenericArrayOps<T>::destroyAll;
|
||||||
typedef typename QGenericArrayOps<T>::parameter_type parameter_type;
|
typedef typename QGenericArrayOps<T>::parameter_type parameter_type;
|
||||||
|
|
||||||
void insert(T *where, const T *b, const T *e)
|
void insert(T *where, const T *b, const T *e)
|
||||||
{
|
{
|
||||||
Q_ASSERT(this->isMutable());
|
Q_ASSERT(this->isMutable() || (b == e && where == this->end()));
|
||||||
Q_ASSERT(!this->isShared());
|
Q_ASSERT(!this->isShared() || (b == e && where == this->end()));
|
||||||
Q_ASSERT(where >= this->begin() && where <= this->end());
|
Q_ASSERT(where >= this->begin() && where <= this->end());
|
||||||
Q_ASSERT(b <= e);
|
Q_ASSERT(b <= e);
|
||||||
Q_ASSERT(e <= where || b > this->end()); // No overlap
|
Q_ASSERT(e <= where || b > this->end() || where == this->end()); // No overlap or append
|
||||||
Q_ASSERT(size_t(e - b) <= this->allocatedCapacity() - this->size);
|
Q_ASSERT(size_t(e - b) <= this->allocatedCapacity() - this->size);
|
||||||
|
|
||||||
// Provides strong exception safety guarantee,
|
// Provides strong exception safety guarantee,
|
||||||
@ -616,7 +602,7 @@ struct QMovableArrayOps
|
|||||||
|
|
||||||
void insert(T *where, size_t n, parameter_type t)
|
void insert(T *where, size_t n, parameter_type t)
|
||||||
{
|
{
|
||||||
Q_ASSERT(!this->isShared());
|
Q_ASSERT(!this->isShared() || (n == 0 && where == this->end()));
|
||||||
Q_ASSERT(where >= this->begin() && where <= this->end());
|
Q_ASSERT(where >= this->begin() && where <= this->end());
|
||||||
Q_ASSERT(this->allocatedCapacity() - this->size >= n);
|
Q_ASSERT(this->allocatedCapacity() - this->size >= n);
|
||||||
|
|
||||||
@ -716,45 +702,6 @@ struct QMovableArrayOps
|
|||||||
(--e)->~T();
|
(--e)->~T();
|
||||||
} while (e != b);
|
} while (e != b);
|
||||||
}
|
}
|
||||||
|
|
||||||
void moveAppend(T *b, T *e)
|
|
||||||
{
|
|
||||||
Q_ASSERT(this->isMutable());
|
|
||||||
Q_ASSERT(!this->isShared());
|
|
||||||
Q_ASSERT(b <= e);
|
|
||||||
Q_ASSERT(e <= this->begin() || b > this->end()); // No overlap
|
|
||||||
Q_ASSERT(size_t(e - b) <= this->allocatedCapacity() - this->size);
|
|
||||||
|
|
||||||
// Provides strong exception safety guarantee,
|
|
||||||
// provided T::~T() nothrow
|
|
||||||
|
|
||||||
struct CopyConstructor
|
|
||||||
{
|
|
||||||
CopyConstructor(T *w) : where(w) {}
|
|
||||||
|
|
||||||
void copy(T *src, const T *const srcEnd)
|
|
||||||
{
|
|
||||||
n = 0;
|
|
||||||
for (; src != srcEnd; ++src) {
|
|
||||||
new (where + n) T(std::move(*src));
|
|
||||||
++n;
|
|
||||||
}
|
|
||||||
n = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
~CopyConstructor()
|
|
||||||
{
|
|
||||||
while (n)
|
|
||||||
where[--n].~T();
|
|
||||||
}
|
|
||||||
|
|
||||||
T *const where;
|
|
||||||
size_t n;
|
|
||||||
} copier(this->end());
|
|
||||||
|
|
||||||
copier.copy(b, e);
|
|
||||||
this->size += (e - b);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T, class = void>
|
template <class T, class = void>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user