1 | // Copyright (C) 2018 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #ifndef QPODVECTOR_P_H |
5 | #define QPODVECTOR_P_H |
6 | |
7 | // |
8 | // W A R N I N G |
9 | // ------------- |
10 | // |
11 | // This file is not part of the Qt API. It exists purely as an |
12 | // implementation detail. This header file may change from version to |
13 | // version without notice, or even be removed. |
14 | // |
15 | // We mean it. |
16 | // |
17 | |
18 | #include <QtCore/private/qglobal_p.h> |
19 | #include <QDebug> |
20 | |
21 | QT_BEGIN_NAMESPACE |
22 | |
23 | template<class T, int Increment> |
24 | class QPODVector |
25 | { |
26 | public: |
27 | QPODVector() |
28 | : m_count(0), m_capacity(0), m_data(nullptr) {} |
29 | ~QPODVector() { if (m_data) ::free(ptr: m_data); } |
30 | |
31 | const T &at(int idx) const { |
32 | return m_data[idx]; |
33 | } |
34 | |
35 | T &operator[](int idx) { |
36 | return m_data[idx]; |
37 | } |
38 | |
39 | void clear() { |
40 | m_count = 0; |
41 | } |
42 | |
43 | void prepend(const T &v) { |
44 | insert(idx: 0, v); |
45 | } |
46 | |
47 | void append(const T &v) { |
48 | insert(idx: m_count, v); |
49 | } |
50 | |
51 | void insert(int idx, const T &v) { |
52 | if (m_count == m_capacity) { |
53 | m_capacity += Increment; |
54 | m_data = (T *)realloc(ptr: static_cast<void *>(m_data), size: m_capacity * sizeof(T)); |
55 | } |
56 | int moveCount = m_count - idx; |
57 | if (moveCount) |
58 | ::memmove(dest: static_cast<void *>(m_data + idx + 1), src: static_cast<const void *>(m_data + idx), n: moveCount * sizeof(T)); |
59 | m_count++; |
60 | m_data[idx] = v; |
61 | } |
62 | |
63 | void reserve(int count) { |
64 | if (count >= m_capacity) { |
65 | m_capacity = (count + (Increment-1)) & (0xFFFFFFFF - Increment + 1); |
66 | m_data = (T *)realloc(ptr: static_cast<void *>(m_data), size: m_capacity * sizeof(T)); |
67 | } |
68 | } |
69 | |
70 | void insertBlank(int idx, int count) { |
71 | int newSize = m_count + count; |
72 | reserve(count: newSize); |
73 | int moveCount = m_count - idx; |
74 | if (moveCount) |
75 | ::memmove(dest: static_cast<void *>(m_data + idx + count), src: static_cast<const void *>(m_data + idx), |
76 | n: moveCount * sizeof(T)); |
77 | m_count = newSize; |
78 | } |
79 | |
80 | void remove(int idx, int count = 1) { |
81 | int moveCount = m_count - (idx + count); |
82 | if (moveCount) |
83 | ::memmove(dest: static_cast<void *>(m_data + idx), src: static_cast<const void *>(m_data + idx + count), |
84 | n: moveCount * sizeof(T)); |
85 | m_count -= count; |
86 | } |
87 | |
88 | void removeOne(const T &v) { |
89 | int idx = 0; |
90 | while (idx < m_count) { |
91 | if (m_data[idx] == v) { |
92 | remove(idx); |
93 | return; |
94 | } |
95 | ++idx; |
96 | } |
97 | } |
98 | |
99 | int find(const T &v) { |
100 | for (int idx = 0; idx < m_count; ++idx) |
101 | if (m_data[idx] == v) |
102 | return idx; |
103 | return -1; |
104 | } |
105 | |
106 | bool contains(const T &v) { |
107 | return find(v) != -1; |
108 | } |
109 | |
110 | int count() const { |
111 | return m_count; |
112 | } |
113 | |
114 | void copyAndClear(QPODVector<T,Increment> &other) { |
115 | if (other.m_data) ::free(ptr: other.m_data); |
116 | other.m_count = m_count; |
117 | other.m_capacity = m_capacity; |
118 | other.m_data = m_data; |
119 | m_count = 0; |
120 | m_capacity = 0; |
121 | m_data = nullptr; |
122 | } |
123 | |
124 | QPODVector<T,Increment> &operator<<(const T &v) { append(v); return *this; } |
125 | private: |
126 | QPODVector(const QPODVector &); |
127 | QPODVector &operator=(const QPODVector &); |
128 | int m_count; |
129 | int m_capacity; |
130 | T *m_data; |
131 | }; |
132 | |
133 | QT_END_NAMESPACE |
134 | |
135 | #endif |
136 | |