OSDN Git Service

add containers from recontainers branch with minor changes for private use
authorIvailo Monev <xakepa10@gmail.com>
Mon, 20 Sep 2021 02:29:06 +0000 (05:29 +0300)
committerIvailo Monev <xakepa10@gmail.com>
Mon, 20 Sep 2021 02:29:06 +0000 (05:29 +0300)
src/core/CMakeLists.txt
src/core/tools/qstdcontainers_p.h [new file with mode: 0644]

index fd4e356..5ea6d41 100644 (file)
@@ -278,6 +278,7 @@ set(CORE_HEADERS
     ${CMAKE_CURRENT_SOURCE_DIR}/tools/qvector.h
     ${CMAKE_CURRENT_SOURCE_DIR}/tools/qiterator.h
     ${CMAKE_CURRENT_SOURCE_DIR}/tools/qpair.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/tools/qstdcontainers_p.h
     ${CMAKE_CURRENT_SOURCE_DIR}/qcorecommon_p.h
 )
 
diff --git a/src/core/tools/qstdcontainers_p.h b/src/core/tools/qstdcontainers_p.h
new file mode 100644 (file)
index 0000000..10b3979
--- /dev/null
@@ -0,0 +1,615 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2016 Ivailo Monev
+**
+** This file is part of the QtCore module of the Katie Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+**
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSTDCONTAINERS_P_H
+#define QSTDCONTAINERS_P_H
+
+//
+//  W A R N I N G
+//  -------------
+//
+// This file is not part of the Katie API.  It exists purely as an
+// implementation detail.  This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qiterator.h>
+#include <QtCore/qalgorithms.h>
+
+#include <vector>
+#include <list>
+#include <unordered_set>
+
+QT_BEGIN_NAMESPACE
+
+template <typename T>
+class Q_CORE_EXPORT QStdVector : public std::vector<T>
+{
+    typedef std::vector<T> Data;
+
+public:
+    QStdVector() : Data() { }
+    explicit QStdVector(int size) : Data(size) { }
+    QStdVector(int size, const T &t) : Data() { Data::reserve(size); Data::insert(Data::begin(), size, t);}
+#ifdef Q_COMPILER_INITIALIZER_LISTS
+    inline QStdVector(std::initializer_list<T> args) : Data(args) { }
+#endif
+
+    inline bool isEmpty() const { return Data::empty(); }
+    inline void squeeze() { Data::shrink_to_fit(); }
+    inline const T *constData() const { return Data::data(); }
+    inline void append(const T &t) { Data::push_back(t); }
+    inline void prepend(const T &t) { Data::insert(Data::begin(), t); }
+    inline void insert(int i, const T &t) { Data::insert(Data::begin() + i, t); }
+    inline void insert(int i, int n, const T &t) { Data::insert(Data::begin() + i, n, t); }
+    inline void push_front(const T &t) { prepend(t); }
+
+    void replace(int i, const T &t);
+    void remove(int i);
+    void remove(int i, int n);
+    QStdVector<T> &fill(const T &t, int size = -1);
+    int indexOf(const T &t, int from = 0) const;
+    int lastIndexOf(const T &t, int from = -1) const;
+    bool contains(const T &t) const;
+    int count(const T &t) const;
+    T value(int i) const;
+    T value(int i, const T &defaultValue) const;
+    QStdVector<T> mid(int pos, int length = -1) const;
+
+    inline int count() const { return Data::size(); }
+    inline T& first() { Q_ASSERT(!isEmpty()); return Data::front(); }
+    inline const T &first() const { Q_ASSERT(!isEmpty()); return Data::front(); }
+    inline T& last() { Q_ASSERT(!isEmpty()); return Data::back(); }
+    inline const T &last() const { Q_ASSERT(!isEmpty()); return Data::back(); }
+    inline bool startsWith(const T &t) const { return !isEmpty() && first() == t; }
+    inline bool endsWith(const T &t) const { return !isEmpty() && last() == t; }
+    inline void pop_front() { Q_ASSERT(!isEmpty()); Data::erase(Data::begin()); }
+    inline typename Data::const_iterator constBegin() const { return Data::cbegin(); }
+    inline typename Data::const_iterator constEnd() const { return Data::cend(); }
+
+    // comfort
+    QStdVector<T> &operator+=(const QStdVector<T> &l);
+    inline QStdVector<T> operator+(const QStdVector<T> &l) const { QStdVector n = *this; n += l; return n; }
+    inline QStdVector<T> &operator+=(const T &t) { append(t); return *this; }
+    inline QStdVector<T> &operator<<(const T &t) { append(t); return *this; }
+    inline QStdVector<T> &operator<<(const QStdVector<T> &l) { *this += l; return *this; }
+
+    static inline QStdVector<T> fromStdVector(const std::vector<T> &vector)
+    { QStdVector<T> tmp; tmp.reserve(vector.size()); qCopy(vector.cbegin(), vector.cend(), std::back_inserter(tmp)); return tmp; }
+    inline std::vector<T> toStdVector() const { return std::vector<T>(*this); }
+
+    typedef typename Data::iterator Iterator;
+    typedef typename Data::const_iterator ConstIterator;
+     // type deduction for e.g. qMin()/qMax()
+    inline int size() const { return Data::size(); }
+    inline int capacity() const { return Data::capacity(); }
+     // release memory and set capacity to 0
+    inline void clear() { Data::clear(); Data::shrink_to_fit(); }
+
+#if !defined(Q_NO_USING_KEYWORD)
+    using Data::insert;
+#endif
+};
+
+template <typename T>
+inline void QStdVector<T>::remove(int i, int n)
+{
+    Q_ASSERT_X(i >= 0 && n >= 0 && i + n <= Data::size(), "QStdVector<T>::remove", "index out of range");
+    Data::erase(Data::begin() + i, Data::begin() + i + n);
+}
+
+template <typename T>
+inline void QStdVector<T>::remove(int i)
+{
+    Q_ASSERT_X(i >= 0 && i < Data::size(), "QStdVector<T>::remove", "index out of range");
+    Data::erase(Data::begin() + i, Data::begin() + i + 1);
+}
+
+template <typename T>
+inline void QStdVector<T>::replace(int i, const T &t)
+{
+    Q_ASSERT_X(i >= 0 && i < Data::size(), "QStdVector<T>::replace", "index out of range");
+    Data::data()[i] = t;
+}
+
+template<typename T>
+inline T QStdVector<T>::value(int i) const
+{
+    if (i < 0 || i >= Data::size()) {
+        return T();
+    }
+    return Data::at(i);
+}
+template<typename T>
+inline T QStdVector<T>::value(int i, const T &defaultValue) const
+{
+    return ((i < 0 || i >= Data::size()) ? defaultValue :  Data::at(i));
+}
+
+template <typename T>
+QStdVector<T> &QStdVector<T>::fill(const T &from, int asize)
+{
+    if (asize < 0)
+        asize = Data::size();
+    Data::clear();
+    if (asize > 0) {
+        Data::reserve(asize);
+        Data::insert(Data::begin(), asize, from);
+    }
+    Data::shrink_to_fit();
+    return *this;
+}
+
+template <typename T>
+inline QStdVector<T> &QStdVector<T>::operator+=(const QStdVector &l)
+{
+    Data::reserve(Data::size() + l.size());
+    for (size_t i = 0; i < l.size(); i++) {
+        Data::push_back(l.at(i));
+    }
+    return *this;
+}
+
+template <typename T>
+int QStdVector<T>::indexOf(const T &t, int from) const
+{
+    if (from < 0)
+        from = qMax(from + int(Data::size()), 0);
+    if (from < Data::size()) {
+        for (size_t i = from; i < Data::size(); i++) {
+            if (Data::at(i) == t)
+                return i;
+        }
+    }
+    return -1;
+}
+
+template <typename T>
+int QStdVector<T>::lastIndexOf(const T &t, int from) const
+{
+    if (from < 0)
+        from += Data::size();
+    else if (from >= Data::size())
+        from = Data::size() - 1;
+    while(from >= 0) {
+        if (Data::at(from) == t)
+            return from;
+        from--;
+    }
+    return -1;
+}
+
+template <typename T>
+bool QStdVector<T>::contains(const T &t) const
+{
+    for (size_t i = 0; i < Data::size(); i++) {
+        if (Data::at(i) == t)
+            return true;
+    }
+    return false;
+}
+
+template <typename T>
+int QStdVector<T>::count(const T &t) const
+{
+    int c = 0;
+    for (size_t i = 0; i < Data::size(); i++) {
+        if (Data::at(i) == t)
+            c++;
+    }
+    return c;
+}
+
+template <typename T>
+QStdVector<T> QStdVector<T>::mid(int pos, int length) const
+{
+    if (length < 0)
+        length = Data::size() - pos;
+    if (pos == 0 && length == Data::size())
+        return *this;
+    if (pos + length > Data::size())
+        length = Data::size() - pos;
+    QStdVector<T> copy;
+    copy.reserve(length);
+    for (size_t i = pos; i < pos + length; i++)
+        copy.push_back(Data::at(i));
+    return copy;
+}
+
+Q_DECLARE_SEQUENTIAL_ITERATOR(StdVector)
+Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR(StdVector)
+
+
+template <typename T>
+class Q_CORE_EXPORT QStdList : public std::vector<T>
+{
+    typedef std::vector<T> Data;
+
+public:
+    QStdList() : Data() { }
+    QStdList(const QStdList &other) : Data() {
+        Data::reserve(other.size());
+        for (size_t i = 0;  i < other.size(); i++)
+            Data::push_back(other.at(i));
+    }
+    explicit QStdList(int size) : Data(size) { }
+#ifdef Q_COMPILER_INITIALIZER_LISTS
+    inline QStdList(std::initializer_list<T> args) : Data(args) { }
+#endif
+
+    inline int length() const { return Data::size(); }
+    inline void removeFirst() { Q_ASSERT(!isEmpty()); Data::erase(Data::begin()); }
+    inline void removeLast() { Q_ASSERT(!isEmpty()); Data::erase(Data::end()); }
+
+    void append(const QStdList<T> &l);
+    void removeAt(int i);
+    int removeAll(const T &t);
+    bool removeOne(const T &t);
+    T takeAt(int i);
+    T takeFirst();
+    T takeLast();
+    void move(int from, int to);
+
+    static inline QStdList<T> fromStdList(const std::list<T> &list)
+    { QStdList<T> tmp; qCopy(list.begin(), list.end(), std::back_inserter(tmp)); return tmp; }
+    inline std::list<T> toStdList() const
+    { std::list<T> tmp; qCopy(Data::cbegin(), Data::cend(), std::back_inserter(tmp)); return tmp; }
+
+    // almost the same as QVector<T>
+    inline bool isEmpty() const { return Data::empty(); }
+    inline void append(const T &t) { Data::push_back(t); }
+    inline void prepend(const T &t) { Data::insert(Data::begin(), t); }
+    inline void insert(int i, const T &t) { Data::insert(Data::begin() + i, t); }
+    inline void insert(int i, int n, const T &t) { Data::insert(Data::begin() + i, n, t); }
+    inline void push_front(const T &t) { prepend(t); }
+
+    void replace(int i, const T &t);
+    void remove(int i);
+    void remove(int i, int n);
+    int indexOf(const T &t, int from = 0) const;
+    int lastIndexOf(const T &t, int from = -1) const;
+    bool contains(const T &t) const;
+    int count(const T &t) const;
+    T value(int i) const;
+    T value(int i, const T &defaultValue) const;
+    QStdList<T> mid(int pos, int length = -1) const;
+
+    inline int count() const { return Data::size(); }
+    inline T& first() { Q_ASSERT(!isEmpty()); return Data::front(); }
+    inline const T &first() const { Q_ASSERT(!isEmpty()); return Data::front(); }
+    inline T& last() { Q_ASSERT(!isEmpty()); return Data::back(); }
+    inline const T &last() const { Q_ASSERT(!isEmpty()); return Data::back(); }
+    inline bool startsWith(const T &t) const { return !isEmpty() && first() == t; }
+    inline bool endsWith(const T &t) const { return !isEmpty() && last() == t; }
+    inline void pop_front() { Q_ASSERT(!isEmpty()); Data::erase(Data::begin()); }
+    inline typename Data::const_iterator constBegin() const { return Data::cbegin(); }
+    inline typename Data::const_iterator constEnd() const { return Data::cend(); }
+
+    // comfort
+    QStdList<T> &operator+=(const QStdList<T> &l);
+    inline QStdList<T> operator+(const QStdList<T> &l) const { QStdList n = *this; n += l; return n; }
+    inline QStdList<T> &operator+=(const T &t) { append(t); return *this; }
+    inline QStdList<T> &operator<<(const T &t) { append(t); return *this; }
+    inline QStdList<T> &operator<<(const QStdList<T> &l) { *this += l; return *this; }
+
+    typedef typename Data::iterator Iterator;
+    typedef typename Data::const_iterator ConstIterator;
+     // type deduction for e.g. qMin()/qMax()
+    inline int size() const { return Data::size(); }
+     // release memory and set capacity to 0
+    inline void clear() { Data::clear(); Data::shrink_to_fit(); }
+
+#if !defined(Q_NO_USING_KEYWORD)
+    using Data::insert;
+#endif
+};
+
+template <typename T>
+inline void QStdList<T>::append(const QStdList<T> &l)
+{
+    Data::reserve(Data::size() + l.size());
+    for (size_t i = 0; i < l.size(); i++) {
+        Data::push_back(l.at(i));
+    }
+}
+
+template <typename T>
+inline void QStdList<T>::removeAt(int i)
+{
+    Data::erase(Data::begin() + i);
+}
+
+template <typename T>
+inline T QStdList<T>::takeAt(int i)
+{
+    Q_ASSERT_X(i >= 0 && i < Data::size(), "QStdList<T>::take", "index out of range");
+    T t = Data::at(i); removeAt(i); return t;
+}
+
+template <typename T>
+inline T QStdList<T>::takeFirst()
+{
+    T t = first(); removeFirst(); return t;
+}
+
+template <typename T>
+inline T QStdList<T>::takeLast()
+{
+    T t = last(); removeLast(); return t;
+}
+
+template <typename T>
+inline void QStdList<T>::move(int from, int to)
+{
+    Q_ASSERT_X(from >= 0 && from < Data::size() && to >= 0 && to < Data::size(),
+               "QStdList<T>::move", "index out of range");
+    Data::insert(Data::begin() + to, takeAt(from));
+}
+
+template <typename T>
+int QStdList<T>::removeAll(const T &t)
+{
+    int c = 0;
+    typename Data::iterator it = Data::begin();
+    while (it != Data::end()) {
+        if (*it == t) {
+            Data::erase(it);
+            c++;
+            continue;
+        }
+        it++;
+    }
+    return c;
+}
+
+template <typename T>
+bool QStdList<T>::removeOne(const T &t)
+{
+    for (size_t i = 0; i < Data::size(); i++) {
+        if (Data::at(i) == t) {
+            Data::erase(Data::begin() + i);
+            return true;
+        }
+    }
+    return false;
+}
+
+// copy from QVector<T>
+template <typename T>
+inline void QStdList<T>::remove(int i, int n)
+{
+    Q_ASSERT_X(i >= 0 && n >= 0 && i + n <= Data::size(), "QStdList<T>::remove", "index out of range");
+    Data::erase(Data::begin() + i, Data::begin() + i + n);
+}
+
+template <typename T>
+inline void QStdList<T>::remove(int i)
+{
+    Q_ASSERT_X(i >= 0 && i < Data::size(), "QStdList<T>::remove", "index out of range");
+    Data::erase(Data::begin() + i, Data::begin() + i + 1);
+}
+
+template <typename T>
+inline void QStdList<T>::replace(int i, const T &t)
+{
+    Q_ASSERT_X(i >= 0 && i < Data::size(), "QStdList<T>::replace", "index out of range");
+    Data::data()[i] = t;
+}
+
+template<typename T>
+inline T QStdList<T>::value(int i) const
+{
+    if (i < 0 || i >= Data::size()) {
+        return T();
+    }
+    return Data::at(i);
+}
+template<typename T>
+inline T QStdList<T>::value(int i, const T &defaultValue) const
+{
+    return ((i < 0 || i >= Data::size()) ? defaultValue :  Data::at(i));
+}
+
+template <typename T>
+inline QStdList<T> &QStdList<T>::operator+=(const QStdList &l)
+{
+    append(l);
+    return *this;
+}
+
+template <typename T>
+int QStdList<T>::indexOf(const T &t, int from) const
+{
+    if (from < 0)
+        from = qMax(from + int(Data::size()), 0);
+    if (from < Data::size()) {
+        for (size_t i = from; i < Data::size(); i++) {
+            if (Data::at(i) == t)
+                return i;
+        }
+    }
+    return -1;
+}
+
+template <typename T>
+int QStdList<T>::lastIndexOf(const T &t, int from) const
+{
+    if (from < 0)
+        from += Data::size();
+    else if (from >= Data::size())
+        from = Data::size() - 1;
+    while(from >= 0) {
+        if (Data::at(from) == t)
+            return from;
+        from--;
+    }
+    return -1;
+}
+
+template <typename T>
+bool QStdList<T>::contains(const T &t) const
+{
+    for (size_t i = 0; i < Data::size(); i++) {
+        if (Data::at(i) == t)
+            return true;
+    }
+    return false;
+}
+
+template <typename T>
+int QStdList<T>::count(const T &t) const
+{
+    int c = 0;
+    for (size_t i = 0; i < Data::size(); i++) {
+        if (Data::at(i) == t)
+            c++;
+    }
+    return c;
+}
+
+template <typename T>
+QStdList<T> QStdList<T>::mid(int pos, int length) const
+{
+    if (length < 0)
+        length = Data::size() - pos;
+    if (pos == 0 && length == Data::size())
+        return *this;
+    if (pos + length > Data::size())
+        length = Data::size() - pos;
+    QStdList<T> copy;
+    copy.reserve(length);
+    for (size_t i = pos; i < pos + length; i++)
+        copy.push_back(Data::at(i));
+    return copy;
+}
+
+Q_DECLARE_SEQUENTIAL_ITERATOR(StdList)
+Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR(StdList)
+
+
+template<class T>
+struct SetHasher {
+    size_t operator()(const T& k) const { return qHash(k); }
+};
+
+template <class T>
+class Q_CORE_EXPORT QStdSet : public std::unordered_set<T, SetHasher<T>>
+{
+    typedef std::unordered_set<T, SetHasher<T>> Data;
+
+public:
+    inline QStdSet() : Data() {}
+    inline QStdSet(const QStdSet<T> &other) : Data(other) {}
+
+    inline bool isEmpty() const { return Data::empty(); }
+    inline void squeeze() { Data::rehash(0); }
+    inline bool remove(const T &value) { return Data::erase(value) != 0; }
+    inline int count() const { return Data::size(); }
+    inline bool contains(const T &value) const { return Data::count(value) != 0; }
+    bool contains(const QStdSet<T> &set) const;
+
+    inline typename Data::iterator insert(const T &value)
+        { return static_cast<typename Data::iterator>(Data::emplace(value).first); }
+    inline typename Data::const_iterator constBegin() const { return Data::cbegin(); }
+    inline typename Data::const_iterator constEnd() const { return Data::cend(); }
+    inline typename Data::const_iterator constFind(const T &value) const { return Data::find(value); }
+    typedef typename Data::iterator Iterator;
+    typedef typename Data::const_iterator ConstIterator;
+
+    QStdSet<T> &unite(const QStdSet<T> &other);
+    QStdSet<T> &intersect(const QStdSet<T> &other);
+    QStdSet<T> &subtract(const QStdSet<T> &other);
+
+    // comfort
+    inline QStdSet<T> &operator<<(const T &value) { insert(value); return *this; }
+    inline QStdSet<T> &operator|=(const QStdSet<T> &other) { unite(other); return *this; }
+    inline QStdSet<T> &operator|=(const T &value) { insert(value); return *this; }
+    inline QStdSet<T> &operator&=(const QStdSet<T> &other) { intersect(other); return *this; }
+    inline QStdSet<T> &operator&=(const T &value)
+        { QStdSet<T> result; if (contains(value)) result.insert(value); return (*this = result); }
+    inline QStdSet<T> &operator+=(const QStdSet<T> &other) { unite(other); return *this; }
+    inline QStdSet<T> &operator+=(const T &value) { insert(value); return *this; }
+    inline QStdSet<T> &operator-=(const QStdSet<T> &other) { subtract(other); return *this; }
+    inline QStdSet<T> &operator-=(const T &value) { remove(value); return *this; }
+    inline QStdSet<T> operator|(const QStdSet<T> &other) const
+        { QStdSet<T> result = *this; result |= other; return result; }
+    inline QStdSet<T> operator&(const QStdSet<T> &other) const
+        { QStdSet<T> result = *this; result &= other; return result; }
+    inline QStdSet<T> operator+(const QStdSet<T> &other) const
+        { QStdSet<T> result = *this; result += other; return result; }
+    inline QStdSet<T> operator-(const QStdSet<T> &other) const
+        { QStdSet<T> result = *this; result -= other; return result; }
+};
+
+template <class T>
+inline QStdSet<T> &QStdSet<T>::unite(const QStdSet<T> &other)
+{
+    typename QStdSet<T>::const_iterator i = other.constEnd();
+    while (i != other.constEnd()) {
+        insert(*i);
+        i++;
+    }
+    return *this;
+}
+
+template <class T>
+inline QStdSet<T> &QStdSet<T>::intersect(const QStdSet<T> &other)
+{
+    QStdSet<T> copy(*this);
+    typename QStdSet<T>::const_iterator i = copy.constBegin();
+    while (i != copy.constEnd()) {
+        if (!other.contains(*i))
+            remove(*i);
+        i++;
+    }
+    return *this;
+}
+
+template <class T>
+inline QStdSet<T> &QStdSet<T>::subtract(const QStdSet<T> &other)
+{
+    QStdSet<T> copy(*this);
+    typename QStdSet<T>::const_iterator i = copy.constBegin();
+    while (i != copy.constEnd()) {
+        if (other.contains(*i))
+            remove(*i);
+        i++;
+    }
+    return *this;
+}
+
+template <class T>
+inline bool QStdSet<T>::contains(const QStdSet<T> &other) const
+{
+    typename QStdSet<T>::const_iterator i = other.constBegin();
+    while (i != other.constEnd()) {
+        if (!contains(*i))
+            return false;
+        ++i;
+    }
+    return true;
+}
+
+QT_END_NAMESPACE
+
+#endif // QSTDCONTAINERS_P_H
\ No newline at end of file