blob: 35fdaf79c1979c00b1ec208774706335992589fb [file] [log] [blame]
edisonn@google.com04115a12013-02-25 20:07:24 +00001/*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef SkTSet_DEFINED
9#define SkTSet_DEFINED
10
11#include "SkTDArray.h"
12#include "SkTypes.h"
13
14/** \class SkTSet<T>
15
16 The SkTSet template class defines a set.
17 Main operations supported now are: add, merge, find and contains.
18
19 TSet<T> is mutable.
20*/
21
22// TODO: Add remove, intersect and difference operations.
23// TODO: Add bench tests.
24template <typename T> class SK_API SkTSet {
25public:
26 SkTSet() {
27 fArray = SkNEW(SkTDArray<T>);
28 }
29
30 ~SkTSet() {
31 SkASSERT(fArray);
32 SkDELETE(fArray);
33 }
34
35 SkTSet(const SkTSet<T>& src) {
36 this->fArray = SkNEW_ARGS(SkTDArray<T>, (*src.fArray));
37#ifdef SK_DEBUG
38 validate();
39#endif
40 }
41
42 SkTSet<T>& operator=(const SkTSet<T>& src) {
43 *this->fArray = *src.fArray;
44#ifdef SK_DEBUG
45 validate();
46#endif
47 return *this;
48 }
49
50 /** Merges src elements into this, and returns the number of duplicates
51 * found.
52 */
53 int mergeInto(const SkTSet<T>& src) {
54 SkASSERT(fArray);
55 int duplicates = 0;
56
57 SkTDArray<T>* fArrayNew = new SkTDArray<T>();
58 fArrayNew->setReserve(count() + src.count());
59 int i = 0;
60 int j = 0;
61
62 while (i < count() && j < src.count()) {
63 if ((*fArray)[i] < (*src.fArray)[j]) {
64 fArrayNew->push((*fArray)[i]);
65 i++;
66 } else if ((*fArray)[i] > (*src.fArray)[j]) {
67 fArrayNew->push((*src.fArray)[j]);
68 j++;
69 } else {
70 duplicates++;
71 j++; // Skip one of the duplicates.
72 }
73 }
74
75 while (i < count()) {
76 fArrayNew->push((*fArray)[i]);
77 i++;
78 }
79
80 while (j < src.count()) {
81 fArrayNew->push((*src.fArray)[j]);
82 j++;
83 }
84 SkDELETE(fArray);
85 fArray = fArrayNew;
86 fArrayNew = NULL;
87
88#ifdef SK_DEBUG
89 validate();
90#endif
91 return duplicates;
92 }
93
94 /** Adds a new element into set and returns true if the element is already
95 * in this set.
96 */
97 bool add(const T& elem) {
98 SkASSERT(fArray);
99
100 int pos = 0;
101 int i = find(elem, &pos);
102 if (i >= 0) {
103 return false;
104 }
105 *fArray->insert(pos) = elem;
106#ifdef SK_DEBUG
107 validate();
108#endif
109 return true;
110 }
111
112 /** Returns true if this set is empty.
113 */
114 bool isEmpty() const {
115 SkASSERT(fArray);
116 return fArray->isEmpty();
117 }
118
119 /** Return the number of elements in the set.
120 */
121 int count() const {
122 SkASSERT(fArray);
123 return fArray->count();
124 }
125
126 /** Return the number of bytes in the set: count * sizeof(T).
127 */
128 size_t bytes() const {
129 SkASSERT(fArray);
130 return fArray->bytes();
131 }
132
133 /** Return the beginning of a set iterator.
134 * Elements in the iterator will be sorted ascending.
135 */
136 const T* begin() const {
137 SkASSERT(fArray);
138 return fArray->begin();
139 }
140
141 /** Return the end of a set iterator.
142 */
143 const T* end() const {
144 SkASSERT(fArray);
145 return fArray->end();
146 }
147
148 const T& operator[](int index) const {
149 SkASSERT(fArray);
150 return (*fArray)[index];
151 }
152
153 /** Resets the set (deletes memory and initiates an empty set).
154 */
155 void reset() {
156 SkASSERT(fArray);
157 fArray->reset();
158 }
159
160 /** Rewinds the set (preserves memory and initiates an empty set).
161 */
162 void rewind() {
163 SkASSERT(fArray);
164 fArray->rewind();
165 }
166
167 /** Reserves memory for the set.
168 */
169 void setReserve(size_t reserve) {
170 SkASSERT(fArray);
171 fArray->setReserve(reserve);
172 }
173
174 /** Returns the index where an element was found.
175 * Returns -1 if the element was not found, and it fills *posToInsertSorted
176 * with the index of the place where elem should be inserted to preserve the
177 * internal array sorted.
178 * If element was found, *posToInsertSorted is undefined.
179 */
180 int find(const T& elem, int* posToInsertSorted = NULL) const {
181 SkASSERT(fArray);
182
183 if (fArray->count() == 0) {
184 if (posToInsertSorted) {
185 *posToInsertSorted = 0;
186 }
187 return -1;
188 }
189 int iMin = 0;
190 int iMax = fArray->count();
191
192 while (iMin < iMax - 1) {
193 int iMid = (iMin + iMax) / 2;
194 if (elem < (*fArray)[iMid]) {
195 iMax = iMid;
196 } else {
197 iMin = iMid;
198 }
199 }
200 if (elem == (*fArray)[iMin]) {
201 return iMin;
202 }
203 if (posToInsertSorted) {
204 if (elem < (*fArray)[iMin]) {
205 *posToInsertSorted = iMin;
206 } else {
207 *posToInsertSorted = iMin + 1;
208 }
209 }
210
211 return -1;
212 }
213
214 /** Returns true if the array contains this element.
215 */
216 bool contains(const T& elem) const {
217 SkASSERT(fArray);
218 return (this->find(elem) >= 0);
219 }
220
221 /** Copies internal array to destination.
222 */
223 void copy(T* dst) const {
224 SkASSERT(fArray);
225 fArray->copyRange(0, fArray->count(), dst);
226 }
227
228 /** Returns a const reference to the internal vector.
229 */
230 const SkTDArray<T>& toArray() {
231 SkASSERT(fArray);
232 return *fArray;
233 }
234
235 /** Unref all elements in the set.
236 */
237 void unrefAll() {
238 SkASSERT(fArray);
239 fArray->unrefAll();
240 }
241
242 /** safeUnref all elements in the set.
243 */
244 void safeUnrefAll() {
245 SkASSERT(fArray);
246 fArray->safeUnrefAll();
247 }
248
249#ifdef SK_DEBUG
250 void validate() const {
251 SkASSERT(fArray);
252 fArray->validate();
253 SkASSERT(isSorted() && !hasDuplicates());
254 }
255
256 bool hasDuplicates() const {
257 for (int i = 0; i < fArray->count() - 1; ++i) {
258 if ((*fArray)[i] == (*fArray)[i + 1]) {
259 return true;
260 }
261 }
262 return false;
263 }
264
265 bool isSorted() const {
266 for (int i = 0; i < fArray->count() - 1; ++i) {
267 // Use only < operator
268 if (!((*fArray)[i] < (*fArray)[i + 1])) {
269 return false;
270 }
271 }
272 return true;
273 }
274#endif
275
276private:
277 SkTDArray<T>* fArray;
278};
279
280#endif