00001 /**************************************************************************** 00002 ** 00003 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). 00004 ** All rights reserved. 00005 ** Contact: Nokia Corporation (qt-info@nokia.com) 00006 ** 00007 ** This file is part of the QtCore module of the Qt Toolkit. 00008 ** 00009 ** $QT_BEGIN_LICENSE:LGPL$ 00010 ** Commercial Usage 00011 ** Licensees holding valid Qt Commercial licenses may use this file in 00012 ** accordance with the Qt Commercial License Agreement provided with the 00013 ** Software or, alternatively, in accordance with the terms contained in 00014 ** a written agreement between you and Nokia. 00015 ** 00016 ** GNU Lesser General Public License Usage 00017 ** Alternatively, this file may be used under the terms of the GNU Lesser 00018 ** General Public License version 2.1 as published by the Free Software 00019 ** Foundation and appearing in the file LICENSE.LGPL included in the 00020 ** packaging of this file. Please review the following information to 00021 ** ensure the GNU Lesser General Public License version 2.1 requirements 00022 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 00023 ** 00024 ** In addition, as a special exception, Nokia gives you certain additional 00025 ** rights. These rights are described in the Nokia Qt LGPL Exception 00026 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this module. 00027 ** 00028 ** GNU General Public License Usage 00029 ** Alternatively, this file may be used under the terms of the GNU 00030 ** General Public License version 3.0 as published by the Free Software 00031 ** Foundation and appearing in the file LICENSE.GPL included in the 00032 ** packaging of this file. Please review the following information to 00033 ** ensure the GNU General Public License version 3.0 requirements will be 00034 ** met: http://www.gnu.org/copyleft/gpl.html. 00035 ** 00036 ** If you have questions regarding the use of this file, please contact 00037 ** Nokia at qt-info@nokia.com. 00038 ** $QT_END_LICENSE$ 00039 ** 00040 ****************************************************************************/ 00041 00042 #ifndef QSET_H 00043 #define QSET_H 00044 00045 #include <QtCore/qhash.h> 00046 00047 QT_BEGIN_HEADER 00048 00049 QT_BEGIN_NAMESPACE 00050 00051 QT_MODULE(Core) 00052 00053 template <class T> 00054 class QSet 00055 { 00056 typedef QHash<T, QHashDummyValue> Hash; 00057 00058 public: 00059 inline QSet() {} 00060 inline QSet(const QSet<T> &other) : q_hash(other.q_hash) {} 00061 00062 inline QSet<T> &operator=(const QSet<T> &other) 00063 { q_hash = other.q_hash; return *this; } 00064 00065 inline bool operator==(const QSet<T> &other) const 00066 { return q_hash == other.q_hash; } 00067 inline bool operator!=(const QSet<T> &other) const 00068 { return q_hash != other.q_hash; } 00069 00070 inline int size() const { return q_hash.size(); } 00071 00072 inline bool isEmpty() const { return q_hash.isEmpty(); } 00073 00074 inline int capacity() const { return q_hash.capacity(); } 00075 inline void reserve(int size); 00076 inline void squeeze() { q_hash.squeeze(); } 00077 00078 inline void detach() { q_hash.detach(); } 00079 inline bool isDetached() const { return q_hash.isDetached(); } 00080 inline void setSharable(bool sharable) { q_hash.setSharable(sharable); } 00081 00082 inline void clear() { q_hash.clear(); } 00083 00084 inline bool remove(const T &value) { return q_hash.remove(value) != 0; } 00085 00086 inline bool contains(const T &value) const { return q_hash.contains(value); } 00087 00088 bool contains(const QSet<T> &set) const; 00089 00090 class const_iterator; 00091 00092 class iterator 00093 { 00094 typedef QHash<T, QHashDummyValue> Hash; 00095 typename Hash::iterator i; 00096 friend class const_iterator; 00097 00098 public: 00099 typedef std::bidirectional_iterator_tag iterator_category; 00100 typedef qptrdiff difference_type; 00101 typedef T value_type; 00102 typedef const T *pointer; 00103 typedef const T &reference; 00104 00105 inline iterator() {} 00106 inline iterator(typename Hash::iterator o) : i(o) {} 00107 inline iterator(const iterator &o) : i(o.i) {} 00108 inline iterator &operator=(const iterator &o) { i = o.i; return *this; } 00109 inline const T &operator*() const { return i.key(); } 00110 inline const T *operator->() const { return &i.key(); } 00111 inline bool operator==(const iterator &o) const { return i == o.i; } 00112 inline bool operator!=(const iterator &o) const { return i != o.i; } 00113 inline bool operator==(const const_iterator &o) const 00114 { return i == o.i; } 00115 inline bool operator!=(const const_iterator &o) const 00116 { return i != o.i; } 00117 inline iterator &operator++() { ++i; return *this; } 00118 inline iterator operator++(int) { iterator r = *this; ++i; return r; } 00119 inline iterator &operator--() { --i; return *this; } 00120 inline iterator operator--(int) { iterator r = *this; --i; return r; } 00121 inline iterator operator+(int j) const { return i + j; } 00122 inline iterator operator-(int j) const { return i - j; } 00123 inline iterator &operator+=(int j) { i += j; return *this; } 00124 inline iterator &operator-=(int j) { i -= j; return *this; } 00125 }; 00126 00127 class const_iterator 00128 { 00129 typedef QHash<T, QHashDummyValue> Hash; 00130 typename Hash::const_iterator i; 00131 friend class iterator; 00132 00133 public: 00134 typedef std::bidirectional_iterator_tag iterator_category; 00135 typedef qptrdiff difference_type; 00136 typedef T value_type; 00137 typedef const T *pointer; 00138 typedef const T &reference; 00139 00140 inline const_iterator() {} 00141 inline const_iterator(typename Hash::const_iterator o) : i(o) {} 00142 inline const_iterator(const const_iterator &o) : i(o.i) {} 00143 inline const_iterator(const iterator &o) 00144 : i(o.i) {} 00145 inline const_iterator &operator=(const const_iterator &o) { i = o.i; return *this; } 00146 inline const T &operator*() const { return i.key(); } 00147 inline const T *operator->() const { return &i.key(); } 00148 inline bool operator==(const const_iterator &o) const { return i == o.i; } 00149 inline bool operator!=(const const_iterator &o) const { return i != o.i; } 00150 inline const_iterator &operator++() { ++i; return *this; } 00151 inline const_iterator operator++(int) { const_iterator r = *this; ++i; return r; } 00152 inline const_iterator &operator--() { --i; return *this; } 00153 inline const_iterator operator--(int) { const_iterator r = *this; --i; return r; } 00154 inline const_iterator operator+(int j) const { return i + j; } 00155 inline const_iterator operator-(int j) const { return i - j; } 00156 inline const_iterator &operator+=(int j) { i += j; return *this; } 00157 inline const_iterator &operator-=(int j) { i -= j; return *this; } 00158 }; 00159 00160 // STL style 00161 inline iterator begin() { return q_hash.begin(); } 00162 inline const_iterator begin() const { return q_hash.begin(); } 00163 inline const_iterator constBegin() const { return q_hash.constBegin(); } 00164 inline iterator end() { return q_hash.end(); } 00165 inline const_iterator end() const { return q_hash.end(); } 00166 inline const_iterator constEnd() const { return q_hash.constEnd(); } 00167 iterator erase(iterator i) 00168 { return q_hash.erase(reinterpret_cast<typename Hash::iterator &>(i)); } 00169 00170 // more Qt 00171 typedef iterator Iterator; 00172 typedef const_iterator ConstIterator; 00173 inline int count() const { return q_hash.count(); } 00174 inline const_iterator insert(const T &value) // ### Qt 5: should return an 'iterator' 00175 { return static_cast<typename Hash::const_iterator>(q_hash.insert(value, 00176 QHashDummyValue())); } 00177 iterator find(const T &value) { return q_hash.find(value); } 00178 const_iterator find(const T &value) const { return q_hash.find(value); } 00179 inline const_iterator constFind(const T &value) const { return find(value); } 00180 QSet<T> &unite(const QSet<T> &other); 00181 QSet<T> &intersect(const QSet<T> &other); 00182 QSet<T> &subtract(const QSet<T> &other); 00183 00184 // STL compatibility 00185 typedef T key_type; 00186 typedef T value_type; 00187 typedef value_type *pointer; 00188 typedef const value_type *const_pointer; 00189 typedef value_type &reference; 00190 typedef const value_type &const_reference; 00191 typedef qptrdiff difference_type; 00192 typedef int size_type; 00193 00194 inline bool empty() const { return isEmpty(); } 00195 // comfort 00196 inline QSet<T> &operator<<(const T &value) { insert(value); return *this; } 00197 inline QSet<T> &operator|=(const QSet<T> &other) { unite(other); return *this; } 00198 inline QSet<T> &operator|=(const T &value) { insert(value); return *this; } 00199 inline QSet<T> &operator&=(const QSet<T> &other) { intersect(other); return *this; } 00200 inline QSet<T> &operator&=(const T &value) 00201 { QSet<T> result; if (contains(value)) result.insert(value); return (*this = result); } 00202 inline QSet<T> &operator+=(const QSet<T> &other) { unite(other); return *this; } 00203 inline QSet<T> &operator+=(const T &value) { insert(value); return *this; } 00204 inline QSet<T> &operator-=(const QSet<T> &other) { subtract(other); return *this; } 00205 inline QSet<T> &operator-=(const T &value) { remove(value); return *this; } 00206 inline QSet<T> operator|(const QSet<T> &other) const 00207 { QSet<T> result = *this; result |= other; return result; } 00208 inline QSet<T> operator&(const QSet<T> &other) const 00209 { QSet<T> result = *this; result &= other; return result; } 00210 inline QSet<T> operator+(const QSet<T> &other) const 00211 { QSet<T> result = *this; result += other; return result; } 00212 inline QSet<T> operator-(const QSet<T> &other) const 00213 { QSet<T> result = *this; result -= other; return result; } 00214 #if QT_VERSION < 0x050000 00215 // ### Qt 5: remove 00216 inline QSet<T> operator|(const QSet<T> &other) 00217 { QSet<T> result = *this; result |= other; return result; } 00218 inline QSet<T> operator&(const QSet<T> &other) 00219 { QSet<T> result = *this; result &= other; return result; } 00220 inline QSet<T> operator+(const QSet<T> &other) 00221 { QSet<T> result = *this; result += other; return result; } 00222 inline QSet<T> operator-(const QSet<T> &other) 00223 { QSet<T> result = *this; result -= other; return result; } 00224 #endif 00225 00226 QList<T> toList() const; 00227 inline QList<T> values() const { return toList(); } 00228 00229 static QSet<T> fromList(const QList<T> &list); 00230 00231 private: 00232 Hash q_hash; 00233 }; 00234 00235 template <class T> 00236 Q_INLINE_TEMPLATE void QSet<T>::reserve(int asize) { q_hash.reserve(asize); } 00237 00238 template <class T> 00239 Q_INLINE_TEMPLATE QSet<T> &QSet<T>::unite(const QSet<T> &other) 00240 { 00241 QSet<T> copy(other); 00242 typename QSet<T>::const_iterator i = copy.constEnd(); 00243 while (i != copy.constBegin()) { 00244 --i; 00245 insert(*i); 00246 } 00247 return *this; 00248 } 00249 00250 template <class T> 00251 Q_INLINE_TEMPLATE QSet<T> &QSet<T>::intersect(const QSet<T> &other) 00252 { 00253 QSet<T> copy1(*this); 00254 QSet<T> copy2(other); 00255 typename QSet<T>::const_iterator i = copy1.constEnd(); 00256 while (i != copy1.constBegin()) { 00257 --i; 00258 if (!copy2.contains(*i)) 00259 remove(*i); 00260 } 00261 return *this; 00262 } 00263 00264 template <class T> 00265 Q_INLINE_TEMPLATE QSet<T> &QSet<T>::subtract(const QSet<T> &other) 00266 { 00267 QSet<T> copy1(*this); 00268 QSet<T> copy2(other); 00269 typename QSet<T>::const_iterator i = copy1.constEnd(); 00270 while (i != copy1.constBegin()) { 00271 --i; 00272 if (copy2.contains(*i)) 00273 remove(*i); 00274 } 00275 return *this; 00276 } 00277 00278 template <class T> 00279 Q_INLINE_TEMPLATE bool QSet<T>::contains(const QSet<T> &other) const 00280 { 00281 typename QSet<T>::const_iterator i = other.constBegin(); 00282 while (i != other.constEnd()) { 00283 if (!contains(*i)) 00284 return false; 00285 ++i; 00286 } 00287 return true; 00288 } 00289 00290 template <typename T> 00291 Q_OUTOFLINE_TEMPLATE QList<T> QSet<T>::toList() const 00292 { 00293 QList<T> result; 00294 result.reserve(size()); 00295 typename QSet<T>::const_iterator i = constBegin(); 00296 while (i != constEnd()) { 00297 result.append(*i); 00298 ++i; 00299 } 00300 return result; 00301 } 00302 00303 template <typename T> 00304 Q_OUTOFLINE_TEMPLATE QSet<T> QList<T>::toSet() const 00305 { 00306 QSet<T> result; 00307 result.reserve(size()); 00308 for (int i = 0; i < size(); ++i) 00309 result.insert(at(i)); 00310 return result; 00311 } 00312 00313 template <typename T> 00314 QSet<T> QSet<T>::fromList(const QList<T> &list) 00315 { 00316 return list.toSet(); 00317 } 00318 00319 template <typename T> 00320 QList<T> QList<T>::fromSet(const QSet<T> &set) 00321 { 00322 return set.toList(); 00323 } 00324 00325 Q_DECLARE_SEQUENTIAL_ITERATOR(Set) 00326 00327 template <typename T> 00328 class QMutableSetIterator 00329 { 00330 typedef typename QSet<T>::iterator iterator; 00331 QSet<T> *c; 00332 iterator i, n; 00333 inline bool item_exists() const { return n != c->constEnd(); } 00334 00335 public: 00336 inline QMutableSetIterator(QSet<T> &container) 00337 : c(&container) 00338 { c->setSharable(false); i = c->begin(); n = c->end(); } 00339 inline ~QMutableSetIterator() 00340 { c->setSharable(true); } 00341 inline QMutableSetIterator &operator=(QSet<T> &container) 00342 { c->setSharable(true); c = &container; c->setSharable(false); 00343 i = c->begin(); n = c->end(); return *this; } 00344 inline void toFront() { i = c->begin(); n = c->end(); } 00345 inline void toBack() { i = c->end(); n = i; } 00346 inline bool hasNext() const { return c->constEnd() != i; } 00347 inline const T &next() { n = i++; return *n; } 00348 inline const T &peekNext() const { return *i; } 00349 inline bool hasPrevious() const { return c->constBegin() != i; } 00350 inline const T &previous() { n = --i; return *n; } 00351 inline const T &peekPrevious() const { iterator p = i; return *--p; } 00352 inline void remove() 00353 { if (c->constEnd() != n) { i = c->erase(n); n = c->end(); } } 00354 inline const T &value() const { Q_ASSERT(item_exists()); return *n; } 00355 inline bool findNext(const T &t) 00356 { while (c->constEnd() != (n = i)) if (*i++ == t) return true; return false; } 00357 inline bool findPrevious(const T &t) 00358 { while (c->constBegin() != i) if (*(n = --i) == t) return true; 00359 n = c->end(); return false; } 00360 }; 00361 00362 QT_END_NAMESPACE 00363 00364 QT_END_HEADER 00365 00366 #endif // QSET_H